何为网站开发,大基建最新消息,漯河做网站优化,上海十大外贸公司Redis集群配置可能会在运行时更改。可以添加新节点#xff0c;可以更改特定插槽的主节点。还有可能因为master宕机或网络抖动等原因#xff0c;引起了主从切换。
无法感知集群槽位变化
SpringBoot2.x 开始默认使用的 Redis 客户端由 Jedis 变成了 Lettuce#xff0c;但是当…
Redis集群配置可能会在运行时更改。可以添加新节点可以更改特定插槽的主节点。还有可能因为master宕机或网络抖动等原因引起了主从切换。
无法感知集群槽位变化
SpringBoot2.x 开始默认使用的 Redis 客户端由 Jedis 变成了 Lettuce但是当 Redis 集群中节点槽位变化之后Lettuce 将无法继续操作 Redis原因在于此时 Lettuce 使用的仍然是有问题的连接信息。
实际上Lettuce 支持 redis 集群拓扑动态刷新但是默认并没有开启SpringBoot 在集成 Lettuce 时默认也没有开启。并且在 SpringBoot2.3.0 之前是没有配置项设置 Lettuce 自动刷新拓扑的。在这次提交中增加了这一配置。使用Jedis便没有这个问题。
官方的描述Lettuce需要刷新节点拓扑视图Lettuce Github Wiki
解决方案
方法一使用Jedis连接
Spring Boot2.0以下默认使用Jedis由于jedis通过自身异常反馈来识别重连、刷新服务端的集群信息机制保证其自动故障恢复所以Jedis client默认自动支持拓扑刷新方法一便是使用更换为Jedis客户端。
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactIdexclusionsexclusiongroupIdio.lettuce/groupIdartifactIdlettuce-core/artifactId/exclusion/exclusions
/dependency
dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactId
/dependency方法二配置LettuceConnectionFactory,设置拓扑刷新策略
文档参考集群特定选项
Bean
public DefaultClientResources lettuceClientResources() {return DefaultClientResources.create();
}Bean
public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties, ClientResources clientResources) {ClusterTopologyRefreshOptions topologyRefreshOptions ClusterTopologyRefreshOptions.builder().enablePeriodicRefresh(Duration.ofSeconds(30)) //按照周期刷新拓扑.enableAllAdaptiveRefreshTriggers() //根据事件刷新拓扑.build();ClusterClientOptions clusterClientOptions ClusterClientOptions.builder()//redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接.timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10))).topologyRefreshOptions(topologyRefreshOptions).build();LettuceClientConfiguration clientConfiguration LettuceClientConfiguration.builder().clientResources(clientResources).clientOptions(clusterClientOptions).build();RedisClusterConfiguration clusterConfig new RedisClusterConfiguration(redisProperties.getCluster().getNodes());clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));LettuceConnectionFactory lettuceConnectionFactory new LettuceConnectionFactory(clusterConfig, clientConfiguration);return lettuceConnectionFactory;
}方法三开启自动拓扑刷新
Spring Boot2.3之后可以通过简单的配置变可以打开自动刷新拓扑的功能
# 定时拓扑刷新Periodic updates
spring.redis.lettuce.cluster.refresh.period60s
# 自适应拓扑刷新Adaptive updates
spring.redis.lettuce.cluster.refresh.adaptivetrue健康检查无法自动感知集群恢复
我们都知道Redis Cluster集群模式在主节点宕机后会自动切换到可用的从节点集群会再度恢复可用性。
但是如果在例如K8S、注册中心等管理服务中存活探针用了actuator的health地址那k8s容器里的服务也一样会down掉也会导致服务不可用即使服务层面已经刷新了redis集群的拓扑服务/actuator/health健康情况依然会是down状态原因是配置的redis集群nodes的每个node都会检查是否健康不管这个node是主节点还是从节点错误如下 redis: {status: DOWN,details: {error: org.springframework.data.redis.RedisConnectionFailureException: Redis connection failed; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 10.0.35.249:6380}
},redis cluster模式某节点宕机之后Spring识别redis集群健康为down是个bug。是由于Spring Data Redis 2.2.8 提交所引起具体可看这个解释。这个问题在spring boot2.4.x之后被修复。
解决方案
方法一升级Spring版本到2.4.X
作者有在issue#21514下回应到不会在2.3.X版本修复这个问题而是在2.4.X中才会修改
方法二重写健康检查代码
重写redis集群健康监控的Indicator可以参考issue#21514下某网友的回答
// 重新实现RedisReactiveHealthIndicatorprivate Health up(Health.Builder builder, Properties info, ReactiveRedisConnection connection) {if (connection instanceof ReactiveRedisClusterConnection) {ListMapString, String details getDetails(info);if (details.isEmpty()) {return builder.outOfService().build();} else {return builder.up().withDetail(nodes, details).build();}} else {return builder.up().withDetail(version, info.getProperty(redis_version)).build();}}private ListMapString, String getDetails(Properties info) {return info.keySet().stream().map(String.class::cast).map(k - k.substring(0, k.lastIndexOf(.))).distinct().sorted().map(node - Map.of(node, node,redis_version, info.getProperty(node .redis_version),role, info.getProperty(node .role),uptime_in_days, info.getProperty(node .uptime_in_days))).collect(Collectors.toList());}方法三关闭Redis健康检查
management.health.redis.enabledfalse文档参考RedisCluster集群模式下master宕机主从切换期间Lettuce连接Redis无法使用报错Redis command timed out的问题redis集群拓扑结构自动更新:使用Lettuce连接Cluster集群实例时异常处理刷新群集拓扑视图Redis集群调整节点并手动切换主从引发的微服务报错问题spring boot健康检查无法感知redis故障恢复的问题梳理Redis集群模式下RedisReactiveHealthIndicator中断