主从、哨兵与 Cluster
学习目标
理解 Redis 主从复制的异步窗口,能区分 Sentinel 高可用与 Cluster 分片,并让客户端正确发现主节点、处理重定向和副本读。
核心知识点
本篇按 Redis Open Source 8 稳定主版本的通用语义说明;官方文档核对日期为 2026-10-06。托管服务、ACL、TLS、地址发布方式和小版本能力可能不同,上线前按实际服务端与客户端版本复核。
主从复制默认异步:主节点可以先确认写入,之后才把复制流发送给副本。主节点在写入到达副本前故障时,故障转移可能提升未收到该写入的副本,导致已确认写入丢失;持久化、复制确认和业务一致性是不同保证。Redis 复制
| 方案 | 主要职责 | 数据分布 | 客户端需要处理 | 主要边界 |
|---|---|---|---|---|
| 主从复制 | 复制数据并扩展可接受陈旧数据的读取 | 每个副本保存主节点的数据副本 | 写主节点;按业务容忍度选择副本读 | 异步复制有复制延迟和已确认写入丢失窗口 |
| Sentinel | 监控非 Cluster 主从组、协商故障转移、发现当前主节点 | 不分片;一个主从组仍保存同一份逻辑数据 | 从多个 Sentinel 发现主节点并重连 | 多数派不可达时不进行自动故障转移;切换不保证无损 |
| Redis Cluster | 按槽分片并在主节点故障时提升副本 | 16384 个槽分布到多个主节点 | 维护槽表、处理 MOVED / ASK、重试有界 | 多键需要同槽;异步复制与分区仍有数据安全窗口 |
Sentinel 与 Cluster 解决的问题不同,不应把 Sentinel 当作分片代理,也不在一个 Cluster 内再用 Sentinel 管理槽主节点。二者的自动故障转移都不是同步共识提交,不保证无损;若写入不能丢失,必须由持久化、上游事务、幂等/版本协议和可验证恢复流程共同定义业务承诺。
下面的命令需要连接已准备好的、独立可丢弃的 Redis 8 实验拓扑:普通主从示例使用本机 6379/6380;Sentinel 使用本机 26379;Cluster 使用本机 7000—7005。先确认这些端口属于本次实验、配置了所需 ACL/TLS,并且没有业务数据。不同拓扑的实际节点地址和状态都是动态信息,命令示例只给出查询过程,不伪造固定主机、端口、槽归属或故障转移结果。有 ACL 时通过 redis-cli --user lab_user --askpass 安全认证,不把密码写入命令行。
常用用法
INFO replication:观察复制链路与偏移量
用于在授权诊断连接上查看当前节点角色、复制偏移和链路状态。
# 初始:本机隔离实验拓扑已启动主节点和至少一个副本,连接目标节点的 6379 端口。
# 边界:INFO replication 仅在具备权限的受控诊断连接低频读取;主机地址和复制状态随拓扑变化。
INFO replication
# 关键变化:读取当前主从角色、复制链路、偏移量和 backlog 状态供时间序列比较。
# 输出:检查 role、master_link_status、*_repl_offset 与 repl_backlog_*;数值随复制进度变化。主节点确认客户端写入与副本应用复制流之间存在异步窗口;故障转移可能丢失已确认写入。观察复制偏移差、链路状态和最近通信时间时应连续采样并与业务写入量关联;瞬时相等不能证明下一次写入会及时复制。复制 backlog 用于断线后的部分重同步:若副本断线期间的复制流仍在 backlog 保留范围内,可尝试部分同步;否则需要全量同步,增加网络、CPU、内存和磁盘压力。backlog 不是持久化备份,也不会消除故障转移窗口。复制与部分重同步、INFO。
WAIT:等待同一连接上的副本确认
用于在同一条客户端连接上为之前的写入增加一个有界的副本确认等待。
# 初始:本机隔离主从实验中,lab:{topology}:wait 仅为可丢弃的学习键。
SET lab:{topology}:wait example-v1
WAIT 1 250
# 关键变化:WAIT 最多等待 250 毫秒,并返回确认了此前本连接写入的副本数。
# 输出:整数可能小于 1;应用必须将实际返回数与所需副本数比较。WAIT numreplicas timeout 的 timeout 单位是毫秒,设为 0 会无限等待,生产应给出有限值。它只等待同一连接此前写入的复制确认;使用连接池的应用必须确保写入与 WAIT 没有被分配到不同连接,并检查返回整数。它能缩小部分风险窗口,但不保证副本已 fsync,也不保证强一致性;Sentinel 或 Cluster 仍可能在特定故障时丢失已确认写入。WAIT 的连接、超时与一致性说明。
SENTINEL CKQUORUM:检查发现与选举条件
用于检查当前 Sentinel 组是否同时具备故障检测 quorum 和执行切换所需的多数派。
# 初始:至少三个分布在独立故障域的 Sentinel 已加载 lab-master 配置。
# 在连接到本机 26379 端口的 Sentinel 协议会话中执行:
SENTINEL CKQUORUM lab-master
# 关键变化:将当前 Sentinel 成员可达性与配置 quorum、选举多数派做一次健康检查。
# 输出:OK 或带有当前不可达数量的错误信息;内容取决于实际成员状态。quorum 是多少 Sentinel 需要同意主节点不可达才能标记为客观下线;真正启动故障转移还要选出 leader,并取得 Sentinel 进程多数派授权。quorum 小于多数派会更敏感地检测失败,但不会免除选举多数派;多数派不可达时不会在少数分区自行切换。建议至少三个 Sentinel 放在彼此独立的机器或故障域,并把 CKQUORUM 的健康结果纳入监控。Sentinel 的重配和故障通知不构成业务数据的零丢失承诺。Sentinel quorum、选举与命令列表。
SENTINEL get-master-addr-by-name:故障后重新发现主节点
用于在连接中断或收到切换通知后查询 Sentinel 当前记录的主节点地址。
# 初始:lab-master 由多个 Sentinel 监控;客户端可连接至少两个已登记 Sentinel 地址。
# 在本机 26379 端口的 Sentinel 会话中执行:
SENTINEL get-master-addr-by-name lab-master
# 关键变化:客户端缓存 lab-master 从 old_endpoint 更新为 discovered_endpoint,并创建指向新主节点的连接。
# 输出:当前地址和端口由 Sentinel 状态决定;故障转移期间可能仍需重试发现。客户端应保留可用的 Sentinel 地址列表,发生连接失败时查询服务名并重连新主节点,而不是把首次发现的主机永久写死。发现新地址不会迁移旧 TCP 连接,也不会重放或修复结果未知的写入;故障转移仍可能丢失先前已确认写入,重试必须结合业务幂等键和请求超时边界。Sentinel 选副本时会综合其是否仍适合提升、优先级和已处理复制偏移,因此提升的是可用候选者,不是对所有已确认写入的证明。Sentinel 客户端发现、副本选择与命令列表。
CLUSTER KEYSLOT:验证 hash tag 与同槽约束
用于让服务端计算两个 key 的槽号,核实计划中的多键操作是否同槽。
# 初始:本机 7000 端口连接到已分配全部槽的隔离 Redis Cluster。
CLUSTER KEYSLOT lab:{order:42}:profile
CLUSTER KEYSLOT lab:{order:42}:events
# 关键变化:两个 key 的第一个非空 hash tag 相同,因此服务端将二者映射到同一槽。
# 输出:各自的槽号由 CRC16 计算;比较两个实际返回值,不写死拓扑输出。Redis Cluster 将 key 映射到 0—16383 共 16384 个 hash slot,基础算法为 CRC16(key) mod 16384。若 key 中存在有效的 {...} hash tag,只对第一个左花括号与其右侧第一个右花括号之间的非空字节计算;不同业务 key 可共享 {order:42},使事务、Lua 和多键命令落在同槽。空 tag {} 不会按空内容散列,而会回退为整个 key。生产 key 命名应先评估热点风险,过于集中的 tag 会让一个槽和一个主节点过热。不同槽的多键命令会得到 CROSSSLOT,不能靠客户端重试修复。Cluster 槽与 hash tag 规则、CLUSTER KEYSLOT。
CLUSTER SHARDS:刷新槽表并区分 MOVED 与 ASK
用于读取当前分片、槽范围和节点角色,并为客户端检查重定向与迁槽进度。
# 初始:本机 Cluster 已完成初始化;连接到任一可达节点。
CLUSTER SHARDS
# 关键变化:客户端或运维工具取得当前 slot map,并与已缓存的分片拓扑比对。
# 输出:shard ID、槽范围、节点角色和地址受真实集群、RESP 版本与迁槽进度影响。回复包含当前分片的结构化信息;Redis 7 起提供 CLUSTER SHARDS,不要把一份示例地址或槽范围当作固定拓扑。MOVED 表示服务端认为该槽的归属已永久改变,客户端应把槽映射更新到目标节点;通常重新拉取完整 slot map,避免只修一个槽而漏掉同批变更。ASK 表示 resharding(迁槽)期间只把这一次命令临时转发到目标节点,后续请求仍按旧槽表路由;在目标连接上先发 ASKING 再发这一条命令,不能提前永久更新 slot map。迁槽完成后来源节点会改为 MOVED。客户端还需为地址不可达、槽未分配、TRYAGAIN 和 CROSSSLOT 设置可观测的错误处理与有界重试;不同槽的多键操作属于跨槽访问,不会由重试变成同槽。运维侧的 CLUSTER SETSLOT、MIGRATE 等会改拓扑或搬数据的管理操作只应在审批后的隔离演练/变更窗口执行。Cluster redirection、resharding 与 CLUSTER SHARDS、CLUSTER SHARDS。
ASKING:只授权一次迁槽期间的重定向请求
用于在目标节点的 importing 状态下,紧接着执行服务端通过 ASK 指定的那一条请求。
# 初始:lab:{order:42}:recent 对应的槽正处于受控迁槽;客户端已收到目标节点的 ASK 响应。
ASKING
GET lab:{order:42}:recent
# 关键变化:ASKING 只设置当前连接的一次性标记,服务端据此处理下一条请求。
# 输出:GET 值受 key 实际位置与迁移进度影响;下一次请求仍使用原 slot map。ASKING 必须和紧随其后的单条被重定向命令在同一个目标节点连接上执行;它不是全局切换,也不更新客户端的本地 slot map。收到 ASK 时仅重试这次命令,下一条同槽命令继续先走旧 owner;迁槽结束后以 MOVED 更新路由。连接池若不能保持这两条命令在同一连接,就应交给支持 Cluster 协议的客户端处理。ASK 临时重定向语义、ASKING。
READONLY:在 Cluster 副本上读取可容忍陈旧的数据
用于声明当前 Cluster 副本连接只执行可能读到旧值的只读查询。
# 初始:本机 Cluster 客户端连接到已确认可服务 lab:{order:42} 槽的副本。
READONLY
GET lab:{order:42}:profile
# 关键变化:lab:{order:42}:profile 的读取路由由主节点改为读取本副本已应用的值,写请求不走此连接。
# 输出:GET 返回当前副本已应用的数据,可能落后于主节点。副本读可分担读流量,但复制异步意味着读结果可能陈旧且不提供强一致性,故不能用于余额、权限或刚写后必须读到新值的路径,除非业务协议另有版本校验/读主保证。副本只可服务其主节点当前负责的槽;重分片后无权服务的槽仍会重定向。READWRITE 可清除当前连接的只读模式;客户端必须区分它与 Sentinel 普通副本连接,并分别应用读路由策略。Cluster 副本读取、READONLY。
REPLICAOF:仅在隔离副本配置上游
用于把一次性实验副本接到本机指定主节点,并观察异步同步状态。
# 初始:本机 6381 是新建、隔离且可丢弃的空副本;6380 是同一实验拓扑中的主节点。
# 危险:REPLICAOF 仅在隔离测试环境连接正确的两台实验实例时执行;同步会覆盖副本原有数据。
REPLICAOF 127.0.0.1 6380
# 关键变化:6381 开始向 6380 建立异步复制;命令受理不表示全量同步已完成。
# 输出:OK 仅表示配置请求被接受;另在副本上读取 INFO replication 核实链路与同步进度。不能在生产主节点或含有独有数据的实例上试运行 REPLICAOF。将节点改为副本会让其数据按上游同步,旧数据可能被覆盖;REPLICAOF NO ONE 也会改变节点角色并允许产生新的写历史,不能作为无审批的恢复快捷键。Sentinel 与 Cluster 的自动故障转移应由其协调逻辑管理;人为改角色会制造不同配置和数据分叉风险。REPLICAOF。
易混点
- 异步复制是复制速度与可用性的设计取舍,不是每次写入同步落到副本;副本数、
WAIT返回数和 RDB/AOF 设置都不能单独证明任意故障下零丢失。 - Sentinel 的 quorum 是检测门槛,leader 获得多数派授权才执行故障转移;增加 quorum 不会修复网络隔离,也不等于数据已持久化。
- Cluster 以槽分片,副本复制的是所属主节点槽数据。哈希标签适合有限相关键的原子操作,不能把所有 key 都放进一个 tag,否则单槽会成为容量和吞吐热点。
- Cluster 客户端必须支持
MOVED、ASK、ASKING、超时重连与同槽限制;普通单节点连接池不能代替 Cluster-aware 客户端。 - 成功切换只说明控制面选择了新主节点并恢复服务,不表示应用此前的超时写入已提交、旧主节点停止接收过期客户端写入,或所有副本都追平。
课后小问
WAIT 1 250返回 0 时,为什么不能把它当作写入未执行并盲目重放?- Sentinel 中 quorum 与 leader 多数派分别解决什么问题?
- 在 Cluster 槽迁移过程中,客户端收到
ASK后为何不应马上更新本地槽映射? - 哪些读可以发给副本,哪些业务需要从主节点或权威存储读取?
本节小结
主从提供异步副本,Sentinel 为非分片部署提供协商式故障转移和地址发现,Cluster 通过 16384 个槽实现分片并要求客户端维护路由。WAIT、quorum 和副本读都有明确的可用性、延迟与一致性边界;故障转移可能丢失已确认写入,必须将该窗口纳入业务恢复设计。
快速回顾
复制看 offset、link 和 backlog;Sentinel 看 quorum、leader majority 与重新发现;Cluster 看 slot map、hash tag、MOVED/ASK 与同槽限制。任何拓扑演练都先确认实例、端口、数据可丢弃和回滚步骤。
阿源的知识库