社区编辑申请
注册/登录
SpringBoot 项目接入 Redis 集群
开发 项目管理 存储软件 Redis
Hello 大家好,我是鸭血粉丝,Redis 想必大家一定不会陌生,平常工作中或多或少都会用到,不管是用来存储登录信息还是用来缓存热点数据,对我们来说都是很有帮助的。

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝  。转载本文请联系Java极客技术公众号。 

Hello 大家好,我是鸭血粉丝,Redis 想必大家一定不会陌生,平常工作中或多或少都会用到,不管是用来存储登录信息还是用来缓存热点数据,对我们来说都是很有帮助的。但是 Redis 的集群估计并不是每个人都会用到,因为很多业务场景或者系统都是一些简单的管理系统,并不会需要用到 Redis 的集群环境。

阿粉之前也是这样,项目中用的的 Redis 是个单机环境,但是最近随着终端量的上升,慢慢的发现单机已经快支撑不住的,所以思考再三决定将 Redis 的环境升级成集群。下面阿粉给大家介绍一下在升级的过程中项目中需要调整的地方,这篇文章不涉及集群的搭建和配置,感兴趣的同学自行搜索。

配置参数

因为这篇文章不介绍 Redis 集群的搭建,这里我们假设已经有了一个 Redis 的集群环境,我们项目中需要调整以下几个部分

  1. 修改配置参数,集群的节点和密码配置;
  2. 确保引入的 Jedis 版本支持设置密码,spring-data-redis 1.8 以上,SpringBoot 1.5 以上才支持设置密码;
  3. 注入 RedisTemplate;
  4. 编写工具类;

修改配置参数

  1. ############### Redis 集群配置 ######################### 
  2. spring.custome.redis.cluster.nodes=172.20.0.1:7001,172.20.0.2:7002,172.20.0.3:7003 
  3. spring.custome.redis.cluster.max-redirects=3 
  4. spring.custome.redis.cluster.max-active=500 
  5. spring.custome.redis.cluster.max-wait=-1 
  6. spring.custome.redis.cluster.max-idle=500 
  7. spring.custome.redis.cluster.min-idle=20 
  8. spring.custome.redis.cluster.timeout=3000 
  9. spring.custome.redis.cluster.password=redis.cluster.password 

引入依赖(如果需要)

确保 SpringBoot 的版本大于 1.4.x 如果不是的话,采用如下配置,先排除 SpringBoot 中旧版本 Jedis 和 spring-data-redis,再依赖高版本的 Jedis 和 spring-data-redis。

  1. <dependency> 
  2.             <groupId>org.springframework.boot</groupId> 
  3.             <artifactId>spring-boot-starter-data-redis</artifactId> 
  4.             <!-- 1.4 版本 SpringBoot 中 Jedis 不支持密码登录 --> 
  5.             <exclusions> 
  6.                 <exclusion> 
  7.                     <groupId>redis.clients</groupId> 
  8.                     <artifactId>jedis</artifactId> 
  9.                 </exclusion> 
  10.                 <exclusion> 
  11.                     <groupId>org.springframework.data</groupId> 
  12.                     <artifactId>spring-data-redis</artifactId> 
  13.                 </exclusion> 
  14.             </exclusions> 
  15.         </dependency> 
  16.         <!-- 手动依赖 Jedis 和 spring-data-redis--> 
  17.         <dependency> 
  18.             <groupId>redis.clients</groupId> 
  19.             <artifactId>jedis</artifactId> 
  20.             <version>2.9.0</version> 
  21.         </dependency> 
  22.         <dependency> 
  23.             <groupId>org.springframework.data</groupId> 
  24.             <artifactId>spring-data-redis</artifactId> 
  25.             <version>1.8.0.RELEASE</version> 
  26.         </dependency> 

 

注入 RedisTemplate

