Skip to content

Redis 集群的实现原理是什么? ​

  • 标签:后端、Redis

🏛 业务架构师 ​

Redis 集群(Cluster)的核心机制三条:哈希槽分片(16384 个 slot 按 CRC16(key) mod 16384 落位)、节点间 Gossip 协议交换拓扑、主从+自动故障转移。客户端可直连任意节点,不归它管的 key 返回 MOVED 重定向(智能客户端本地缓存槽位映射,smart client)。

业务上我更想讲什么阶段才该上集群,这是投入产出判断:

先确认瓶颈真实存在:

  • 单机内存到 25GB 以上、fork 生成 RDB 的停顿开始影响请求;
  • 写入 QPS 接近单机上限(约 10 万级);
  • 需要横向扩容能力。

集群的代价(很多人低估):

  • 多 key 操作受限:mget、事务、Lua 涉及的 key 必须同槽,要么按 hash tag {user1}:orders 人为聚簇(又制造热点风险),要么放弃批量操作;
  • 运维复杂度翻倍:槽迁移、扩缩容、故障演练都是专业活,小团队常被反噬;
  • 客户端行为变化:重定向、拓扑刷新。

我的演进路线:单机(绝大多数业务到此为止)→ 主从+哨兵(要高可用)→ 先做业务垂直拆分(把不同业务的 Redis 实例分开,多数"内存不够"其实是业务混部)→ 最后才集群。见过太多日活十万的系统强行上集群,然后被 hash tag 和跨槽问题折磨——容量问题优先用"拆实例"解决,分片是最后手段。

🏗 系统架构师 ​

Redis 集群(Redis Cluster)我按"数据分布 + 路由 + 高可用 + 扩缩容"讲:

  • 数据分片:16384 个哈希槽,slot = CRC16(key) mod 16384,槽分配到各主节点。key 按 hash tag({user1}.xxx)可强制同槽,做多 key 操作;
  • 智能客户端路由:客户端可直连任意节点,节点不是自己负责的槽返回 MOVED(客户端缓存槽位映射);迁移期间返回 ASK 让客户端临时去新节点查;
  • 高可用:每个主节点挂 1~N 个副本,主挂后其余主节点间 Gossip 投票选主(超过半数认定下线即 failover),无需哨兵组件;
  • 扩缩容:槽迁移是逐 key 的 MIGRATE,同步阻塞毫秒级,可在线操作但大 key 迁移要小心。

权衡与限制:

  • 无中心架构换来了水平扩展(官方建议 ≤1000 主节点),代价是多 key 事务/Lua 限制在同槽、客户端复杂、不支持多库;
  • 半数以上主节点不可用则集群整体不可用——机房级故障要靠多机房部署;
  • 容量规划我按单节点内存 ≤ 10~25GB 设计,太大反而拖慢 fork/RDB 与故障恢复。

💻 全栈开发专家 ​

Redis Cluster 的核心是 16384 个哈希槽(slot):

  • 分片:slot = CRC16(key) % 16384,每个 master 负责一段槽位区间。节点数 × 槽区间就能水平扩容。
  • 路由:客户端可连任意节点,key 不归它管就回 MOVED(槽已迁移完成)或 ASK(迁移中),smart client(如 Lettuce/Redisson)本地缓存槽位表直连目标节点,基本一次网络往返。
  • ** gossip 协议**:节点间 PING/PONG 交换集群拓扑、故障检测,无中心元数据节点。
  • 高可用:每个 master 挂 1~N 个 replica,master 失效经多数派检测后自动提升从库。

我踩过的生产坑:

  1. 多 key 操作要求同 slot:MGET key1 key2 跨槽直接报错。解法是 hash tag:user:{1001}:profile,花括号内相同就落同一槽。
  2. 扩容迁移期间:运维用 redis-cli --cluster reshard 槽迁移要避开高峰,大 key 迁移会卡。
  3. 客户端要开启拓扑刷新(Lettuce enableAllAdaptiveRefreshTriggers),否则故障切换后一直打旧节点。

集群解决容量和写扩展;哨兵解决高可用不扩容,选型先看数据量。