先说结论

Redis 通过 RDB 快照和 AOF 日志实现数据持久化,通过异步主从复制保存副本,使用 Sentinel 完成主从架构的监控与自动切换,或使用 Redis Cluster 同时实现分片和故障转移。它们通常只能降低数据丢失风险,不能自动提供跨节点强一致。

RDB 快照

RDB 在某个时间点生成内存数据快照文件,适合备份、全量复制和快速恢复。

优点:

  • 文件紧凑,适合备份和跨机房传输。
  • 重启恢复通常比重放大量 AOF 快。
  • 主进程主要负责 Fork,具体写文件由子进程完成。

不足:

  • 两次快照之间的数据可能在故障时丢失。
  • Fork 大进程会带来页表复制和延迟抖动。
  • 快照期间写入导致 Copy-on-Write,可能增加内存峰值。
  • 磁盘慢或内存大时生成时间较长。

Fork 和 Copy-on-Write

生成 RDB 时,子进程读取 Fork 时刻的内存视图。主进程继续处理写入;被修改的内存页复制后由主进程使用,子进程仍看到旧页。

因此执行 BGSAVE 时要关注:

  • 实例内存大小。
  • 系统剩余内存。
  • 写入速率。
  • Transparent Huge Pages。
  • Fork 耗时和磁盘吞吐。

高写入期间 COW 可能让 RSS 明显增长,容器 Limit 过紧会导致 OOMKilled。

AOF 日志

AOF 记录会改变数据的写命令,重启时重放恢复。

常见刷盘策略:

  • Always:每条命令同步磁盘,安全性高但吞吐和延迟成本大。
  • Everysec:通常每秒刷盘一次,性能与数据安全折中,故障时可能丢约一秒数据。
  • No:由操作系统决定刷盘,性能较好但丢失窗口更大。

生产常选择 Everysec,但要根据业务可接受的数据损失目标决定。

AOF Rewrite

AOF 持续追加会不断变大。Rewrite 根据当前内存状态生成等价但更紧凑的命令,例如一个 Key 被修改一万次,重写后只保留恢复当前值所需的命令。

Rewrite 同样涉及 Fork、COW、CPU 和磁盘 IO。不能只关注 AOF 文件大小,还要监控重写持续时间、失败次数和磁盘余量。

RDB 和 AOF 怎么选

维度 RDB AOF
数据丢失窗口 快照间隔 取决于刷盘策略
文件大小 通常较小 通常较大
恢复速度 通常较快 需要重放日志
运行开销 周期性 Fork 与写文件 持续追加与定期重写
备份 适合 也可使用但管理更复杂

重要数据可以同时开启 RDB 和 AOF。具体 Redis 版本的加载优先级和混合持久化能力需要结合官方文档和配置确认。

混合持久化

混合模式在 AOF 重写文件前部保存 RDB 格式快照,后部追加重写期间的命令,兼顾恢复速度和 AOF 的较小数据丢失窗口。

启用前要确认 Redis 版本、运维工具和备份流程都支持该格式。

持久化不等于备份

误删除和错误写入也会进入 AOF 和副本。持久化用于进程重启恢复,高可用用于实例故障切换,历史恢复仍需要独立备份、保留周期和恢复演练。

主从复制流程

Replica 连接 Master
       ↓
身份验证与复制握手
       ↓
能增量同步?
  ├── 是:发送积压缓冲区中的命令
  └── 否:生成 RDB 全量同步
       ↓
Replica 加载快照
       ↓
持续接收新写命令

主从复制通常异步,Master 执行成功后不会等待所有 Replica 应用。因此刚写入的数据可能暂时无法从 Replica 读取,Master 故障时尚未同步的数据也可能丢失。

全量同步

Replica 首次加入或断线太久时进行全量同步。Master 生成快照并发送,同时把期间的新写命令保存在缓冲区;Replica 加载快照后再应用增量命令。

大实例全量同步会消耗 Fork、磁盘、网络和 Replica 加载时间。多个 Replica 同时全量同步可能形成复制风暴。

增量同步

Master 维护复制 ID、Offset 和复制积压缓冲区。Replica 短暂断线重连后,如果缺失数据仍在缓冲区,可以只补发断线期间命令。

缓冲区过小会让稍长网络抖动退化为全量同步。大小应结合写入速率和预期最长断线时间配置。

复制延迟

常见原因:

  • 网络延迟或带宽不足。
  • Replica CPU、磁盘或内存压力。
  • Master 大量写入。
  • Big Key 传输和处理。
  • Lua 或慢命令阻塞事件循环。
  • Replica 执行持久化和全量同步。

读写分离时必须接受短暂旧数据。写后立刻读取关键状态应读 Master,或使用业务版本校验。

Sentinel 解决什么问题

Sentinel 监控 Master 和 Replica,在 Master 故障时选择 Replica 提升为新 Master,并通知其他 Replica 和客户端切换。

它提供:

  • 监控与故障检测。
  • 主观下线和客观下线判断。
  • Leader Sentinel 选举。
  • Replica 选主和故障转移。
  • 客户端获取当前 Master 地址。

Sentinel 不负责数据分片,数据集仍完整保存在每个 Master/Replica 节点。

主观下线与客观下线

单个 Sentinel 认为节点不可达是主观下线。达到配置数量的 Sentinel 都认为 Master 不可达,才形成客观下线并尝试故障转移。

这样可以减少单个 Sentinel 网络异常造成误切换,但仍需合理部署到不同故障域,并处理网络分区。

