单机 Redis 的内存、连接和命令执行都集中在一台机器上。Cluster 把 Key 空间切成 16384 个槽位,让不同节点负责不同数据,同时通过 Gossip 传播拓扑和故障状态。
目录
- 槽位与请求归属
- [MOVED、ASK 与客户端路由](#MOVED、ASK 与客户端路由)
- [Hash Tag 与跨槽限制](#Hash Tag 与跨槽限制)
- [Gossip 与故障检测](#Gossip 与故障检测)
- 迁槽与扩缩容
- 集群设计边界
一、槽位与请求归属

Cluster 使用 CRC16(key) mod 16384 计算槽位。节点不按 Key 前缀直接分片,而是维护自己负责的槽位范围。
槽位是稳定的路由单位。扩容时迁移槽位,不需要把整个实例的数据集一次性搬走。
二、MOVED、ASK 与客户端路由

客户端连错节点时,节点返回 MOVED slot host:port,表示槽位归属已经稳定变化,客户端应更新拓扑缓存后重发。迁移过程中,目标节点可能返回 ASK,客户端只对下一次请求临时发送 ASKING,不能立即永久改写槽位表。
生产客户端必须支持集群模式、拓扑刷新、重试次数和跨节点 pipeline。普通单机客户端即使能连上某个节点,也无法正确处理 MOVED。
三、Hash Tag 与跨槽限制
Key 中的 {...} 是 Hash Tag:order:{1001}:items 与 order:{1001}:meta 只对花括号内容计算槽位,因此可以放在同一节点。
多 Key 命令、事务和 Lua 脚本通常要求所有 Key 在同一槽位。Hash Tag 能解决局部聚合,但不能把所有业务都塞进一个 Tag,否则热点会集中到单节点。
四、Gossip 与故障检测

节点通过 Cluster Bus 交换节点 ID、地址、槽位和故障标记。某节点先标记疑似故障,得到足够票数后形成失败共识,并触发副本晋升。
Cluster 的故障检测与 Sentinel 不同,客户端也不向 Sentinel 查询主节点;它从集群节点获得拓扑并自行路由。
五、迁槽与扩缩容

迁移一个槽位时,源节点和目标节点会经历导入、导出、逐 Key 搬迁和槽位确认。迁移期间请求可能收到 ASK,客户端必须按协议重试。
扩容应先加入空节点,再按负载均衡迁移槽位;缩容则先迁空目标节点负责的槽位,确认没有 Key 后再下线。迁移速度要受控,避免网络、CPU 和 fork 同时抖动。
六、集群设计边界
Cluster 解决水平分片和节点级故障,不自动解决跨槽事务、跨节点强一致和业务级热点。商品详情适合按商品 ID 分片,订单聚合要提前设计 Hash Tag 和读模型。
6.1 场景:商品详情上集群后,结算接口突然 CROSSSLOT
商品详情服务把库存、价格、限购计数分别设计为 product:stock:1001、product:price:1001、user:buy:42:1001。单机阶段,一段 Lua 可以原子校验库存并写限购;迁入 Cluster 后,脚本调用直接返回 CROSSSLOT Keys in request don't hash to the same slot。
这里不能把异常当成客户端偶发错误重试,因为重试仍会落到不同槽位。若这些数据确实必须由一次脚本共同修改,Key 设计应以同一个业务聚合根 使用 Hash Tag,例如 product:{1001}:stock 与 product:{1001}:price。但用户维度限购如果也塞进 {1001},热门商品会把所有用户请求打到同一槽,扩容形同虚设。
正确做法通常是分两层:库存扣减放在商品槽位并通过 Lua 保证原子;用户限购用独立分片或数据库唯一约束兜底;订单事件异步汇合。Hash Tag 是为了局部原子性,不是为了让所有相关数据"看起来在一起"。
6.2 场景:扩容时 ASK 激增,业务误判为 Redis 故障
给集群新增节点并迁移热点槽位时,监控里 ASK 响应短时间升高。一个自研客户端把所有重定向都按 MOVED 处理,收到 ASK 就刷新整个槽位表并永久改路由,导致一部分请求在源、目标之间来回跳,P99 延迟翻倍。
处理办法不是暂停迁槽,而是修正客户端协议:MOVED 更新本地槽位缓存;ASK 只对当前命令在目标节点前发送 ASKING,下一次仍按原槽位表路由,直到收到稳定 MOVED。迁槽操作同时应限速,并避开 AOF 重写、RDB 快照和大 Key 删除等重 I/O 时段。
扩容前还要检查槽位分布,而非只看节点内存。若热点 Key 的 Hash Tag 设计不当,新增节点也分不到热点;如果一个槽位本身极热,唯一有效的改造是拆 Key、分片计数或调整业务读模型。
6.3 用命令确认迁移是否真的完成
扩容窗口内不要只看云平台的节点列表。先用 CLUSTER INFO 确认 cluster_state:ok,再用 CLUSTER SLOTS 检查每个槽位的 owner;对正在迁移的节点执行 CLUSTER NODES,关注 migrating、importing 标记。迁移工具报告"完成"但仍有孤儿 Key 时,业务可能在重启后出现 CLUSTERDOWN Hash slot not served。
迁移前应保存槽位分布和热点 Key 样本,迁移后比较各节点的 used_memory、命令吞吐和 P99。若某节点内存明显偏高,说明"槽位数量均匀"不等于"数据量均匀",需要继续拆分大 Key 或重新规划业务 Tag。
记住:槽位决定归属,MOVED 表示稳定路由变化,ASK 只表示迁移中的临时方向;扩容迁移的是槽位,不是简单复制整台机器。