音响风尚圈

音响风尚圈

Spring Boot 2.3.0 新特性Redis 拓扑动态感应

admin 168 100
背景

关于Redis在生产中我们一般情况下都会选择rediscluster高可用架构部署,既能保证数据分片并且实现节点的故障自动转移。基本部署拓扑如下:

创建测试集群

这里通过我封装的pig4cloud/redis-cluster:4.0镜像,即可构建一个6个节点的rediscluster测试环境。

dockerrun--nameredis-cluster-d-eCLUSTER_ANNOUNCE_IP=宿主机IP\-p7000-7005:7000-7005-p17000-17005:17000-17005pig4cloud/redis-cluster:4.0复制代码

查看集群节点信息

⋊./:09:48172.17.0.111:7000:7003@17003slaveb8d24150df4a221c1045cd9a0696bd1972912:7001@17001master-0132:7005@17005slave810baa140db6e008a137708f09d4335f5207:7000@17000myself,master-0001:7004@17004slaveb3cf24a918d96a1949f49a1d7b3a965ff9:7002@17002master-0173connected10923-16383复制代码
应用层接入集群

这里使用演示,默认的连接池使用lettuce

spring:redis:cluster:nodes:-172.17.0.111:7000-172.17.0.111:7001-172.17.0.111:7002-172.17.0.111:7003-172.17.0.111:7004-172.17.0.111:7005复制代码

简单使用redisTemplate操作集群

@RestControllerpublicclassDemoController{@AutowiredprivateRedisTemplateredisTemplate;@GetMapping("/add")publicStringredis(){().set("k1","v1");return"ok";}}复制代码

调用查看日志

⋊curlhttp://localhost:8080/addok⏎复制代码

我们会发现操作k1是在7000节点进行操作写入

[channel=0x5ff7aa8f,/172.17.0.156:50783-/172.17.0.111:7000,epid=0x8]write()writeAndFlushcommandClusterCommand[command=AsyncCommand[type=SET,output=StatusOutput[output=null,error='null'],commandType=],redirections=0,maxRedirections=5][channel=0x5ff7aa8f,/172.17.0.156:50783-/172.17.0.111:7000,epid=0x8]write()done复制代码
模拟单点故障

关闭7000节点

./:7000SHUTDOWN复制代码

查看rediscluster集群日志dockerlogs-fredis-cluster

我们可以看到此时集群选举完毕,完成故障转移

23:S05Jun08:24:49.387Failoverauthgrantedtoc21167a6da7f8af31d2dd612d449cdf92ad2e7e9forepoch726:M05Jun08:24:49.388Failoverelectionwon:I':S05Jun08:24:49.389SettingsecondaryreplicationIDto5253748ecf5bd7ab3536058fba8cad62d2d5e825,validuptooffset:1622.NewreplicationIDis21d6a0b199a1ba655c0279d9c78f9682477ac9a323:M05Jun08:24:49.389*:M05Jun08:24:49.390#Clusterstatechanged:ok复制代码

此时集群状态。7005从slave变更为master

应用层日志

大量输出连接7000节点异常

$AnnotatedConnectException:Connectionrefused:/172.17.0.111:7000Causedby::$AnnotatedConnectException:Connectionrefused:/172.17.0.111:7000Causedby::$AnnotatedConnectException:Connectionrefused:/172.17.0.111:7000Causedby::Connectionrefused复制代码

再次操作redisTemplate会发现卡死,等待结果返回

⋊curlhttp://localhost:8080/add复制代码

原因分析

此时还是操作k1,根据slot对应连接到7000节点,已经连接不到无限尝试重连的问题。lettuce客户端并未和rediscluster集群状态同步刷新,把宕机节点移除,完成故障转移。

集群拓扑动态感应

拓扑动态感应即客户端能够根据rediscluster集群的变化,动态改变客户端的节点情况,完成故障转移。

我们只需要在版本中开启此特性即可。

spring:redis:lettuce:cluster:refresh:adaptive:true复制代码

其实lettuce官方一直有这个功能,但springdataredis并未跟进,具体内容可以参考user-content-refreshing-the-cluster-topology-view章节

旧版本兼容

我们只需要参考adaptive开关打开后做了哪些事情,给自己的项目配置上topology-view即可

@BeanpublicLettuceConnectionFactoryredisConnectionFactory(RedisPropertiesredisProperties){RedisClusterConfigurationredisClusterConfiguration=newRedisClusterConfiguration(().getNodes());//().enablePeriodicRefresh().enableAllAdaptiveRefreshTriggers().refreshPeriod((5)).build();ClusterClientOptionsclusterClientOptions=().topologyRefreshOptions(clusterTopologyRefreshOptions).build();//().readFrom(_PREFERRED).clientOptions(clusterClientOptions).build();returnnewLettuceConnectionFactory(redisClusterConfiguration,lettuceClientConfiguration);}