集群收缩原理

集群收缩就是让其中一些节点安全下线。

所谓的安全下线指的是让一个节点下线之前,把其负责的所有 slots 迁移到别的节点上,否则该节点下线后其负责的 slots 就没法继续提供服务了。

收缩流程如下:

Redis集群系列十 —— 集群伸缩之收缩_数据

需求

前面扩容完成后,集群中共有4个主节点和4个从节点。随机找一个设备下线,这里以下线 30003 节点为例。

下线 30003  节点,首先需要把其上负责 slots 的数据分别迁移到指定的节点上,然后通知所有集群中的节点删除 30003 集群节点,最后 30003 节点关闭下线。

迁移槽位时最好让每个节点为的槽位尽量保持平均,那么计算公式为: (待迁移节点槽位数 / 现有节点数)=要迁出的槽位数。

示例:

待迁移节点槽位数 = 4096;现有节点数 = 3;结果为:1365.3333。

由于不能被整除,所以每个节点的槽位分别为:1365、1365、1366。

迁移槽位

准备开始迁移槽位,操作命令如下:

redis-cli --cluster reshard 127.0.0.1:30007 --cluster-from b9f22886f74d62e36fe308af4eb7f95dc31367ad --cluster-to 6134319b42511239b4c514111efbad5d6141dab0 --cluster-slots 4096

语法:

redis-cli --cluster reshard 已存在节点ip:端口 --cluster-from 要迁出节点ID --cluster-to 接收槽节点ID --cluster-slots 迁出槽数量

稍等片刻,等全部槽迁移完成后,查看集群状态如下:

Redis集群系列十 —— 集群伸缩之收缩_java_02

从图上可以看到 30003 上已经不再有槽位了,同时迁移的节点会合并到 30007 节点上。

下线节点

当槽位移动完成后分别对 30003 主从两个节实施安全下线,操作命令如下:

redis-cli --cluster del-node 127.0.0.1:30003 b9f22886f74d62e36fe308af4eb7f95dc31367ad

语法:

redis-cli --cluster del-node 已存在节点IP:端口 要删除的节点ID

Redis集群系列十 —— 集群伸缩之收缩_数据库_03

下线完主节点后,重复以上操作下线其原从节点。

最后如图所示:

Redis集群系列十 —— 集群伸缩之收缩_重定向_04

当集群中的所有其他节点收到下线命令(cluster forget <node id> )时,会删除自己保存的 node_id 对应的节点状态,至此就完成了集群的缩容。

总结

Redis 集群扩缩容最核心的地方还是数据的迁移,扩容和缩容的最大区别:

  1. 数据迁移的方向;
  2. 扩容添加新节点后,需要向整个集群广播 slot 被新的节点负责的信息。

集群收缩下线节点时,需要向集群广播让所有节点 forget 掉下线节点,同时在数据迁移过程中,我们需要解决的很重要的问题就是数据路由问题,Redis 通过 ASK 重定向和 moved 重定向解决了该问题。

集群收缩主要分为三步:

  1. 迁移槽和数据
  2. 下线节点
  3. 关闭节点