Sentinel 选新 Master 的考虑

通常综合 Replica 优先级、复制状态、数据 Offset 和稳定性选择。数据越接近原 Master 的 Replica 越适合提升。

故障切换期间客户端会经历短暂失败,需要使用支持 Sentinel 的客户端并配置重连、有限重试和幂等。

脑裂和数据丢失

网络分区时旧 Master 可能仍接收写入,而 Sentinel 在另一侧提升新 Master。网络恢复后旧 Master 降为 Replica,它在分区期间接收的写入可能丢失。

可通过限制 Master 在可用 Replica 不足或复制延迟过大时拒绝写入,降低脑裂损失。但这是用可用性换数据安全,仍无法提供严格共识一致性。

Redis Cluster

Cluster 将 16384 个 Slot 分配给多个 Master,每个 Master 管理部分数据,并可配置 Replica。

Key → CRC16 → Slot 0..16383 → 对应 Master

它解决:

  • 数据容量超过单机内存。
  • 写入和读取压力水平分散。
  • 单 Master 故障时由 Replica 提升。

MOVED 和 ASK

客户端请求到错误节点时:

  • MOVED 表示 Slot 已稳定属于另一个节点,客户端应更新拓扑缓存。
  • ASK 常见于 Slot 迁移过程中,表示本次请求临时去目标节点,但不立即永久修改归属。

生产应使用支持 Cluster 拓扑感知的客户端,不要自己手写重定向逻辑。

Cluster 的限制

  • 多 Key 操作通常要求 Key 在同一 Slot。
  • 故障切换仍可能丢失未同步写入。
  • Slot 迁移时 Big Key 会造成抖动。
  • 节点扩缩容涉及数据迁移和带宽。
  • 热 Key 可能让单 Slot、单节点过载。
  • Cluster Bus 和节点数量增加运维复杂度。

Sentinel 和 Cluster 怎么选

  • 数据量能放入单机、主要需要自动主从切换:Sentinel。
  • 数据量或吞吐需要水平分片:Cluster。
  • 强一致事务、跨 Key 复杂关系:重新评估 Redis 是否适合做事实源。

云厂商代理版 Redis 可能隐藏 Sentinel 或 Cluster 细节,但数据丢失窗口、分片限制和故障语义仍需向厂商确认。

故障切换期间客户端设计

  • 使用连接池和拓扑感知客户端。
  • 设置连接、命令和重试超时。
  • 只对幂等操作进行有限重试。
  • 写失败不能无限重试并堵塞业务线程。
  • 关键写入要有数据库或消息日志作为事实源。
  • 熔断和降级避免重连风暴。

数据恢复流程

  1. 隔离故障实例,避免继续接受写入。
  2. 保存 RDB、AOF 和日志副本。
  3. 在隔离环境验证文件完整性。
  4. 启动临时实例加载数据。
  5. 对比业务数据库或事件日志进行校验。
  6. 根据恢复点补偿缺失数据。
  7. 灰度切换流量并持续观察。

不要直接拿未经验证的持久化文件覆盖线上当前数据。

监控指标

  • used_memory、RSS 和内存碎片率。
  • RDB/AOF 最近成功时间和失败次数。
  • AOF 重写状态和文件大小。
  • 主从复制 Offset 和延迟。
  • Replica 连接状态与全量同步次数。
  • Sentinel 切换事件。
  • Cluster Slot 覆盖和失败节点。
  • 磁盘容量、Fork 耗时和 COW 内存。

容易踩坑的地方

  • 开启 AOF 就绝对不丢数据。
  • 有 Replica 就等于完成备份。
  • Sentinel 能解决数据分片。
  • Cluster 能提供强一致。
  • Redis 只使用内存,磁盘性能不重要。
  • Fork 不会影响线上延迟。
  • 故障切换后客户端会自动无感恢复。

常见问题

追问 1:RDB 和 AOF 应该怎么选?

缓存可只使用 RDB 或接受重建;重要数据通常同时使用 RDB 与 AOF,并选择 Everysec 等合适刷盘策略。但 Redis 仍不应替代关键业务事实数据库。

追问 2:AOF Everysec 会丢多少数据?

通常可能丢失最近约一秒尚未同步磁盘的数据,但具体还受操作系统、磁盘和 Redis 实现影响。机器或磁盘故障场景不能做绝对承诺。

追问 3:为什么主从切换会丢数据?

复制异步,Master 已确认但尚未发送或 Replica 尚未应用的写入,在原 Master 故障后不会存在于新 Master。

追问 4:Sentinel 需要几个节点?

通常至少三个并部署在不同故障域,以形成多数判断。还要根据 Quorum 和故障转移授权配置,不能只看进程数量。

追问 5:Redis Cluster 为什么是 16384 个 Slot?

Slot 是 Key 到节点之间的逻辑分片层,便于迁移和拓扑管理。固定数量在集群消息开销和分片粒度间折中,客户端无需为每个 Key 保存节点映射。

追问 6:如何减少脑裂造成的数据丢失?

限制 Master 在可用 Replica 数不足或复制延迟过大时拒绝写入,将节点分布在合理故障域,并让关键业务拥有外部事实源和补偿。这会牺牲部分可用性。

追问 7:持久化文件损坏怎么办?

先复制原文件,在隔离环境使用官方检查和修复工具评估,再结合历史备份和业务事实源恢复。不要直接在唯一线上副本上操作。