Redis 主从、哨兵与集群

举报
yd_227606267 发表于 2026/11/06 14:31:47 2026/11/06
【摘要】 对比复制、哨兵、Cluster 三种架构,讲清选主、槽位与脑裂问题

单机 Redis 有两个硬伤:容量受限于单机内存,故障时无法自动恢复。主从复制解决读扩展与数据冗余,哨兵解决自动故障转移,Cluster 解决水平分片。三者是递进关系,不是替代关系。本文以 Redis 7.x 为基准,讲清复制流程、哨兵选主、Cluster 的槽位机制,以及各自的失效边界。

一、主从复制

从节点执行 REPLICAOF 127.0.0.1 6379 后,复制分三个阶段。

第一阶段:建立连接与全量同步。 从节点发送 PSYNC ? -1,主节点执行 BGSAVE 生成 RDB,同时把期间的新写命令存入复制缓冲区。RDB 发送完毕后,主节点再补发缓冲区里的命令。RDB 传输期间,从节点用旧数据(或空数据)对外服务。

第二阶段:命令传播。 全量同步完成后,主节点每执行一条写命令就异步发给所有从节点。从节点维护 master_repl_offset,记录已处理的字节偏移。

第三阶段:部分重同步。 网络闪断重连时,从节点发送 PSYNC <runid> <offset>,如果主节点的复制积压缓冲区(repl backlog)里还保留着该偏移之后的数据,就只补发缺失部分,不必再做全量同步。积压缓冲区由 repl-backlog-size 控制,默认 1 MB,高写入场景建议调到 64 MB 以上。

repl-backlog-size 64mb
repl-diskless-sync yes
repl-diskless-sync-delay 5
repl-diskless-load on-empty-db

repl-diskless-sync yes 让主节点直接把 RDB 写入 socket,不落盘,适合磁盘慢但网络好的环境。repl-diskless-sync-delay 是等待窗口,让多个从节点同时连接时共享一次传输。

复制是异步的:主节点写完内存就返回,不等从节点确认。所以从节点可能落后主节点若干毫秒,故障切换时这部分数据会丢。可以用 WAIT numreplicas timeout 阻塞等待指定数量的从节点确认,但它只保证「命令已到达从节点」,不保证已执行,也不是强一致方案。

二、哨兵:自动故障转移

哨兵(Sentinel)是独立进程,默认端口 26379,职责有三:监控、通知、自动故障转移。

监控。 哨兵每秒向主从节点发送 PING,超过 down-after-milliseconds(默认 30 秒)无响应标记为主观下线(SDown)。

客观下线。 单个哨兵可能因网络问题误判,所以需要多个哨兵确认。当 quorum 个哨兵都认为主节点 SDown,才标记为客观下线(ODown)。哨兵集群建议至少 3 个、奇数个,部署在不同物理机。

选主。 由领头哨兵(通过 Raft 选举产生)从从节点中挑选新主,规则依次是:

  1. 过滤掉主观下线、断线时间过长的从节点;
  2. 按 replica-priority 排序,值越小优先级越高,0 表示永不选为主;
  3. 优先级相同,比较复制偏移量,越大(数据越新)越优先;
  4. 仍相同,比较 runid,字典序小的胜出。

选出新主后,领头哨兵向其余从节点发送 REPLICAOF 指向新主,并向客户端发布新拓扑。旧主恢复后会作为从节点接入。

sentinel monitor mymaster 10.0.0.11 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

quorum 设为 2 表示至少 2 个哨兵同意才判定客观下线;parallel-syncs 1 表示故障转移后一次只让一个从节点同步新主,避免新主被多个全量同步压垮。

三、脑裂与数据丢失

网络分区时可能出现:主节点与哨兵、从节点失联,但客户端仍能写入主节点;哨兵在另一侧把从节点提升为新主。分区恢复后,旧主降级为从节点,会清空自己的数据做全量同步,期间写入的数据全部丢失。

Redis 提供两个参数限制损失:

min-replicas-to-write 1
min-replicas-max-lag 10

主节点要求至少有 1 个从节点,且延迟不超过 10 秒,否则拒绝写入。这能减少脑裂期间写入的数据量,但无法完全避免。

四、Cluster:水平分片

单机内存有上限,哨兵只能解决高可用,不能解决容量。Cluster 把数据分散到多个主节点,每个主节点负责一部分槽位。

