主页 > 软件开发  > 

SpringBoot+redisTemplate实现redis数据库迁移、键名修改

SpringBoot+redisTemplate实现redis数据库迁移、键名修改

目录 1.项目依赖2.动态创建 RedisTemplate实例3.创建Redis操作服务类4.创建控制器5.测试 在 Spring Boot 项目中使用RedisTemplate实现: Redis 数据库迁移,本质上就是将一个 Redis 数据库中的数据复制到另一个 Redis 数据库中。 Redis 修改键名,实际上 Redis 并没有直接提供修改键名的方法,但可以通过先复制原键的值到新键,然后删除原键的方式来间接实现键的修改

以下是详细的实现步骤:

1.项目依赖

首先,确保你的 Spring Boot 项目中已经添加了 Spring Data Redis 依赖。

在pom.xml中添加以下依赖:

<!--redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.4.6</version> </dependency> 2.动态创建 RedisTemplate实例

创建一个工具类,用于根据传入的数据库配置信息动态创建 RedisTemplate 实例。

package com.example.redisdemo.utils; import io.micrometer mon.util.StringUtils; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.stereotype.Component; /** * redis工具类:根据传入的数据库配置信息动态创建 RedisTemplate 实例 * @author qzz * @date 2025/3/4 */ @Component public class RedisTemplateFactory { private String REDIS_HOST = "localhost"; private Integer REDIS_PORT = 6379; private String REDIS_PASSWORD = ""; /** * 根据传入的数据库配置信息动态创建 RedisTemplate 实例 * @param database * @return */ public RedisTemplate<String, Object> createRedisTemplate(int database) { return createRedisTemplate(REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, database); } /** * 根据传入的数据库配置信息动态创建 RedisTemplate 实例 * @param host * @param port * @param password * @param database * @return */ public RedisTemplate<String, Object> createRedisTemplate(String host, int port, String password, int database) { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName(host); config.setPort(port); if(StringUtils.isNotEmpty(password)){ config.setPassword(password); } config.setDatabase(database); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config); connectionFactory.afterPropertiesSet(); RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 设置键的序列化器 template.setKeySerializer(new StringRedisSerializer()); // 设置值的序列化器 template.setValueSerializer(new StringRedisSerializer()); // 设置哈希键的序列化器 template.setHashKeySerializer(new StringRedisSerializer()); // 设置哈希值的序列化器 template.setHashValueSerializer(new StringRedisSerializer()); template.afterPropertiesSet(); return template; } } 3.创建Redis操作服务类 package com.example.redisdemo.service.impl; import com.example.redisdemo.model.ResultJson; import com.example.redisdemo.request.RedisDBRequestJson; import com.example.redisdemo.request.RedisKeyRequestJson; import com.example.redisdemo.service.IRedisOperationService; import com.example.redisdemo.utils.RedisTemplateFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * redis 迁移数据库、修改键名操作 * @author qzz * @date 2025/3/3 */ @Slf4j @Service public class RedisOperationServiceImpl implements IRedisOperationService { @Autowired private RedisTemplateFactory redisTemplateFactory; /** * redis数据库迁移 --- 数据库只动态修改 database * @param redisDBRequestJson * @return */ @Override @Transactional(rollbackFor = Exception.class) public ResultJson transferRedisDB(RedisDBRequestJson redisDBRequestJson) { try { //redis源数据库 RedisTemplate<String, Object> sourceRedisTemplate = redisTemplateFactory.createRedisTemplate(redisDBRequestJson.getSourceDatabase()); //redis目标数据库 RedisTemplate<String, Object> targetRedisTemplate = redisTemplateFactory.createRedisTemplate(redisDBRequestJson.getTargetDatabase()); // 获取源数据库中的所有键 Set<String> keys = sourceRedisTemplate.keys("*"); if (keys != null) { for (String key : keys) { //复制键及其值 到 目标RedisTemplate copyKey(key, sourceRedisTemplate, targetRedisTemplate); } } }catch (Exception e){ log.error("Redis数据库迁移失败", e); return ResultJson.fail(500,"Redis数据库迁移失败"); } return ResultJson.success(); } /** * 复制键及其值 到 目标RedisTemplate * @param sourceKey 源键 * @param sourceRedisTemplate 源RedisTemplate * @param targetRedisTemplate 目标RedisTemplate */ private static void copyKey(String sourceKey, RedisTemplate<String, Object> sourceRedisTemplate, RedisTemplate<String, Object> targetRedisTemplate) { copyKey(sourceKey, sourceKey, sourceRedisTemplate, targetRedisTemplate); } /** * 复制键及其值 到 目标RedisTemplate,并可以指定目标键名 * @param sourceKey 源键 * @param targetKey 目标键 * @param sourceRedisTemplate 源RedisTemplate * @param targetRedisTemplate 目标RedisTemplate */ private static void copyKey(String sourceKey, String targetKey, RedisTemplate<String, Object> sourceRedisTemplate, RedisTemplate<String, Object> targetRedisTemplate) { // 获取键的类型 String type = sourceRedisTemplate.type(sourceKey).code(); switch (type){ case "string": //处理字符串类型的值 String value = (String) sourceRedisTemplate.opsForValue().get(sourceKey); targetRedisTemplate.opsForValue().set(targetKey, value); break; case "list": Long listSize = sourceRedisTemplate.opsForList().size(sourceKey); for (int i = 0; i < listSize; i++) { String listValue = (String) sourceRedisTemplate.opsForList().index(sourceKey, i); targetRedisTemplate.opsForList().rightPush(targetKey, listValue); } break; case "set": // 处理集合类型的数据 Set<Object> setMembers = sourceRedisTemplate.opsForSet().members(sourceKey); if (setMembers != null) { for (Object member : setMembers) { targetRedisTemplate.opsForSet().add(targetKey, member); } } break; case "zset": // 处理有序集合类型的数据 Set<Object> zsetMembers = sourceRedisTemplate.opsForZSet().range(sourceKey, 0, -1); if (zsetMembers != null) { for (Object member : zsetMembers) { Double score = sourceRedisTemplate.opsForZSet().score(sourceKey, member); targetRedisTemplate.opsForZSet().add(targetKey, member, score); } } break; case "hash": // 处理哈希类型的数据 Map<Object, Object> hashEntries = sourceRedisTemplate.opsForHash().entries(sourceKey); if (!hashEntries.isEmpty()) { targetRedisTemplate.opsForHash().putAll(targetKey, hashEntries); } break; default: System.out.println("Unsupported data type: " + type); } } /** * redis 修改键名: 实现 Redis 键的修改,实际上 Redis 并没有直接提供修改键名的方法,但可以通过先复制原键的值到新键,然后删除原键的方式来间接实现键的修改 * @param redisDBRequestJson * @return */ @Override @Transactional(rollbackFor = Exception.class) public ResultJson updateRedisKey(RedisDBRequestJson redisDBRequestJson) { try { //redis目标数据库 RedisTemplate<String, Object> targetRedisTemplate = redisTemplateFactory.createRedisTemplate(redisDBRequestJson.getTargetDatabase()); //遍历key列表 for (RedisKeyRequestJson redisKey : redisDBRequestJson.getRedisKeyList()) { if (targetRedisTemplate.hasKey(redisKey.getSourceKey())) { String sourceKey = redisKey.getSourceKey(); String targetKey = redisKey.getTargetKey(); //1.复制键及其值 到新键 copyKey(sourceKey, targetKey, targetRedisTemplate, targetRedisTemplate); //2.获取原键的过期时间 Long expire = targetRedisTemplate.getExpire(sourceKey, TimeUnit.SECONDS); if (expire != null && expire > 0) { // 设置新键的过期时间 targetRedisTemplate.expire(targetKey, expire, TimeUnit.SECONDS); } //3.删除原键 targetRedisTemplate.delete(sourceKey); } } }catch (Exception e){ log.error("Redis 修改键名失败", e); return ResultJson.fail(500,"Redis 修改键名失败"); } return ResultJson.success(); } /** * redis数据库迁移 --- 数据库动态修改 host、password、database * @param requestJson * @return */ @Override @Transactional(rollbackFor = Exception.class) public ResultJson transferRedisDBByDynamics(RedisDBRequestJson requestJson) { try { //redis源数据库 RedisTemplate<String, Object> sourceRedisTemplate = redisTemplateFactory.createRedisTemplate(requestJson.getSourceHost(), requestJson.getSourcePort(), requestJson.getSourcePassword(), requestJson.getSourceDatabase()); //redis目标数据库 RedisTemplate<String, Object> targetRedisTemplate = redisTemplateFactory.createRedisTemplate(requestJson.getTargetHost(), requestJson.getTargetPort(), requestJson.getTargetPassword(), requestJson.getTargetDatabase()); // 获取源数据库中的所有键 Set<String> keys = sourceRedisTemplate.keys("*"); if (keys != null) { for (String key : keys) { //复制键及其值 到 目标RedisTemplate copyKey(key, sourceRedisTemplate, targetRedisTemplate); } } }catch (Exception e){ log.error("Redis数据库迁移失败", e); return ResultJson.fail(500,"Redis数据库迁移失败"); } return ResultJson.success(); } } 4.创建控制器

创建一个控制器类,用于接收客户端传递的数据库配置信息,并进行数据迁移、修改键名的操作。

package com.example.redisdemo.controller; import com.example.redisdemo.model.ResultJson; import com.example.redisdemo.request.RedisDBRequestJson; import com.example.redisdemo.service.IRedisOperationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** * redis 迁移数据库、修改键名操作 * @author qzz * @date 2025/3/3 */ @RestController public class RedisController { @Autowired private IRedisOperationService operationService; /** * redis数据库迁移 --- 数据库只动态修改 database * @return */ @PostMapping("/api/{version}/redis-migration/") public ResultJson transferRedisDB(@RequestBody RedisDBRequestJson redisDBRequestJson) { return operationService.transferRedisDB(redisDBRequestJson); } /** * redis 修改键名 * @return */ @PostMapping("/api/{version}/redis/rename-key/") public ResultJson updateRedisKey(@RequestBody RedisDBRequestJson redisDBRequestJson) { return operationService.updateRedisKey(redisDBRequestJson); } /** * redis数据库迁移 --- 数据库动态修改 host、password、database * @return */ @PostMapping("/api/{version}/redis-migration/dynamics/") public ResultJson transferRedisDBByDynamics(@RequestBody RedisDBRequestJson redisDBRequestJson) { return operationService.transferRedisDBByDynamics(redisDBRequestJson); } } 5.测试

启动 Spring Boot 应用后,可以通过以下 URL 发起请求进行数据迁移: 修改键名:

标签:

SpringBoot+redisTemplate实现redis数据库迁移、键名修改由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“SpringBoot+redisTemplate实现redis数据库迁移、键名修改