跳转到内容
seren-spark

10 持久化与高可用

重启怎么办?节点坏了怎么办?容量不够怎么办?

Section titled “重启怎么办?节点坏了怎么办?容量不够怎么办?”

学习目标 · 分清持久化、复制、Sentinel 和 Cluster 解决的不同问题,理解数据丢失窗口与客户端要求。

10.1 持久化:把内存状态带到下一次启动

Section titled “10.1 持久化:把内存状态带到下一次启动”
方式记录的是什么优点代价与边界
RDB某一时刻的数据快照文件紧凑,便于备份与加载两次快照之间的新数据可能丢失;生成快照有资源成本
AOF重建数据所需的写操作记录可按 fsync 策略控制落盘频度有写入、重写与恢复成本;不保证零丢失
同时启用快照与日志配合可综合恢复和备份需求仍需验证恢复、磁盘空间、延迟和兼容性

appendfsync everysec 是常用的折中:通常约每秒刷盘,故障时可能丢失最近约一秒的数据,异常 I/O 等条件下不能机械地保证“一秒封顶”。always 更频繁刷盘且有性能代价,no 交给操作系统调度。是否需要 AOF,取决于数据能否重建及恢复目标;纯缓存也可能因重建压力而需要持久化。

内存数据
→ 快照 →
RDB时刻 T 的状态
写操作
→ 追加 / 刷盘 →
AOF用于重建状态
→
重启加载
图 06 · 写入内存、写入文件缓冲区、刷到稳定存储,是不同的完成时刻。

BGSAVE 通常通过 fork 后的子进程生成快照,父进程继续服务,但 fork 和写时复制仍可能带来停顿或额外内存。AOF 重写根据当前数据生成更紧凑的重建表示,不是逐行压缩原日志。Redis 7+ 的多文件 AOF 与老教程单个 appendonly.aof 不同,备份和恢复需按版本文档处理完整文件集合。

下面在第 2 章的专用本地容器执行。它使用命名卷且启用了 AOF;这只是正常重启测试,不能证明机器掉电时零丢失。

# PowerShell · 仅对自己的学习容器执行
docker exec redis-learning redis-cli SET learn:persist "survives-restart"
docker exec redis-learning redis-cli INFO persistence
docker restart redis-learning
docker exec redis-learning redis-cli GET learn:persist

等容器重新就绪后,应读到 survives-restart;若刚启动就连接失败,查看日志并重试 PING。记录 aof_enabled、rdb_last_bgsave_status 等字段。不要拿一个未挂持久卷的容器删除重建实验,推断 Redis 持久化没有作用。

10.3 主从复制与 Sentinel:增加副本、发现故障

Section titled “10.3 主从复制与 Sentinel:增加副本、发现故障”

主节点处理写入,把变更异步复制给副本。副本可提供读能力或接替故障主节点,但副本读取可能落后。首次或无法增量衔接时进行全量同步;链路短暂断开且复制积压缓冲仍包含缺失部分时,可以增量补齐。

应用发现当前主节点
→
主节点读 / 写
→ 异步复制 →
副本可能短暂落后
Sentinel 监控组
→
监控、选举、切换、通知客户端
图 07 · Sentinel 负责发现和协调故障切换,不负责保存业务数据,也不做数据分片。

Sentinel 的 quorum 用于判定客观下线,真正执行切换还需要多数 Sentinel 授权等条件,不能简单背成“两个说坏了就永远能切换”。通常将多个 Sentinel 分散在独立故障域。应用使用支持 Sentinel 的客户端发现新主节点,不应把旧主 IP 永久写死。

主节点确认成功后、尚未复制的写入可能在故障切换中丢失。WAIT 等命令可以等待副本确认并缩小某些风险,但不能把异步复制变成完整强一致系统。下单后立刻读副本,还可能短暂读不到刚写的数据。

10.4 Cluster:把不同 Key 分给不同主节点

Section titled “10.4 Cluster:把不同 Key 分给不同主节点”

Redis Cluster 将 Key 映射到 16,384 个哈希槽,槽分配给多个主节点;每个主节点可配副本。客户端根据 Key 找槽,再找到负责节点。拓扑变化时处理 MOVED / ASK 重定向,通常由成熟的 Cluster 客户端完成。

Cluster 客户端
→ 按槽路由 →
主 A + 副本槽 0–5460
主 B + 副本槽 5461–10922
主 C + 副本槽 10923–16383
图 08 · 槽范围仅为示意。副本提供冗余,不等于每多一个副本就多一份可写分片容量。

多 Key 命令、Lua 和事务通常要求涉及的 Key 在同一槽。例如 order:{101}:stock 与 order:{101}:users 都使用 {101} 作为 hash tag,可落同槽。单机示例中能运行的跨 Key 操作,搬进 Cluster 后可能报 CROSSSLOT。某些客户端可以拆分部分读取,但拆分后的原子性不等价。

不要把所有 Key 都写成同一个 {global},那会让分片集中。一个超热 Key 本身也不会因为 Cluster 扩容就自动拆分;需要业务级的热点方案。Cluster 只用 DB 0,不使用 SELECT 切换逻辑数据库。

  • “有主从就自动切换”:复制本身不等于完整故障管理,Sentinel 与 Cluster 有各自机制。
  • “副本就是备份”:误删除也会复制,独立备份与恢复演练仍然有价值。
  • “小项目先上 Cluster”:节点和客户端复杂度上升;先根据容量、可用性和流量需求决定。

做一次上述正常重启验证。再为三种需求选方案:单机重启恢复、主节点故障自动切换、单机容量放不下。写明每种方案不能解决什么。

自测与答案 · Sentinel 和 Cluster 最大区别是什么?

Sentinel 通常管理不分片的一组主从,关注监控和自动故障切换;Cluster 同时做槽分片和集群故障处理。重启恢复靠持久化;自动切换需要高可用拓扑与客户端;跨单机容量需要分片或其他容量方案。它们均不能单独保证所有已确认写入在任意故障中都不丢失。

依据:持久化 · 复制 · Sentinel · Cluster