槽迁移的状态机
槽的所有权变更通过 CLUSTER SETSLOT 的状态推进完成。标准流程是:目标节点先把该槽置为 IMPORTING 并指明来源节点,源节点把该槽置为 MIGRATING 并指明目标节点,随后逐键用 MIGRATE 搬运;键搬完后,向集群内所有节点广播该槽的新归属,让路由收敛到目标节点。理解这三个状态,才能看懂 reshard 工具到底做了什么,也才能在槽卡住时知道该往哪一步推进。
基本信息
| 导入状态 | CLUSTER SETSLOT <slot> IMPORTING <源节点id>,在目标节点执行 |
|---|---|
| 迁出状态 | CLUSTER SETSLOT <slot> MIGRATING <目标节点id>,在源节点执行 |
| 完成归属 | CLUSTER SETSLOT <slot> NODE <目标节点id>,向各节点广播 |
| 清除状态 | CLUSTER SETSLOT <slot> STABLE |
| 查看残留键 | CLUSTER GETKEYSINSLOT <slot> <count> |
典型使用场景
- 自动化工具不可用时,手工处理个别槽的迁移
- 排障:槽卡在中间态时判断需要补做哪一步
- 阅读 reshard 工具输出时理解其背后动作
- 大 key 单独处理:先迁空槽,再针对大 key 单独搬运
- 迁移中断后的收尾:按流程补完或回退到稳定状态
完整流程示意
完整流程示意
# 目标节点:声明该槽正在被导入
redis-cli -p 7001 CLUSTER SETSLOT 1234 IMPORTING <源节点id>
# 源节点:声明该槽正在迁出
redis-cli -p 7000 CLUSTER SETSLOT 1234 MIGRATING <目标节点id>
redis-cli -p 7000 CLUSTER GETKEYSINSLOT 1234 100 # 查看该槽剩余的键
redis-cli -p 7000 MIGRATE 10.0.0.12 7001 user:1001 0 5000 # 逐键搬运
# 全部搬完后在各节点广播新的属主
redis-cli -p 7000 CLUSTER SETSLOT 1234 NODE <目标节点id>
redis-cli -p 7000 CLUSTER SETSLOT 1234 STABLE # 放弃迁移时清除中间状态状态与期间表现
| 状态 | 设置方 | 访问表现 |
|---|---|---|
| MIGRATING | 源节点 | 键已迁走的请求返回 ASK,引导客户端去目标节点取 |
| IMPORTING | 目标节点 | 只接受带 ASKING 的命令,否则返回 MOVED |
| NODE | 集群内各节点 | 归属正式更新,客户端路由随之收敛 |
| STABLE | 源或目标节点 | 清除中间态,回到普通状态 |
redis-cli --cluster reshard 已经把整套流程自动化,手工操作建议只用于排障与个别槽修正。手工操作最容易漏掉「向所有相关节点广播归属」和「清理中间态」这两步,遗漏后集群会长期处于拓扑不一致的状态。