Spring Boot 3 配置 Redis 兼容单例和集群

瑞星  金牌会员 | 2024-10-9 20:28:24 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 859|帖子 859|积分 2577

配置项

Spring Boot 3.x 的 redis 配置和 Spring Boot 2.x 是不一样的, 路径多了一个data
  1. spring:
  2.   ...
  3.   data:
  4.     redis:
  5.       host: @redis.host@
  6.       port: @redis.port@
  7.       password: @redis.password@
  8.       database: @redis.database@
复制代码
兼容单例和集群的配置

开发时一般用一个Redis单例就足够, 测试和生产环境再换成集群, 但是在application.yml中默认的 Redis 单例和集群配置格式是不同的, 如果要用同一套格式兼容两种配置, 需要自定义 RedisConnectionFactory 这个bean的初始化.
  1. @Configuration
  2. public class RedisConfig {
  3.     @Value("${spring.data.redis.host}")
  4.     public String host;
  5.     @Value("${spring.data.redis.port}")
  6.     public int port;
  7.     @Value("${spring.data.redis.password}")
  8.     public String password;
  9.     @Value("${spring.data.redis.database}")
  10.     public int database;
  11.     @Bean
  12.     public RedisTemplate<String, String> redisStringTemplate(RedisConnectionFactory redisConnectionFactory) {
  13.         RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
  14.         redisTemplate.setConnectionFactory(redisConnectionFactory);
  15.         redisTemplate.setDefaultSerializer(new StringRedisSerializer());
  16.         return redisTemplate;
  17.     }
  18.     @Bean
  19.     public RedisTemplate<String, byte[]> redisBytesTemplate(RedisConnectionFactory redisConnectionFactory) {
  20.         RedisTemplate<String, byte[]> redisTemplate = new RedisTemplate<>();
  21.         redisTemplate.setConnectionFactory(redisConnectionFactory);
  22.         RedisSerializer<String> redisKeySerializer = new StringRedisSerializer();
  23.         redisTemplate.setKeySerializer(redisKeySerializer);
  24.         redisTemplate.setHashKeySerializer(redisKeySerializer);
  25.         redisTemplate.setValueSerializer(RedisSerializer.byteArray());
  26.         redisTemplate.setHashValueSerializer(RedisSerializer.byteArray());
  27.         return redisTemplate;
  28.     }
  29.     @Bean
  30.     public RedisConnectionFactory lettuceConnectionFactory() {
  31.         if (host.contains(",")) {
  32.             RedisClusterConfiguration config = new RedisClusterConfiguration(Arrays.asList(host.split(",")));
  33.             config.setMaxRedirects(3);
  34.             if (password != null && !password.isEmpty()) {
  35.                 config.setPassword(RedisPassword.of(password));
  36.             }
  37.             LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
  38.             factory.afterPropertiesSet();
  39.             return factory;
  40.         } else {
  41.             RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
  42.             config.setHostName(host);
  43.             config.setPort(port);
  44.             config.setDatabase(database);
  45.             if (password != null && !password.isEmpty()) {
  46.                 config.setPassword(RedisPassword.of(password));
  47.             }
  48.             LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
  49.             factory.afterPropertiesSet();
  50.             return factory;
  51.         }
  52.     }
  53. }
复制代码
如许, 当配置改为集群时, 只需要修改 spring.data.redis.host 的内容为 1.1.1.1:6379,1.1.1.2:6379,1.1.1.3:6379如许的格式就可以了.
使用 Byte 作为值存储

