How to repair redis cluster inconsistent or unstable state ?

在redis cluster进行在线扩容过时,需要迁移slot和对应的数据,有时候出现一些莫名其妙的错误,或者redis-trib.rb reshard突然中断。比如,提示“Nodes don’t agree about configuration”,或者提示节点处于importing或者migrating状态,检查的slots处于open状态。

异常的状态和修复的思路

1、slots个数少于16384个,编号是0-16383。

对于这个问题,修复比较简单,方法也很多。redis-trib.rb fix可以直接修复。

也可以手动修复,redis-trib.rb check检查,缺少了那些slots。再在redis master节点上执行cluster addslots slot-id,注意slots分布的均匀性。

2、slots处于open状态,比如migrating 或者 importing迁移状态。

redis-trib.rb check检查出那个slot在那些节点上处于迁移open状态,如果集群数据可以丢失不影响业务准确性,或者处于importing状态的slot目前还没有数据,直接在这些节点执行CLUSTER SETSLOT  slot-idt STABLE命令。
如果数据不能丢失,建议停止业务的写入的,通过CLUSTER GETKEYSINSLOT和数据读取命令导出key和数据,然后通过CLUSTER SETSLOT slot-idt STABLE命令,使slot处于稳定状态。

3、集群的slosts配置信息不一致,用redis-trib.rb check/fix集群通常提示“Nodes don’t agree about configuration”
如果是redis-trib.rb迁移过程中产生的,等待一段时间后,redis-trib.rb check检查。因为redis cluster的epoch信息是最终一致性,在redis-trib.rb check的这一瞬间,并不能保证集群中节点拿到的slots分布信息是一致的。基于redis cluster的epoch gossio传播机制,建议把cluster-node-timeout参数设置已经相对较小的值,比如6s。
集群中不同节点记录的slots信息不一致,在不节点上执行cluster nodes信息,找出那些的slots配置信息不一致,一般就少数几个节点存在不一致。
下面的案例中,“383dd555f86a11be7d6dca295068aea79dca3e14 192.168.4.11:6310 master – 0 1493365422489 14 connected 0”信息其它节点不一致,直接使用setslot命令使其一致。

$ redis-cli  -h 192.168.4.13-p 6300 cluster nodes | grep master | sort -k2      
a270d97c71d9eb682ba5ffdab899028870678302 192.168.4.11:6300 master - 0 1493365429496 1 connected 10923-16383
383dd555f86a11be7d6dca295068aea79dca3e14 192.168.4.11:6310 master - 0 1493365422489 14 connected 0
960ce974cd2a90d120232ff5f2e8d602acb4be1a 192.168.4.11:6311 master - 0 1493365416479 15 connected
d5f7eb21db678bb0114c024463444048db7199d6 192.168.4.12:6300 master - 0 1493365426493 7 connected 1-5461
d6791f6c22be4a8e59205f885072fdf7e39eddd2 192.168.4.12:6310 master - 0 1493365427494 11 connected
d398f0a24d9e8a51f4d28cc66af0a08eea53214d 192.168.4.12:6311 master - 0 1493365410472 10 connected
201df762ffed4b922f888f80ee4640488351c862 192.168.4.13:6300 myself,master - 0 0 2 connected 5462-10922
a8e2ee553501e777717dacfcdd1d6984ad15f1dc 192.168.4.13:6310 master - 0 1493365425492 6 connected
0bf3c19c8b042809caede5a08a1ee0f1e5bef838 192.168.4.13:6311 master - 0 1493365414476 17 connected
redis-cli> cluster setslot 0 node d5f7eb21db678bb0114c024463444048db7199d6

如果数据允许丢失,直接在不一致节点上使用CLSUTER DELSLOTS slot-id删除不一致的slots。然后在该slots所在的节点上执行CLUSTER ADDSLOTS slot-id,广播正确的slots信息到所有的节点。
如果数据不允许丢失,需要把数据从异常的slots中读取出来,再修复slot。

4、关于redis cluster rebalance的一些要点:

1)如果产生了异常,用redis-trib.rb check反复检查,优先尝试redis-trib.rb fix恢复

2)千万不要重启节点或者手动修改nodes.conf中slots配置信息。

3)redis-trib.rb check做初步检查,在所有的节点上执行cluster nodes命令做详细检查,再执行CLUSTER ADDSLOTS/DELSLOTS命令。

4)建议把cluster-require-full-coverage参数设置为no,即使单个slot异常,也不会出现大量的请求异常。

5)redis-trib.rb reshard操作放在screen中执行,避免出现异常的中断,导致slots处于open状态。

6)redis-trib.rb reshard在业务地方期执行,虽然是online方式操作。

7)redis-trib.rb reshard操作之前,把cluster-node-timeout参数设置一个较小的值,比如6000(6秒)。这个参数建议不要设置太小或者太大,30s-60s即可。

参考资料:

https://redis.io/commands/cluster-setslot

此条目发表在redis分类目录,贴了, , , 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>