SpringBoot整合Redis集群

曾经终败给现在 2022-05-12 08:54 338阅读 0赞

目的

使用SpringBoot 1.5.8.RELEASE版本整合Redis 4.0.11,实现Redis Pool操作Redis集群

引入依赖

  1. <!--属性配置支持-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-configuration-processor</artifactId>
  5. <optional>true</optional>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
  8. <!--redis依赖-->
  9. <!--默认继承lettuce,切换成jedis需要排除依赖-->
  10. <dependency>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-starter-data-redis</artifactId>
  13. <exclusions>
  14. <exclusion>
  15. <groupId>io.lettuce</groupId>
  16. <artifactId>lettuce-core</artifactId>
  17. </exclusion>
  18. </exclusions>
  19. </dependency>
  20. <!--redis 客户端-->
  21. <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
  22. <dependency>
  23. <groupId>redis.clients</groupId>
  24. <artifactId>jedis</artifactId>
  25. </dependency>

SpringBoot默认使用lettcuce作为redis客户端,在这里我们使用jedis替换lettcuce所以需要排除lettcuce依赖。

配置连接参数

Spring Data Redis 在1.7版本开始支持Redis的集群,如果非1.7版本,需要自己实现Redis集群的支持。使内置的Redis集群支持,需要Redis服务版本在3.0+

首先建立一个配置文件redis.properties来存放redis集群配置参数:

  1. spring.redis.cluster.nodes=192.168.2.222:7000,192.168.2.222:7001,192.168.2.222:7002,192.168.2.222:7003,192.168.2.222:7004
  2. spring.redis.cluster.max-redirects=2
  3. spring.redis.cluster.timeout=5000
  4. spring.redis.cluster.max-attempts=3
  • nodes 代表redis多个节点的ip与端口号,多个节点需要使用“,”隔开。
  • max-redirects 最大的要重定向的次数(由于集群中数据存储在多个节点所以,在访问数据时需要通过节点进行转发)
  • timeout 连接超时的时间
  • max-attempts 最大的连接重试次数

编写RedisClusterProperty.JAVA

用于获取配置文件中的属性值,在Redis实力工厂提供配置参数:

  1. package com.example.userservice.config.redis;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import org.springframework.context.annotation.PropertySource;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.validation.annotation.Validated;
  7. import java.util.List;
  8. /**
  9. * redis 集群配置属性
  10. */
  11. @Component
  12. @Validated
  13. @Data
  14. @ConfigurationProperties(value = "spring.redis.cluster")
  15. @PropertySource(value = "classpath:jedis.properties")
  16. public class RedisClusterProperty {
  17. /**
  18. * 集群节点的主机名
  19. * spring.redis.cluster.nodes[0] = 127.0.0.1:7379
  20. * spring.redis.cluster.nodes[1] = 127.0.0.1:7380
  21. */
  22. private List<String> nodes;
  23. /**
  24. * 获取连接的超时时间
  25. */
  26. private Integer timeout;
  27. /**
  28. * 最大连接尝试次数
  29. */
  30. private Integer maxAttempts;
  31. }

编写JedisClusterConfig.JAVA

配置Redis实例的工厂,将RedisClusterProperty中的参数注入进去:

  1. package com.example.userservice.config.redis;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.context.annotation.Primary;
  8. import org.springframework.data.redis.connection.RedisClusterConfiguration;
  9. import org.springframework.data.redis.connection.RedisConnectionFactory;
  10. import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
  11. import org.springframework.stereotype.Component;
  12. /**
  13. * redis集群必须redis 3.0以上版本的支持
  14. * redis集群
  15. */
  16. @Configuration
  17. @Component
  18. public class JedisClusterConfig {
  19. private static final Logger LOGGER = LoggerFactory.getLogger(JedisClusterConfig.class);
  20. @Autowired
  21. private RedisClusterProperty redisClusterProperty;
  22. /**
  23. * Spring Data Redis 1.7 支持redis集群
  24. * jedis集群配置
  25. *
  26. * @return
  27. */
  28. @Bean
  29. @Primary
  30. public RedisConnectionFactory connectionFactory() {
  31. RedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory(
  32. new RedisClusterConfiguration(redisClusterProperty.getNodes()));
  33. return redisConnectionFactory;
  34. }
  35. // @Bean
  36. // public JedisCluster getJedisCluster() {
  37. // List<String> servers = redisClusterProperty.getNodes();
  38. // Set<HostAndPort> nodes = new HashSet<>();
  39. // Integer port = null;
  40. // try {
  41. // for (String server : servers) {
  42. // String[] ipPortPair = server.split(":");
  43. // port = Integer.parseInt(ipPortPair[1]);
  44. // nodes.add(new HostAndPort(ipPortPair[0], port));
  45. // }
  46. // } catch (NumberFormatException e) {
  47. // LOGGER.error("paser port :{} error", port);
  48. // }
  49. // JedisCluster jedisCluster = new JedisCluster(nodes, redisClusterProperty.getTimeout(), redisClusterProperty.getMaxAttempts());
  50. // return jedisCluster;
  51. // }
  52. }

