Redis 如何保证高可用

作者:杨帅      发布日期:2026.07.17

架构 · 中间件

Redis 如何保证高可用

从主从复制到 Sentinel、Cluster:一篇讲透 Redis 高可用的设计与取舍

为什么单机 Redis 不够用

Redis 单实例本质上是一个跑在内存里的单点服务:进程崩溃、宿主机宕机、网络分区,任何一个都可能导致服务中断和数据丢失。高可用(High Availability,简称 HA)要解决的核心问题,就是在这些故障发生时,系统仍能持续对外提供服务,并且数据尽量不丢。

Redis 的高可用不是靠单一技术实现的,而是由持久化、主从复制、故障自动转移、集群分片这几层机制组合而成。理解它们各自解决什么问题、又留下了什么隐患,是用好 Redis 的关键。

高可用的四层全景

把四层能力按"从下到上"叠起来看,每一层都补上了下一层缺失的能力:

Redis Cluster 分片扩容 + 去中心化故障转移 Sentinel 哨兵 自动故障发现与主从切换 主从复制 Replication 数据冗余 + 读扩展 持久化 RDB / AOF 重启不丢数据(数据级保障) 能力逐层增强
图 1 · Redis 高可用能力的四层叠加

第一层:主从复制

主从复制(Replication)是 Redis 高可用的地基。一个 master 可以挂多个 replica,master 上的写操作会异步同步到所有 replica,replica 对外提供只读服务。

客户端 写请求 Master 读 + 写 Replica 1 只读 Replica 2 只读 异步复制 异步复制
图 2 · 主从复制:写打到 master,读分散到 replica

全量同步与增量同步

replica 首次连接 master 时会触发全量同步:master 执行 BGSAVE 生成 RDB 快照发给 replica,同时把这期间的新写命令缓存进 replication buffer,快照加载完后再把缓冲区命令回放过去。之后进入增量同步阶段,master 把写命令通过 replication stream 持续推给 replica。

Redis 2.8 之后引入了部分重同步(PSYNC):master 维护一个环形缓冲区 repl_backlog,replica 短暂断连重连后,只要偏移量还在 backlog 范围内,就能只补传缺失的命令,而不必重新全量同步,大幅降低了网络抖动带来的开销。

关键限制:Redis 复制默认是异步的。master 写入成功即返回客户端,不等待 replica 确认。这意味着 master 宕机的瞬间,尚未同步到 replica 的数据会丢失——这是后面所有高可用方案都要面对的根本性权衡。

读写分离与它的短板

主从架构天然支持读写分离,但主从复制本身不具备自动故障转移能力——master 挂了,需要人工把某个 replica 提升为新 master,这在生产环境是不可接受的,于是有了 Sentinel。

第二层:持久化(RDB / AOF)

复制解决的是"实例级"的高可用,持久化解决的是"数据级"的高可用——防止进程重启或宿主机重启后数据全部丢失。

RDB · 快照 定时 fork 子进程写全量二进制快照 文件紧凑、恢复快,适合备份灾备 两次快照之间的数据会丢失 大实例 fork 可能造成短暂阻塞 AOF · 命令日志 追加写日志记录每条写命令 可配每秒 / 每次写 fsync,完整性高 文件体积大,恢复比 RDB 慢 需定期 rewrite 压缩
图 3 · RDB 与 AOF 的取舍对比

生产环境通常RDB + AOF 混合使用:AOF 保证数据尽量不丢,RDB 用于快速恢复和跨机房备份。Redis 4.0 之后还支持混合持久化格式,重写时用 RDB 格式存量数据、AOF 格式存增量命令,兼顾恢复速度与数据完整性。

第三层:哨兵模式(Sentinel)

Sentinel 是 Redis 官方提供的高可用解决方案,本质是一组独立运行的监控进程,负责监控 master/replica 的健康状态,并在 master 故障时自动完成故障发现 → 选举 → 故障转移的全过程,客户端无需人工干预。

Sentinel 1 Sentinel 2 Sentinel 3 心跳监测 (quorum) Master ✕ 宕机 (ODOWN) 选举 & 提升 Replica 1 → 新 Master 对外接管写请求 Replica 2 改为复制新 master
图 4 · Sentinel 故障转移流程:主观下线 → 客观下线 → 选举提升

