Spring Boot 默认使用 Lettuce 作为 Redis 客户端,它支持响应式编程且易于使用。但在部分低版本 Spring Boot 中,Lettuce 与 Redis 集群存在版本兼容性问题,导致连接不稳定或无法连接集群。鉴于此,采用 Jedis 客户端作为 Redis 集群的连接方案成为了切实可行的替代方案。
本文详细介绍如何在 Spring Boot 项目中使用 Jedis 整合 Redis 集群,包含依赖配置、属性设置、关键代码实现以及调用示例,为实际项目中使用 Redis 集群提供完整参考。
相关文章源码地址请参考:springboot-example 项目 — redis-cluster-jedis 分支
引入关键依赖
在 Maven 的 pom.xml
中,除了引入 Spring Boot Web 和 Redis 相关依赖外,需要注意的是要排除默认的 Lettuce 依赖,改用 Jedis 客户端。相关依赖示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| <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> <optional>true</optional> </dependency> </dependencies>
|
此配置确保项目使用 Jedis 作为底层客户端,避免 Lettuce 与低版本 Spring Boot 造成的兼容性问题。
优化 Redis 集群配置文件
将 Redis 集群相关配置统一放到 Spring Boot 的配置文件中,例如 application.properties
,方便集中管理和修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| spring.redis.nodes=master:6379,master:6380,node1:6379,node1:6380,node2:6379,node2:6380
spring.redis.maxRedirects=3
spring.redis.password=xxxxxx
spring.redis.timeout=10000
spring.redis.maxIdle=10 spring.redis.maxTotal=300 spring.redis.maxWaitMillis=3000
spring.redis.minEvictableIdleTimeMillis=300000 spring.redis.numTestsPerEvictionRun=1024 spring.redis.timeBetweenEvictionRunsMillis=30000
spring.redis.testOnBorrow=true spring.redis.testWhileIdle=true
|
说明
- nodes:配置 Redis 集群所有节点的地址,可以根据实际环境动态调整。
- maxRedirects:集群状态切换时最快重定向请求次数,合理设置可保证连接稳定。
- 密码及超时:支持基于授权和不同网络环境的定制化配置。
- 连接池参数:关键提升 Redis 访问性能和稳定性,避免连接资源耗尽。
编写 Redis 配置类使用 Jedis
通过一个专门的 Spring 配置类完成 Jedis 客户端与 Redis 集群的连接初始化,并定义序列化方式以及事务支持。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| @Configuration public class RedisConfig {
@Autowired private RedisProperties redisProperties;
@Bean(name = "jedis.pool.config") public JedisPoolConfig jedisPoolConfig() { JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxIdle(redisProperties.getMaxIdle()); poolConfig.setMaxTotal(redisProperties.getMaxTotal()); poolConfig.setMaxWaitMillis(redisProperties.getMaxWaitMillis()); poolConfig.setMinEvictableIdleTimeMillis(redisProperties.getMinEvictableIdleTimeMillis()); poolConfig.setNumTestsPerEvictionRun(redisProperties.getNumTestsPerEvictionRun()); poolConfig.setTimeBetweenEvictionRunsMillis(redisProperties.getTimeBetweenEvictionRunsMillis()); poolConfig.setTestOnBorrow(redisProperties.isTestOnBorrow()); poolConfig.setTestWhileIdle(redisProperties.isTestWhileIdle()); return poolConfig; }
@Bean("redis.cluster.config") public RedisClusterConfiguration redisClusterConfiguration() { String nodes = redisProperties.getNodes(); if (nodes == null || nodes.trim().isEmpty()) { throw new IllegalArgumentException("请配置spring.redis.nodes!至少包含一个Redis集群节点"); }
RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(); Set<RedisNode> nodeSet = new HashSet<>(); String[] nodesArray = nodes.split(","); for (String node : nodesArray) { String[] hostAndPort = node.trim().split(":"); if (hostAndPort.length != 2) { throw new IllegalArgumentException("redis节点配置格式错误,正确格式如:ip:port"); } String host = hostAndPort[0].trim(); int port = Integer.parseInt(hostAndPort[1].trim()); nodeSet.add(new RedisNode(host, port)); }
clusterConfig.setClusterNodes(nodeSet); clusterConfig.setMaxRedirects(redisProperties.getMaxRedirects()); clusterConfig.setPassword(redisProperties.getPassword()); return clusterConfig; }
@Bean(name = "jedis.cluster.factory") public JedisConnectionFactory jedisConnectionFactory( @Qualifier("redis.cluster.config") RedisClusterConfiguration clusterConfig, @Qualifier("jedis.pool.config") JedisPoolConfig poolConfig) { return new JedisConnectionFactory(clusterConfig, poolConfig); }
@Bean(name = "redisTemplate") @Autowired public RedisTemplate<String, Object> redisTemplate( @Qualifier("jedis.cluster.factory") JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory);
GenericFastJsonRedisSerializer fastJsonSerializer = new GenericFastJsonRedisSerializer();
template.setKeySerializer(new GenericToStringSerializer<>(Object.class)); template.setHashKeySerializer(new GenericToStringSerializer<>(Object.class));
template.setValueSerializer(fastJsonSerializer); template.setHashValueSerializer(fastJsonSerializer);
template.setEnableTransactionSupport(true);
template.afterPropertiesSet(); return template; } }
|
设计亮点
- 参数集成:所有配置均从
RedisProperties
配置对象注入,配置更灵活。
- 连接池优化:完整设置 Jedis 连接池,确保连接性能和健康。
- 序列化优化:采用
GenericFastJsonRedisSerializer
代替默认 JDK 序列化,提升存取效率,防止乱码。
- 事务支持:适应需要多命令事务场景,增强 Redis 操作的完整性保障。
封装 Redis 参数映射类
该类负责映射 Spring Boot 配置文件中的 spring.redis
前缀属性,简化配置读取和管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| @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; }
|
备注:其中使用 Lombok 的 @Data
生成 getter/setter,减少样板代码。
简单测试及验证
通过 Controller 验证 Redis 集群的连接及数据读写功能。示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @RestController public class HelloController {
@Resource private RedisTemplate<String, Object> redisTemplate;
@GetMapping("/setHello") public String setHello() { redisTemplate.opsForValue().set("hello", "world"); return "OK!"; }
@GetMapping("/getHello") public String getHello() { Object value = redisTemplate.opsForValue().get("hello"); return value != null ? value.toString() : "null"; } }
|
调用 /setHello
接口会把 key 为 hello
的字符串写入 Redis,调用 /getHello
接口则能正确获取到刚存入的值,验证集群访问正常。
拓展与优化建议
- 哨兵模式支持:基于 Jedis,也可以简化扩展为哨兵集群连接。详情可参考官方文档及相关博客教程。
- 单机模式兼容:单节点 Redis 环境也可通过类似配置实施 Jedis 连接,调整连接工厂即可。
- 连接池监控:实用时可结合如 Spring Boot Actuator 或 监控平台实时观察连接池状态及性能。
- 序列化方案多样化:FastJson 外,也可尝试 Jackson、Kryo 等性能更优的序列化方式。
- 安全配置:确保 Redis 密码安全,必要时增加客户端 IP 白名单与通信加密措施。
总结
本文通过配置 Maven 依赖、Spring Boot 属性、Java 代码实现,完整演示了如何用 Jedis 高效稳定地连接 Redis 集群,解决了 Lettuce 不兼容的问题。该方案结构清晰、扩展性强,适合生产环境使用。
如果您使用的是低版本 Spring Boot 且面对 Redis 集群连接难题,使用本文方案可以快速上手并应用到实际项目中。
相关阅读
祝您开发顺利!