注入 RedisTemplate 我们需要三个组件,分别是JedisConnectionFactory 、RedisClusterConfiguration、JedisPoolConfig,下面是注入RedisTempalte 的代码。先根据配置创建 JedisConnectFactory 同时需要配置 RedisClusterConfiguration、JedisPoolConfig,最后将JedisConnectionFactory 返回用于创建RedisTemplate

  1. import com.fasterxml.jackson.annotation.JsonAutoDetect; 
  2. import com.fasterxml.jackson.annotation.PropertyAccessor; 
  3. import com.fasterxml.jackson.databind.ObjectMapper; 
  4. import org.apache.commons.pool2.impl.GenericObjectPoolConfig; 
  5. import org.springframework.beans.factory.annotation.Value; 
  6. import org.springframework.context.annotation.Bean; 
  7. import org.springframework.context.annotation.Primary
  8. import org.springframework.data.redis.connection.RedisClusterConfiguration; 
  9. import org.springframework.data.redis.connection.RedisNode; 
  10. import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; 
  11. import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 
  12. import org.springframework.data.redis.core.RedisTemplate; 
  13. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 
  14. import org.springframework.data.redis.serializer.StringRedisSerializer; 
  15.  
  16. import java.time.Duration; 
  17. import java.util.ArrayList; 
  18. import java.util.List; 
  19.  
  20. public class RedisClusterConfig { 
  21.  
  22.     @Bean(name = "redisTemplate"
  23.     @Primary 
  24.     public RedisTemplate redisClusterTemplate(@Value("${spring.custome.redis.cluster.nodes}") String host, 
  25.                                      @Value("${spring.custome.redis.cluster.password}") String password
  26.                                      @Value("${spring.custome.redis.cluster.timeout}") long timeout, 
  27.                                      @Value("${spring.custome.redis.cluster.max-redirects}"int maxRedirect, 
  28.                                      @Value("${spring.custome.redis.cluster.max-active}"int maxActive, 
  29.                                      @Value("${spring.custome.redis.cluster.max-wait}"int maxWait, 
  30.                                      @Value("${spring.custome.redis.cluster.max-idle}"int maxIdle, 
  31.                                      @Value("${spring.custome.redis.cluster.min-idle}"int minIdle) { 
  32.  
  33.         JedisConnectionFactory connectionFactory =  jedisClusterConnectionFactory(host, password
  34.                 timeout, maxRedirect, maxActive, maxWait, maxIdle, minIdle); 
  35.         return createRedisClusterTemplate(connectionFactory); 
  36.     } 
  37.  
  38.     private JedisConnectionFactory jedisClusterConnectionFactory(String host, String password
  39.                                                                    long timeout, int maxRedirect, int maxActive, int maxWait, int maxIdle, int minIdle) { 
  40.         RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); 
  41.         List<RedisNode> nodeList = new ArrayList<>(); 
  42.         String[] cNodes = host.split(","); 
  43.         //分割出集群节点 
  44.         for (String node : cNodes) { 
  45.             String[] hp = node.split(":"); 
  46.             nodeList.add(new RedisNode(hp[0], Integer.parseInt(hp[1]))); 
  47.         } 
  48.         redisClusterConfiguration.setClusterNodes(nodeList); 
  49.         redisClusterConfiguration.setPassword(password); 
  50.         redisClusterConfiguration.setMaxRedirects(maxRedirect); 
  51.  
  52.         // 连接池通用配置 
  53.         GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); 
  54.         genericObjectPoolConfig.setMaxIdle(maxIdle); 
  55.         genericObjectPoolConfig.setMaxTotal(maxActive); 
  56.         genericObjectPoolConfig.setMinIdle(minIdle); 
  57.         genericObjectPoolConfig.setMaxWaitMillis(maxWait); 
  58.         genericObjectPoolConfig.setTestWhileIdle(true); 
  59.         genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(300000); 
  60.  
  61.         JedisClientConfiguration.DefaultJedisClientConfigurationBuilder builder = (JedisClientConfiguration.DefaultJedisClientConfigurationBuilder) JedisClientConfiguration 
  62.                 .builder(); 
  63.         builder.connectTimeout(Duration.ofSeconds(timeout)); 
  64.         builder.usePooling(); 
  65.         builder.poolConfig(genericObjectPoolConfig); 
  66.         JedisConnectionFactory connectionFactory = new JedisConnectionFactory(redisClusterConfiguration, builder.build()); 
  67.         // 连接池初始化 
  68.         connectionFactory.afterPropertiesSet(); 
  69.  
  70.         return connectionFactory; 
  71.     } 
  72.  
  73.     private RedisTemplate createRedisClusterTemplate(JedisConnectionFactory redisConnectionFactory) { 
  74.         RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); 
  75.         redisTemplate.setConnectionFactory(redisConnectionFactory); 
  76.  
  77.         Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 
  78.         ObjectMapper om = new ObjectMapper(); 
  79.         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 
  80.         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 
  81.         jackson2JsonRedisSerializer.setObjectMapper(om); 
  82.  
  83.         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 
  84.         // key采用String的序列化方式 
  85.         redisTemplate.setKeySerializer(stringRedisSerializer); 
  86.         // hash的key也采用String的序列化方式 
  87.         redisTemplate.setHashKeySerializer(stringRedisSerializer); 
  88.         // value序列化方式采用jackson 
  89.         redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); 
  90.         // hash的value序列化方式采用jackson 
  91.         redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); 
  92.         redisTemplate.afterPropertiesSet(); 
  93.  
  94.         return redisTemplate; 
  95.     } 

编写工具类

其实到这里基本上已经完成了,我们可以看到 SpringBoot 项目接入 Redis 集群还是比较简单的,而且如果之前单机环境就是采用RedisTemplate 的话,现在也就不需要编写工具类,之前的操作依旧有效。不过作为贴心的阿粉,我还是给大家准备了一个工具类,代码太长,我只贴部分,需要完成代码的可以到公众号回复【源码仓库】获取。

  1. /** 
  2.      *  删除KEY 
  3.      * @param key 
  4.      * @return 
  5.      */ 
  6.     public boolean delete(String key) { 
  7.         try { 
  8.             return getTemplate().delete(key); 
  9.         } catch (Exception e) { 
  10.             log.error("redis hasKey() is error"); 
  11.             return false
  12.         } 
  13.     } 
  14.  
  15.     /** 
  16.      * 普通缓存获取 
  17.      * 
  18.      * @param key 键 
  19.      * @return 值 
  20.      */ 
  21.     public Object get(String key) { 
  22.  
  23.         return key == null ? null : getTemplate().opsForValue().get(key); 
  24.     } 
  25.  
  26.     /** 
  27.      * 普通缓存放入 
  28.      * 
  29.      * @param key   键 
  30.      * @param value 值 
  31.      * @return true成功 false失败 
  32.      */ 
  33.     public boolean set(String key, Object value) { 
  34.  
  35.         try { 
  36.             getTemplate().opsForValue().set(key, value); 
  37.             return true
  38.         } catch (Exception e) { 
  39.             log.error("redis set() is error"); 
  40.             return false
  41.         } 
  42.  
  43.     } 
  44.  
  45.     /** 
  46.      * 普通缓存放入并设置时间 
  47.      * 
  48.      * @param key   键 
  49.      * @param value 值 
  50.      * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期 
  51.      * @return true成功 false 失败 
  52.      */ 
  53.     public boolean set(String key, Object value, long time) { 
  54.         try { 
  55.             if (time > 0) { 
  56.                 getTemplate().opsForValue().set(key, value, time, TimeUnit.SECONDS); 
  57.             } else { 
  58.                 set(key, value); 
  59.             } 
  60.             return true
  61.         } catch (Exception e) { 
  62.             log.error("redis set() is error"); 
  63.             return false
  64.         } 
  65.     } 
  66.  
  67.     /** 
  68.      * 计数器 
  69.      * 
  70.      * @param key 键 
  71.      * @return 值 
  72.      */ 
  73.     public Long incr(String key) { 
  74.  
  75.         return getTemplate().opsForValue().increment(key); 
  76.     } 
  77.  
  78.     public Long incrBy(String key, long step) { 
  79.  
  80.         return getTemplate().opsForValue().increment(key, step); 
  81.     } 
  82.  
  83.     /** 
  84.      * HashGet 
  85.      * 
  86.      * @param key  键 不能为null 
  87.      * @param item 项 不能为null 
  88.      * @return 值 
  89.      */ 
  90.     public Object hget(String key, String item) { 
  91.  
  92.         return getTemplate().opsForHash().get(key, item); 
  93.     } 
  94.  
  95.     /** 
  96.      * 获取hashKey对应的所有键值 
  97.      * 
  98.      * @param key 键 
  99.      * @return 对应的多个键值 
  100.      */ 
  101.     public Map<Object, Object> hmget(String key) { 
  102.  
  103.         return getTemplate().opsForHash().entries(key); 
  104.     } 
  105.  
  106.     /** 
  107.      * 获取hashKey对应的批量键值 
  108.      * @param key 
  109.      * @param values 
  110.      * @return 
  111.      */ 
  112.     public List<Object> hmget(String key, List<String> values) { 
  113.  
  114.         return getTemplate().opsForHash().multiGet(keyvalues); 
  115.     } 

上面随机列了几个方法,更多方案等待你的探索。

 

 

 

总结

今天阿粉给大家介绍了一下 SpringBoot 项目如何接入 Redis 集群,需要的朋友可以参考一下,不过阿粉还是要说一下,系统的设计不能过于冗余,如果短期内还能支撑业务的发展,那就暂时不要考虑太复杂,毕竟系统的架构是需要不断的完善的,不可能刚开始的时候就设计出一套很完善的系统框架。随着业务的不断发展,当真正发现单机Redis 已经无法满足业务需求的时候再接入也不迟!

 

责任编辑:武晓燕 来源: Java极客技术
相关推荐

2022-05-31 08:04:03

Redis高可用集群

2022-06-20 22:37:25

Linux操作系统命令

2022-06-14 11:01:48

SpringBootTomcatUndertow

2022-05-31 09:01:44

RedisRDBAOF

2022-06-15 08:21:49

Linux运维工程师

2022-05-26 16:51:07

网络丢包网络故障网络

2022-04-29 15:24:53

Redis存储慢查询

2022-06-14 14:18:46

架构秒杀高并发

2022-05-11 09:02:27

Python数据库Excel

2022-06-09 13:45:18

vivoK8S集群Kubernetes

2022-06-07 11:16:51

云原生人工智能运维

2022-06-28 12:35:21

DockerPython

2022-06-12 10:55:48

AmbariApachePMC 成员

2022-06-26 09:55:00

接口自动化项目

2022-04-28 07:31:41

2022-06-06 14:35:59

KubevirtKubernetes虚拟机

2022-06-28 09:34:24

可视化Python代码

2022-06-18 09:26:00

Flink SQLJoin 操作

2022-05-05 09:27:31

Linux服务器优化

2022-06-02 15:28:42

网络安全信息通信数据保护

同话题下的热门内容

Spring Boot 自定义Jackson ObjectMapper,你学会了吗?理想中的接口自动化项目,你了解吗?

编辑推荐

从人肉运维到智能运维,京东金融服务监控的进阶之路阿里10年分布式数据库技术沉淀,AliSQL X-Cluster的应用实战爱奇艺CTO汤兴:道天地将法,《孙子兵法》的管理之道强一致、高可用、自动容灾能力背后,阿里X-Paxos的应用实践猫眼电影李明辉:机器学习在票房预估中的实战
我收藏的内容
点赞
收藏

51CTO技术栈公众号