Skip to content

Cluster 集群

槽位分配、MOVED/ASK 重定向、gossip 通信、扩缩容。

Updated View as Markdown
For humans

Cluster 集群

单机内存有上限,Cluster 把数据分片到多节点,同时自带高可用(每个分片有副本)。面试主线:槽位怎么分、客户端怎么找到数据、扩容怎么迁。

槽位模型

16384 个槽分配到节点

  • 整个集群固定 16384 个槽,key 的归属由 CRC16(key) % 16384 决定
  • 每个节点负责一段槽区间,槽是数据迁移的最小单位
  • 节点之间通过 gossip 协议交换状态(PING/PONG),不用中心协调节点

客户端寻址:MOVED 与 ASK

客户端发命令时,节点判断 key 的槽是否归自己:

  • MOVED 重定向:槽不在本节点。返回 MOVED <slot> <ip:port>,客户端更新本地槽映射缓存,下次直连目标节点。槽映射是稳定的,所以只发生一次
  • ASK 重定向:槽正在迁移中。返回 ASK,客户端先发 ASKING 再发命令,不更新缓存(槽还在迁)

区别一句话:MOVED 是“槽不归我管,以后也别找我”;ASK 是“槽在迁,这次帮我带过去”。

数据迁移(扩缩容)

扩容加节点、缩容减节点都靠在线迁移槽redis-cli --cluster reshard):

  1. 目标节点准备接收槽
  2. 源节点把槽内的 key 逐个迁移(MIGRATE 命令,原子)
  3. 迁移期间访问该槽:命中的 key 直接服务,没迁到的返回 ASK
  4. 迁完广播槽归属变更

过程不中断服务,但迁移有开销:大 key 迁移慢、网络带宽占用、迁移中的 key 访问变慢。

Cluster 的限制

限制 说明
多 key 操作 必须同槽才支持(事务、Lua、mget)
hash tag {user:123}:cart 花括号内参与 CRC16,强制同槽
跨槽事务 不支持
单 key 大小 大 key 无法分散,仍是单点压力
数据分布 槽均匀但数据不保证均匀(取决于 key 分布)

哨兵 vs Cluster

维度 哨兵 Cluster
分片 无(单分片) 有(16384 槽)
容量扩展 不能(换大机器) 在线扩节点
高可用 自动故障转移 分片副本自动转移
复杂度 高(槽、重定向、迁移)

选型:数据量单机能装下用哨兵;容量要横向扩展用 Cluster。

面试追问

  1. 16384 槽怎么来的? CRC16 的结果对 16384 取模。槽数固定,节点增减只改槽归属
  2. MOVED 和 ASK 的区别? MOVED 槽归属已变,客户端更新缓存直连;ASK 槽在迁移,一次性的,不更新缓存
  3. Cluster 的键能跨节点操作吗? 不能,多 key 操作要求同槽。用 hash tag 强制相关 key 落同一槽
  4. 扩容时数据怎么迁? reshard 在线迁移槽,MIGRATE 逐 key 迁移,期间 ASK 重定向。不中断服务但占带宽
  5. 哨兵和 Cluster 怎么选? 容量够用要简单高可用用哨兵;要横向扩展容量用 Cluster
Navigation

Type to search…

↑↓ navigate↵ selectEsc close