槽位机制。 整个键空间划分为 16384 个槽(slot),每个 key 通过 CRC16(key) mod 16384 映射到槽,槽再分配给主节点。客户端访问错误节点时,节点返回 MOVED 重定向;正在迁移的槽返回 ASK 重定向。

# 创建 3 主 3 从集群
redis-cli --cluster create \
  10.0.0.11:6379 10.0.0.12:6379 10.0.0.13:6379 \
  10.0.0.14:6379 10.0.0.15:6379 10.0.0.16:6379 \
  --cluster-replicas 1

# 查看集群状态
redis-cli -c -p 6379 cluster info
redis-cli -c -p 6379 cluster nodes

cluster info 的关键字段:cluster_state:ok 表示所有槽都有节点负责;cluster_slots_assigned:16384 表示槽全部分配;cluster_known_nodes:6 是节点总数。

为什么是 16384。 心跳包会携带槽位位图,16384 位即 2 KB,节点间每秒交换多次,位图太大浪费带宽;而 16384 个主节点在现实中远超需求。集群规模建议不超过 1000 个节点。

Hash Tag。 需要多 key 原子操作的场景(如 MGET、事务、Lua)必须让 key 落在同一槽,用 {} 指定哈希标签:

SET {user:1001}:name "tom"
SET {user:1001}:age 18
# 两者都按 "user:1001" 计算槽位,落在同一节点

五、Cluster 的故障转移

Cluster 内部没有独立哨兵,故障检测与选主由节点自己完成:

  1. 节点间通过 gossip 协议每秒交换 PING/PONG;
  2. 某节点被多数主节点标记为 PFAIL,超过 cluster-node-timeout 后升级为 FAIL;
  3. 故障主节点的从节点发起选举,获得多数主节点投票后晋升;
  4. 新主接管原主负责的槽位,并通过 gossip 广播拓扑变更。

cluster-require-full-coverage yes(默认)表示只要有一个槽不可用,整个集群拒绝服务。追求可用性可设为 no,让其他槽继续服务。

六、三种架构怎么选

| 架构 | 解决 | 不解决 | 适用 |

| --- | --- | --- | --- |

| 主从 | 读扩展、数据冗余 | 自动故障转移、容量 | 读多写少,可接受手动切换 |

| 哨兵 | 自动故障转移 | 容量、写扩展 | 数据量小于单机内存,要求高可用 |

| Cluster | 容量、写扩展、高可用 | 跨槽多 key 原子操作 | 数据量大、写入高 |

提示:Cluster 不支持多数据库(只有 db0),也不支持跨槽的 MGET、MSET、事务和 Lua 脚本。迁移前必须梳理现有代码中的多 key 操作。

常见坑 / 最佳实践

  1. 哨兵至少部署 3 个,且不要和 Redis 同机。 单哨兵或与主节点同机部署,在网络分区时无法形成多数派,故障转移会失效。
  2. repl-backlog-size 要按写入量估算。 默认 1 MB 在高写入下很快被覆盖,从节点重连只能全量同步,反复触发 BGSAVE 拖慢主库。
  3. Cluster 的 key 必须规划 Hash Tag。 上线后再改 key 结构意味着数据迁移,成本极高,设计阶段就要把「同业务、需原子操作」的 key 放进同一 tag。
  4. 不要用 WAIT 实现强一致。 它只保证命令送达从节点,不保证执行,主从切换时仍可能丢数据。
  5. 监控复制延迟。 INFO replication 中的 master_repl_offset 与从节点 slave_repl_offset 之差是延迟字节数,持续增大说明从节点处理不过来。

小结

  • 主从复制分全量同步、命令传播、部分重同步三阶段,部分重同步依赖复制积压缓冲区。
  • 哨兵通过主观下线、客观下线、领头哨兵选主完成故障转移,选主顺序是优先级、偏移量、runid。
  • 脑裂会导致数据丢失,min-replicas-to-write 只能减少损失,不能根除。
  • Cluster 用 16384 个槽做分片,客户端靠 MOVED/ASK 重定向,多 key 操作必须用 Hash Tag 保证同槽。
  • 选型按数据量和可用性要求递进:主从做冗余,哨兵做高可用,Cluster 做容量与写扩展。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。