主观下线与客观下线

单个 Sentinel 认为某节点没响应,只是主观下线(SDOWN);只有当法定数量(quorum)的 Sentinel 都认为它下线,才会被标记为客观下线(ODOWN),进而触发故障转移。这个"多数派确认"的设计是为了避免单个 Sentinel 因自身网络问题误判。

Sentinel 集群自己也要选出一个 Leader 来执行故障转移,基于 Raft 变种实现。因此建议部署奇数个(至少 3 个),分布在不同物理节点甚至机房,避免自身成为单点。

第四层:Redis Cluster

Sentinel 解决了单 master 的高可用,但没解决容量瓶颈——所有写请求依然压在一个 master 上。Redis Cluster 引入分片(Sharding),把数据分散到多个 master,每个 master 又各带 replica,形成"分片 + 高可用"的组合。

哈希槽(Hash Slot)

Redis Cluster 把键空间划分为 16384 个哈希槽,每个 key 通过 CRC16(key) % 16384 映射到某个槽,每个槽固定属于某一分片。客户端可直接计算 key 所在节点,实现去中心化路由。

16384 个哈希槽 · CRC16(key) % 16384 0 – 5460 5461 – 10922 10923 – 16383 Master A Replica A Master B Replica B Master C Replica C 节点间 Gossip 协议互相探测健康状态(不依赖 Sentinel) 某分片 master 宕机 → 该分片 replica 自动提升,其余分片不受影响
图 5 · Redis Cluster:槽位分片 + 每分片自带主从
方案解决的问题不解决的问题
主从复制数据冗余、读扩展自动故障转移
Sentinel自动故障转移写入容量、数据分片
Cluster数据分片、水平扩展、自动故障转移强一致性、跨槽事务

脑裂问题与数据丢失

高可用方案并非没有代价,最典型的隐患是脑裂(Split Brain):网络分区导致原 master 与多数派失联,多数派选出了新 master,但原 master 仍能接收部分客户端的写请求。网络恢复后原 master 降级为 replica,这段时间写入的数据将被丢弃。

⚡ 网络分区 少数派(被隔离) 旧 Master 仍接受写 → 数据将丢失 少量客户端 多数派(含 Sentinel) 新 Master 被选举 → 正常服务 大多数客户端
图 6 · 脑裂:两个 master 同时存在,旧 master 的写入最终被丢弃

Redis 提供两个参数来缓解(不能完全消除)这个问题:

  • min-replicas-to-write:至少要有 N 个 replica 正常连接,master 才接受写请求。
  • min-replicas-max-lag:replica 复制延迟超过这个秒数就视为不健康,不计入上面的 N。

两者配合,可以让"孤立的旧 master"在检测到 replica 不足时主动拒绝写入,缩小脑裂窗口,但由于复制本身异步,无法做到 100% 不丢数据。一致性要求极高的业务(如金融交易),需要在应用层做幂等和补偿,而不是完全依赖 Redis 的最终一致性。

工程实践中的高可用清单

  • 拓扑:至少一主两从,Sentinel/Cluster 节点跨机架甚至跨机房部署,避免单点故障域。
  • 持久化:AOF appendfsync everysec 作为默认折中,关键业务可评估 always;定期做 RDB 全量备份并异地存储。
  • 参数:合理设置 min-replicas-to-write / min-replicas-max-lag,降低脑裂窗口。
  • 监控:关注主从复制延迟、连接数、内存使用率、慢查询。
  • 客户端:使用支持 Sentinel/Cluster 协议的客户端库,能自动发现拓扑变化并重连,避免硬编码 IP。
  • 容量规划:单实例内存控制在合理范围,fork 时的写时复制(COW)开销会随实例增大而上升。
  • 演练:定期做故障转移演练(kill master 进程),验证真实的恢复时间(RTO)和数据丢失量(RPO)。

小结

Redis 的高可用是分层构建起来的:持久化防止数据彻底丢失,主从复制提供数据冗余和读扩展,Sentinel在复制之上加了自动故障发现与转移,Cluster再进一步解决了分片扩容。每一层都是在可用性、一致性和性能之间做取舍——理解这些取舍背后的原理,才能在真实故障发生时判断系统行为是否符合预期,而不是被动地"信任中间件"。