前言
默认springboot使用lettuce作为redis客户端,但是有些低版本的springboot直接使用lettuce连接redis集群会有版本不兼容的问题。故只能采用Jedis来整合redis集群
源代码: # springboot-example 项目 redis-cluster-jedis 分支
步骤
-
依赖
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.boot.version>2.2.5.RELEASE</spring.boot.version> <jedis.version>3.1.0</jedis.version> <fastjson.version>1.2.68</fastjson.version> </properties> <dependencyManagement> <dependencies> <!-- 统一依赖管理 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> -
配置文件
application.properties#redis集群配置 spring.redis.nodes=master:6379,master:6380,node1:6379,node1:6380,node2:6379,node2:6380, #重定向的最大次数 (意义:重定向的最大数量,比如第一台挂了,连第二台,第二台挂了连第三台,这个重新连接的最大数量) spring.redis.maxRedirects=3 #如果有密码 spring.redis.password=xxxxxx #客户端超时时间单位是毫秒 默认是2000 spring.redis.timeout=10000 #最大空闲数 spring.redis.maxIdle=10 #连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal #redis.maxActive=600 #控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性 spring.redis.maxTotal=300 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 spring.redis.maxWaitMillis=3000 #连接的最小空闲时间 默认1800000毫秒(30分钟) spring.redis.minEvictableIdleTimeMillis=300000 #每次释放连接的最大数目,默认3 spring.redis.numTestsPerEvictionRun=1024 #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 spring.redis.timeBetweenEvictionRunsMillis=30000 #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 spring.redis.testOnBorrow=true #在空闲时检查有效性, 默认false spring.redis.testWhileIdle=true -
Redis配置类RedisConfig@Configuration public class RedisConfig { @Autowired private RedisProperties redisProperties; /** * JedisPoolConfig 连接池 * * @return */ @Bean(name="jedis.pool.config") public JedisPoolConfig jedisPoolConfig() { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); // 最大空闲数 jedisPoolConfig.setMaxIdle(redisProperties.getMaxIdle()); // 连接池的最大数据库连接数 jedisPoolConfig.setMaxTotal(redisProperties.getMaxTotal()); // 最大建立连接等待时间 jedisPoolConfig.setMaxWaitMillis(redisProperties.getMaxWaitMillis()); // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟) jedisPoolConfig.setMinEvictableIdleTimeMillis(redisProperties.getMinEvictableIdleTimeMillis()); // 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3 jedisPoolConfig.setNumTestsPerEvictionRun(redisProperties.getNumTestsPerEvictionRun()); // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 jedisPoolConfig.setTimeBetweenEvictionRunsMillis(redisProperties.getTimeBetweenEvictionRunsMillis()); // 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 jedisPoolConfig.setTestOnBorrow(redisProperties.isTestOnBorrow()); // 在空闲时检查有效性, 默认false jedisPoolConfig.setTestWhileIdle(redisProperties.isTestWhileIdle()); return jedisPoolConfig; } /** * 集群redis配置 * @return */ @Bean("redis.cluster.config") public RedisClusterConfiguration redisClusterConfiguration(){ RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); String[] serverHost=redisProperties.getNodes().split(","); if (serverHost.length<1){ throw new RuntimeException("请您设置redis服务器配置信息"); } Set<RedisNode> ipNode = new HashSet<>(); for (String ipAndPorts : serverHost) { String[] ipAndPost=ipAndPorts.split(":"); ipNode.add(new RedisNode(ipAndPost[0].trim(), Integer.valueOf(ipAndPost[1]))); } redisClusterConfiguration.setClusterNodes(ipNode); redisClusterConfiguration.setPassword(redisProperties.getPassword()); redisClusterConfiguration.setMaxRedirects(redisProperties.getMaxRedirects()); return redisClusterConfiguration; } /** * 集群版 factory * @param config * @param jedisPoolConfig * @return */ @Bean(name = "jedis.cluster.factory") public JedisConnectionFactory JedisClusterConnectionFactory(RedisClusterConfiguration config,JedisPoolConfig jedisPoolConfig) { return new JedisConnectionFactory(config,jedisPoolConfig); } /** * 实例化 RedisTemplate 对象 * 使用单机版 @Qualifier("jedis.standalone.factory");使用集群版 @Qualifier("jedis.cluster.factory") * @return */ @Bean(name = "redisTemplate") @Autowired public RedisTemplate<String, Object> functionDomainRedisTemplate(@Qualifier("jedis.cluster.factory") JedisConnectionFactory jedisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); initDomainRedisTemplate(redisTemplate, jedisConnectionFactory); return redisTemplate; } /** * 设置数据存入 redis 的序列化方式,并开启事务 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, JedisConnectionFactory factory) { // 使用 GenericFastJsonRedisSerializer 替换默认序列化 GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer(); // 设置key和value的序列化规则 redisTemplate.setKeySerializer(new GenericToStringSerializer<>(Object.class)); redisTemplate.setValueSerializer(genericFastJsonRedisSerializer); // 设置hashKey和hashValue的序列化规则 redisTemplate.setHashKeySerializer(new GenericToStringSerializer<>(Object.class)); redisTemplate.setHashValueSerializer(genericFastJsonRedisSerializer); // 开启事务 redisTemplate.setEnableTransactionSupport(true); redisTemplate.setConnectionFactory(factory); //调用后初始化方法,没有它将抛出异常 redisTemplate.afterPropertiesSet(); } } -
配置类对象
RedisProperties@Data @Component @ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { private String nodes; private Integer maxRedirects; private String password; private int timeout; private Integer maxIdle; private Integer maxTotal; private Integer maxWaitMillis; private Integer minEvictableIdleTimeMillis; private Integer numTestsPerEvictionRun; private long timeBetweenEvictionRunsMillis; private boolean testOnBorrow; private boolean testWhileIdle; } -
测试代码
@RestController public class HelloController { @Resource private RedisTemplate<String, Object> redisTemplate; @RequestMapping("/setHello") public String setHello(){ redisTemplate.opsForValue().set("hello","world"); return "OK!"; } @RequestMapping("/getHello") public String getHello(){ return (String) redisTemplate.opsForValue().get("hello"); } }
如果想看哨兵、单机的整合,可以参考:www.sunofbeach.net/a/146549777…