redis 集群模式接入使用
💡第三方组件声明
因依赖于第三方版本,请第三方组件、中间件和本文保持一致,避免由于第三方升级的兼容性导致无法正常使用。
启动 Redis 集群
使用 Docker 一键启动 Redis 集群(6 节点:3 主 3 从):
docker run --name redis-cluster -d \
-e CLUSTER_ANNOUNCE_IP=192.168.0.31 \
-p 7000-7005:7000-7005 \
-p 17000-17005:17000-17005 \
registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/redis-cluster:4.0
⚠IP 地址配置
请将 CLUSTER_ANNOUNCE_IP 参数修改为实际的宿主机 IP 地址,确保集群节点间能够正常通信。
客户端连接测试
使用 redis-cli 连接集群并查看节点状态:
./redis-cli -c -h 192.168.0.31 -p 7000
# 查看集群节点信息
192.168.0.31:7000> cluster nodes
✓集群状态
成功执行 cluster nodes 命令后,可看到 6 个节点信息,包括 3 个 master 节点和 3 个 slave 节点,以及各自负责的 slot 范围。
PIGX 应用配置
修改 Nacos 配置
编辑 nacos 配置中心的 application-dev.yml 文件:
spring:
data:
redis:
cluster:
enable: true
nodes:
- pigx-redis:7000
- pigx-redis:7001
- pigx-redis:7002
- pigx-redis:7003
- pigx-redis:7004
- pigx-redis:7005
💡配置说明
cluster.enable: true 启用集群模式
nodes 配置所有集群节点地址(Docker 环境使用容器名,生产环境使用实际 IP)
重启应用
修改配置后,重启 PIGX 应用使配置生效。
扩展说明
集群高可用问题
⚠版本说明
针对 PIGX 3.4 及以下版本,3.5+ 版本已默认支持集群高可用。
在 Redis Cluster 模式下,停用任何一个 master 或 slave 节点可能导致应用无法登录。相关问题见:Issue #664
问题原因
Spring Boot 2.x 默认使用 lettuce 作为 Redis 连接客户端,但自适应拓扑刷新(Adaptive updates)与定时拓扑刷新(Periodic updates)默认关闭。这导致 Redis Cluster 或 Sentinel 的拓扑变化不会通知到 lettuce 连接。
参考文档:Refreshing the cluster topology view
解决方案一:启用拓扑刷新
在 RedisTemplateConfig 和 DynamicRouteAutoConfiguration 中添加以下 Bean:
@Bean
@ConditionalOnProperty(value = "spring.redis.cluster.nodes", matchIfMissing = true)
public LettuceConnectionFactory redisConnectionFactory(RedisProperties redisProperties) {
RedisClusterConfiguration redisClusterConfiguration =
new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
// 启用拓扑刷新
ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
.enablePeriodicRefresh()
.enableAllAdaptiveRefreshTriggers()
.refreshPeriod(Duration.ofSeconds(5))
.build();
ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
.topologyRefreshOptions(clusterTopologyRefreshOptions)
.build();
// 配置读写分离
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.SLAVE_PREFERRED)
.clientOptions(clusterClientOptions)
.build();
return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
}
💡配置说明
enablePeriodicRefresh() 启用定时刷新拓扑
refreshPeriod(Duration.ofSeconds(5)) 每 5 秒刷新一次(不要设置过小)
ReadFrom.SLAVE_PREFERRED 优先从从节点读取,实现读写分离
RedisTemplateConfig 微调
解决方案二:使用 Jedis
更简单的解决方案是使用 jedis 替代 lettuce。
在所有使用 spring-boot-starter-data-redis 的模块中排除 lettuce 依赖:
<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>
<!-- 添加 Jedis 依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
💡方案选择
- 方案一:适合需要高级功能(如异步操作、响应式编程)的场景
- 方案二:更简单直接,适合常规使用场景