文档首页/ 分布式缓存服务 DCS/ 用户指南(吉隆坡区域)/ 常见问题/ 扩容缩容与实例升级/ 使用Lettuce连接Cluster集群实例时,规格变更的异常处理
更新时间:2024-07-29 GMT+08:00

使用Lettuce连接Cluster集群实例时,规格变更的异常处理

问题现象

使用lettuce连接Cluster集群实例,实例执行规格变更后,分片数有变化时,部分槽位(Slot)会迁移到新分片上,当客户端连接到新分片时会出现以下异常问题:

图1 异常现象

详情可参考Lettuce社区:Connection to X not allowed. This connection point is not known in the cluster view.

问题分析

Cluster集群规格变更原理:

客户端根据RESP2协议的内容,启动后从Cluster集群获取节点拓扑信息(Cluster Nodes),并将其拓扑关系维护在客户端的内存数据结构中。

对于数据访问,客户端会根据Key值按照CRC16算法进行Hash计算Slot信息,根据内存中保存的节点拓扑关系和Slot的对应信息进行请求自动路由。

在扩容/缩容过程中,当实例分片数发生变化时,存在节点拓扑关系和Slot对应信息的变化,需要客户端进行拓扑关系的自动更新,否则可能造成请求路由失败或者路由位置错误等,造成客户端访问报错。

例如,3分片Cluster集群实例扩容为6分片Cluster集群实例时,节点拓扑关系和Slot对应信息变化如下图所示:

图2 Cluster集群实例扩容前
图3 Cluster集群实例扩容后

解决方案

方案一(推荐方案):

开启Cluster集群自动刷新拓扑配置。

ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
             // 每隔time毫秒周期性刷新
            .enablePeriodicRefresh(Duration.ofMillis(time))
	     // MOVED重定向, ASK重定向, 重连, 未知节点(since 5.1), 槽位不在当前所有分片中(since 5.2),当出现这五种情况时会触发自适应刷新 
            .enableAllAdaptiveRefreshTriggers()
            .build(); 

具体实现请参考Lettuce客户端连接Cluster集群实例

Lettuce客户端连接Cluster集群实例,如果未开启拓扑刷新,规格变更后,需要重启客户端。

方案二:

关闭“验证集群节点成员资格开关”,关闭方式如下:

ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()  
        .validateClusterNodeMembership(false)  
        .build(); 

原理:若validateClusterNodeMembership为true时,连接前检查当前连接地址是否在集群拓扑关系中(通过CLUSTER NODES获得),若不在则会出现上述异常问题。

关闭“验证集群节点成员资格开关”的影响:

  • 缺少防止安全漏洞的检验;
  • 若未开启集群自动刷新拓扑,当Cluster集群执行变更规格后,若分片数增加时,可能会产生MOVED重定向请求,这个重定向过程会增加集群的网络负担和单次请求耗时;若分片数因删除减少时,会出现无法连接已删除分片的异常情况。