ByteUtil.java
  1. public class ByteUtil {
  2.     public static byte[] toByte(String str) {
  3.         if (str == null) return null;
  4.         return str.getBytes();
  5.     }
  6.     public static byte[][] toByte(String[] strs) {
  7.         if (strs == null) return null;
  8.         byte[][] arr = new byte[strs.length][];
  9.         for (int i = 0; i < strs.length; i++) {
  10.             arr[i] = strs[i].getBytes();
  11.         }
  12.         return arr;
  13.     }
  14.     public static String toString(byte[] bytes) {
  15.         return bytes == null ? null : new String(bytes);
  16.     }
  17.     public static Set<String> toString(Set<byte[]> byteset) {
  18.         if (byteset == null) return null;
  19.         return byteset.stream()
  20.                 .map(String::new)
  21.                 .collect(Collectors.toSet());
  22.     }
  23.     public static List<String> toStrings(List<byte[]> byteslist) {
  24.         if (byteslist == null) return null;
  25.         return byteslist.stream()
  26.                 .map(String::new)
  27.                 .collect(Collectors.toList());
  28.     }
  29.     public static byte[] toByte(int x) {
  30.         ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
  31.         buffer.putInt(x);
  32.         return buffer.array();
  33.     }
  34.     public static int toInteger(byte[] bytes) {
  35.         ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
  36.         buffer.put(bytes);
  37.         buffer.flip();//need flip
  38.         return buffer.getInt();
  39.     }
  40.     public static byte[] toByte(long x) {
  41.         ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
  42.         buffer.putLong(x);
  43.         return buffer.array();
  44.     }
  45.     public static long toLong(byte[] bytes) {
  46.         ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
  47.         buffer.put(bytes);
  48.         buffer.flip();//need flip
  49.         return buffer.getLong();
  50.     }
  51.     public static byte[] toByte(Object object) {
  52.         if (object == null) return null;
  53.         try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
  54.              ObjectOutputStream oos = new ObjectOutputStream(baos)) {
  55.             oos.writeObject(object);
  56.             return baos.toByteArray();
  57.         } catch (IOException e) {
  58.             throw new RuntimeException(e);
  59.         }
  60.     }
  61.     public static <T> List<T> toObjs(List<byte[]> byteslist) {
  62.         if (byteslist == null) return null;
  63.         List<T> list = new ArrayList<>();
  64.         for (byte[] bytes : byteslist) {
  65.             T t = toObj(bytes);
  66.             list.add(t);
  67.         }
  68.         return list;
  69.     }
  70.     @SuppressWarnings("unchecked")
  71.     public static <T> T toObj(byte[] bytes) {
  72.         if (bytes == null || bytes.length < 8) return null;
  73.         try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
  74.              ObjectInputStream ois = new ObjectInputStream(bais)) {
  75.             return (T)ois.readObject();
  76.         } catch (IOException|ClassNotFoundException e) {
  77.             throw new RuntimeException(e);
  78.         }
  79.     }
  80. }
复制代码
在服务中的调用方式
  1. @Autowired
  2. private RedisTemplate<String, byte[]> redisBytesTemplate;
  3. @Override
  4. public Boolean hasKey(String key) {
  5.     return redisBytesTemplate.hasKey(key);
  6. }
  7. @Override
  8. public Boolean hashHasKey(String key, String field) {
  9.     return redisBytesTemplate.opsForHash().hasKey(key,field);
  10. }
  11. @Override
  12. public Integer hashGetInt(String key, String field) {
  13.     HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();
  14.     byte[] bytes = opsForHash.get(key, field);
  15.     return bytes == null? null : ByteUtil.toInteger(bytes);
  16. }
  17. @Override
  18. public void hashSetInt(String key, String field, int value) {
  19.     HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();
  20.     opsForHash.put(key, field, ByteUtil.toByte(value));
  21. }
  22. @Override
  23. public <T> T hashGetObj(String key, String field) {
  24.     HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();
  25.     return ByteUtil.toObj(opsForHash.get(key, field));
  26. }
  27. @Override
  28. public <T> void hashSetObj(String key, String field, T value) {
  29.     HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();
  30.     opsForHash.put(key, field, ByteUtil.toByte(value));
  31. }
  32. /**
  33. * @param timeout seconds to block
  34. */
  35. @Override
  36. public <T> T bLPopObj(int timeout, String key) {
  37.     ListOperations<String, byte[]> opsForList = redisBytesTemplate.opsForList();
  38.     byte[] bytes = opsForList.leftPop(key, timeout, TimeUnit.SECONDS);
  39.     return ByteUtil.toObj(bytes);
  40. }
  41. @Override
  42. public <T> Long rPush(String key, T value) {
  43.     ListOperations<String, byte[]> opsForList = redisBytesTemplate.opsForList();
  44.     return opsForList.rightPush(key, ByteUtil.toByte(value));
  45. }
复制代码
参考


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表