自定义RedisTemplate

SpringData提供的RedisTemplate只支持基本类型的操作,不能处理对象的存储。为了方便对象的操作,我们需要自定义一个RedisTemplate来操作对象。

编写RedisObjectSerializer.JAVA

处理对象的序列化

  1. package com.example.userservice.config.redis;
  2. import org.springframework.core.convert.converter.Converter;
  3. import org.springframework.core.serializer.support.DeserializingConverter;
  4. import org.springframework.core.serializer.support.SerializingConverter;
  5. import org.springframework.data.redis.serializer.RedisSerializer;
  6. import org.springframework.data.redis.serializer.SerializationException;
  7. /**
  8. * redis默认不支持对象的序列化,需要自定义序列化对象
  9. * redisTemplate序列化支持类
  10. */
  11. public class RedisObjectSerializer implements RedisSerializer<Object> {
  12. private Converter<Object, byte[]> serilazier = new SerializingConverter();
  13. private Converter<byte[], Object> deserilazier = new DeserializingConverter();
  14. private static final byte[] EMPTY_ARRAY = new byte[0];
  15. /**
  16. * 将对象序列化为字节数字,序列化失败返回空数组
  17. *
  18. * @param o
  19. * @return
  20. * @throws SerializationException
  21. */
  22. @Override
  23. public byte[] serialize(Object o) throws SerializationException {
  24. if (null == o) {
  25. return EMPTY_ARRAY;
  26. }
  27. try {
  28. return serilazier.convert(o);
  29. } catch (Exception e) {
  30. return EMPTY_ARRAY;
  31. }
  32. }
  33. /**
  34. * 将字节数组反列化成对象,序列化失败返回null
  35. *
  36. * @param bytes
  37. * @return
  38. * @throws SerializationException
  39. */
  40. @Override
  41. public Object deserialize(byte[] bytes) throws SerializationException {
  42. if (isEmpty(bytes)) {
  43. return null;
  44. }
  45. try {
  46. return deserilazier.convert(bytes);
  47. } catch (Exception e) {
  48. return null;
  49. }
  50. }
  51. /**
  52. * 判断字符数字是否为空
  53. *
  54. * @param data
  55. * @return
  56. */
  57. private boolean isEmpty(byte[] data) {
  58. return data == null || data.length == 0;
  59. }
  60. }

编写RedisTemplateConfig.JAVA

配置RedisTemplate,为其支持对象的操作

  1. package com.example.userservice.config.redis;
  2. import com.example.userservice.entity.User;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.data.redis.connection.RedisConnectionFactory;
  6. import org.springframework.data.redis.core.RedisTemplate;
  7. import org.springframework.data.redis.serializer.StringRedisSerializer;
  8. /**
  9. * RedisTemplate配置类
  10. * 使redis支持插入对象
  11. *
  12. */
  13. @Configuration
  14. public class RedisTemplateConfig {
  15. /**
  16. * 自定义RedisTemplate bean对象
  17. * @param factory
  18. * @return
  19. */
  20. @Bean
  21. public RedisTemplate<String, User> redisTemplate(RedisConnectionFactory factory) {
  22. RedisTemplate<String, User> redisTemplate = new RedisTemplate<>();
  23. redisTemplate.setConnectionFactory(factory);
  24. redisTemplate.setKeySerializer(new StringRedisSerializer());
  25. redisTemplate.setValueSerializer(new RedisObjectSerializer());
  26. return redisTemplate;
  27. }
  28. }

Junit测试

  1. @Autowired
  2. RedisTemplate<String, User> redisTemplate;
  3. @Test
  4. public void testRedisCluster(){
  5. User u = new User("001","xiaoming",10);
  6. redisTemplate.opsForValue().set("xiaoming",u);
  7. // System.out.println(redisTemplate.opsForValue().get("xiaoming"));
  8. Assert.assertEquals(10,redisTemplate.opsForValue().get("xiaoming" +
  9. "" +
  10. "").getAge().intValue());
  11. }

成功通过测试,结果如下:

70

注意:!

实体类实现Serializable接口,启动redis集群的时候,不要使用127.0.0.1或者localhost,而要使用本地的IP地址。

发表评论

表情:
评论列表 (有 0 条评论,338人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringBoot整合redis

    一:缓存的应用场景 1:什么是缓存? 在互联网场景下,尤其 2C 端大流量场景下,需要将一些经常展现和不会频繁变更的数据,存放在存取速率更快的地方。缓存就是一个存储器,在技

    相关 springboot整合redis

    一、redis集群原理 redis集群中的所有节点彼此互联,节点内部采用二进制协议优化传输速度和带宽,每个节点都可以与Java客户端连接。redis集群的数据分配采用哈希