4. RDB配置实战
RDB 的可靠性并不取决于“是否开启”,而取决于四个配置维度是否协同:何时触发快照(save 规则)、用什么方式触发(bgsave 与 save 命令)、失败时是否继续写入(stop-writes-on-bgsave-error)、快照文件本身如何压缩与校验(rdbcompression、rdbchecksum)。本节围绕这四项展开,并给出可直接落地的配置样例与验证方法。
一、save 规则:把“多久、多少次”翻译成触发条件
Redis 的自动快照由 save 指令定义,格式为 save <seconds> <changes>,含义是“在 seconds 秒内,如果发生了至少 changes 次写操作,就触发一次快照”。它本质上是一个“时间窗口 + 变更计数”的双阈值条件,而不是定时任务。默认配置通常为:
save 3600 1
save 300 100
save 60 10000
这三条规则是“或”的关系:任意一条满足即触发。例如 60 秒内累计 10000 次写入会触发,300 秒内累计 100 次写入也会触发。需要特别注意的是,后写入的 save 规则不会覆盖前面的规则,它们是叠加的;如果要清空默认规则,必须先写 save "",再追加自定义规则,否则旧规则仍然生效。
规则设计要结合业务写入强度。以“缓存 + 会话”场景为例,若 QPS 约 2000、写比例约 30%,则 60 秒约产生 36000 次写入,此时 save 60 10000 会频繁触发,可能造成周期性 fork 抖动;可改为 save 900 1 与 save 300 1000,把触发频率控制在可接受范围。反之,若业务几乎只读,可保留 save 3600 1 作为兜底,避免长时间无快照导致恢复点过旧。
二、bgsave 与 save:两种触发方式的取舍
手动触发快照有两个命令:BGSAVE 与 SAVE。二者都会生成 RDB 文件,但执行模型完全不同。
- BGSAVE:主进程 fork 出子进程,由子进程完成文件写入,主进程继续处理客户端请求。fork 瞬间会阻塞(与内存页表大小相关),但整体可用性高,是生产环境的首选。
- SAVE:在主进程内同步执行,期间完全阻塞所有客户端命令,直到 RDB 写完。仅建议在停机维护、从节点初始化或明确可接受停写的场景使用。
自动 save 规则触发的也是 BGSAVE 语义。因此,当你在日志中看到 Background saving started by pid ... 与 Background saving terminated with success,说明一次后台快照完成;若看到 Background saving error,则要结合下一节的失败策略处理。
实际运维中,建议用 INFO persistence 观察关键字段:rdb_bgsave_in_progress 表示是否有 BGSAVE 正在执行,rdb_last_bgsave_status 表示最近一次结果,rdb_last_save_time 表示最近一次成功快照的时间戳。若 rdb_bgsave_in_progress:1 长时间不归零,通常意味着磁盘写入过慢或内存过大,需要排查 I/O 与 fork 耗时。
三、stop-writes-on-bgsave-error:失败时的“刹车”策略
当 BGSAVE 失败(常见原因:磁盘满、权限错误、fork 失败、RDB 文件被占用),Redis 默认会进入一种保护状态:stop-writes-on-bgsave-error yes。此时所有写命令返回错误 MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk,读命令仍可执行。
这个默认值的设计意图是:宁可拒绝写入,也不让数据在“无法持久化”的状态下继续累积。但它也可能造成业务侧大面积写失败。因此需要根据场景决策:
- 若 RDB 是唯一持久化手段,保持
yes,并配合磁盘告警与自动清理,避免静默丢数据。 - 若已启用 AOF 且 AOF 正常,可评估设为
no,让写入继续,但必须监控 AOF 状态,防止“双失效”。 - 无论取值如何,都应把
rdb_last_bgsave_status纳入监控,而不是等业务报错才发现。
排查时可按顺序检查:df -h 看磁盘余量、ls -l 看 dump.rdb 权限与属主、dmesg 看是否 OOM 导致 fork 失败、INFO memory 看 used_memory 与 maxmemory 关系。修复后执行一次 BGSAVE,确认状态恢复为 ok,写命令即可自动恢复。
四、压缩与校验:rdbcompression 与 rdbchecksum
rdbcompression yes 控制是否对字符串对象使用 LZF 压缩。开启后 RDB 体积通常明显减小,代价是 fork 子进程在写盘时消耗少量 CPU。对于以字符串为主、值较长的业务(如 JSON 缓存、HTML 片段),收益明显;对于本身已是压缩格式或短字符串为主的场景,收益有限。若 CPU 是瓶颈且磁盘充足,可设为 no 换取更低的快照开销。
rdbchecksum yes 控制是否在 RDB 文件末尾写入 CRC64 校验和。开启后,加载 RDB 时会校验文件完整性,能发现截断或位翻转;代价是写入与加载时多一次 CRC 计算。生产环境建议保持 yes,因为 RDB 是恢复的最后一道防线,校验失败时 Redis 会拒绝加载并报错,避免把损坏数据带入内存。若追求极致加载速度且文件传输链路可靠,可评估关闭,但需自行承担损坏风险。
五、一份可参考的配置与验证流程
下面给出一份面向“中等写入、磁盘可靠、需要快速恢复”场景的示例配置(属于教学示例,实际需按业务压测调整):
save ""
save 900 1
save 300 1000
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
验证步骤建议如下:先执行 CONFIG SET save "900 1 300 1000 60 10000" 动态生效(注意 CONFIG SET save 会整体替换规则),再用 CONFIG GET save 确认;随后执行 BGSAVE,通过 INFO persistence 观察 rdb_bgsave_in_progress 从 1 回到 0、rdb_last_bgsave_status:ok;最后检查 dump.rdb 的修改时间与大小,确认压缩生效(对比关闭压缩前后的体积差异)。若需要验证校验,可复制一份 RDB 并人为截断尾部若干字节,再用 redis-check-rdb 检查,观察校验失败提示,从而理解 rdbchecksum 的实际作用。
save "" 与后续 save 规则写在同一行或漏写,否则可能得到“无自动快照”或“规则叠加不符合预期”的结果。修改 save 规则后,务必用 CONFIG GET save 复核最终生效值。把以上四项配置串起来看:save 规则决定“何时自动拍快照”,BGSAVE/SAVE 决定“怎么拍”,stop-writes-on-bgsave-error 决定“拍失败时业务是否继续写”,rdbcompression/rdbchecksum 决定“拍出来的文件多大、是否可信”。只有这四者与磁盘容量、写入强度、恢复目标相匹配,RDB 才真正成为可依赖的恢复手段。