RedisNotes

第 16 章:持久化机制

zjc 于 2026-01-16 发布

这是《Redis 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Redis 是内存数据库,但可以持久化。RDB 快、小、易备份;AOF 丢失窗口小;混合持久化兼顾两者。本章讲清触发机制、文件格式、恢复流程与生产配置。

16.1 为什么需要持久化

没有持久化时,Redis 重启后数据全部丢失。这对纯缓存可以接受,但对锁任务、队列、计数、排行榜则可能是事故。

两类文件:

RDB: 某一时刻内存快照,二进制
AOF: 写命令追加日志

核心权衡:

维度 RDB AOF
文件大小
恢复速度
数据丢失窗口 取决于触发周期 取决于 appendfsync
CPU/磁盘影响 fork+子进程写文件 持续追加与重写
可读性 二进制 文本命令

16.2 RDB

save 触发

save 3600 1
save 300 100
save 60 10000

含义:满足“秒内至少修改次数”条件时触发保存。

手动:

SAVE
BGSAVE
LASTSAVE

RDB 文件

dbfilename dump.rdb
dir /data
rdbcompression yes
rdbchecksum yes

RDB 保存二进制快照,加载时直接重建对象,比重放命令快。

16.3 fork 与写时复制

BGSAVE 流程:

1. 主进程 fork 子进程
2. 子进程遍历内存,写 RDB 临时文件
3. 写完后原子替换旧 RDB

fork 后父子进程共享物理内存页,采用 Copy-On-Write:

子进程看到 fork 瞬间的数据视图
父进程继续处理写命令
被修改的页才复制

风险:

16.4 AOF

开启:

appendonly yes
appenddirname appendonlydir
appendfilename appendonly.aof
appendfsync everysec

流程:

命令执行成功
  -> 追加到 AOF 缓冲
  -> 根据策略写入文件
  -> fsync 到磁盘

appendfsync 策略

策略 行为 丢失窗口 风险
always 每条命令 fsync 最小 吞吐低、磁盘压力大
everysec 每秒一次 最多约 1 秒 推荐默认
no 交给 OS 不可控 通常不建议

everysec 后台线程执行 fsync。如果上一次 fsync 超过 2 秒仍未完成,Redis 会延迟写操作以避免无限堆积。

16.5 AOF 重写

AOF 会不断增长,重写生成一份只保留最终状态的新 AOF:

旧 AOF:
SET k 1
SET k 2
SET k 3
INCR counter
INCR counter

重写后:
SET k 3
SET counter 2

手动触发:

BGREWRITEAOF

自动触发:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-rewrite-incremental-fsync yes

percentage=100 表示 AOF 比上次重写后大小增长一倍触发;同时需满足 min-size。

16.6 混合持久化

aof-use-rdb-preamble yes

重写后的 AOF 文件:

[RDB 格式基础数据]
[AOF 增量命令]

优点:

适合大多数需要持久化的生产实例。注意老版本 Redis 或兼容工具必须支持该格式。

16.7 恢复流程

Redis 启动时:

1. 读取配置
2. 检查 AOF 开启
3. AOF 存在 -> 优先加载 AOF
4. AOF 不存在 -> 加载 RDB
5. 重建内存数据

因此当 AOF 开启且文件存在时,RDB 不会作为最新数据源。

相关配置:

aof-load-truncated yes
aof-timestamp-enabled no

aof-load-truncated 允许加载末尾被截断的 AOF,通常用于断电恢复;仍应告警并尽快补齐数据。

16.8 持久化对性能的影响

RDB

AOF

建议

  1. RDB/AOF 文件放独立磁盘或高性能盘;
  2. 控制实例大小,降低 fork 时间;
  3. 避免多个大实例同时 rewrite;
  4. 监控 latest_fork_usec、aof_delayed_fsync;
  5. 关键业务用复制和外部备份兜底。

16.9 备份策略

# 生成 RDB
redis-cli -a $PASS BGSAVE

# 查看完成时间
redis-cli -a $PASS LASTSAVE

# 复制文件
cp /data/dump.rdb /backup/dump-$(date +%F-%H%M).rdb

更安全的方式:

  1. 在从节点执行 BGSAVE
  2. 将 RDB/AOF 上传对象存储;
  3. 保留多版本;
  4. 定期演练恢复。

恢复演练:

mkdir /data/restore
cp dump-20260825.rdb /data/restore/dump.rdb
redis-server --port 6399 --dir /data/restore --appendonly no
redis-cli -p 6399 DBSIZE

16.10 生产配置模板

缓存实例:

save ""
appendonly no
maxmemory-policy allkeys-lru

允许分钟级丢失:

save 900 1
appendonly no

允许秒级丢失:

appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 1gb

不能丢:

appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
save 3600 1 300 100 60 10000

即使如此,异步复制下主故障仍可能丢失最后写入;“绝对不能丢”必须由数据库事务/消息系统/业务确认机制保证。

本章小结

思考题

  1. AOF everysec 一定最多丢 1 秒吗?哪些故障会导致更多丢失?
  2. 为什么大实例 RDB fork 期间可能出现内存增长?
  3. 纯缓存实例要不要开启 AOF?从恢复时间、磁盘和业务语义分析。