有意思的是,Jedis在集群主备切换完成之后,是会主动拉取最新的拓扑结构并进行更新的,但是在使用Lettuce时,发现在集群主备切换完成之后,连接并没有恢复,打到该节点上的命令依旧会执行失败导致超时,必须要重启业务程序才能恢复连接。
在使用Lettuce时,如果不进行设置,默认是不会触发拓扑刷新的,因此在主备切换完成后,Lettuce依旧使用本地的映射表,将请求打到已经挂掉的节点上,就会导致持续的命令执行失败的情况。
可以通过以下代码来设置Lettuce的拓扑刷新策略,开启基于事件的自适应拓扑刷新,其中包括了MOVED、 ASK、PERSISTENT_RECONNECTS等触发器,当客户端触发这些事件,并且持续时间超过设定阈值后,触发拓扑刷新,也可以通过enablePeriodicRefresh()设置定时刷新,不过建议这个时间不要太短。
// 设置基于事件的自适应刷新策略
ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
//开启自适应拓扑刷新
.enableAllAdaptiveRefreshTriggers()
//自适应拓扑刷新事件超时时间,超时后进行刷新
.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30))
.build();
redisClusterClient.setOptions(ClusterClientOptions.builder()
.topologyRefreshOptions(topologyRefreshOptions)
// redis命令超时时间
.timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(30)))
.build());
进行以上设置并进行验证,集群在主备切换完成后,客户端在段时间内恢复了连接,能够正常存取数据了。
总结
对于缓存的操作,客户端与集群之间连接的稳定性是保证数据不丢失的关键,Lettuce作为热门的异步客户端,对于集群中产生的一些突发状况是具备处理能力的,只不过在使用的时候需要进行设置。本文目的在于将在开发缓存操作功能时遇到的问题,以及将一些涉及到的底层知识做一下总结,也希望能给大家一些帮助。