一、两种方式的核心差异
| RDB | AOF | |
|---|---|---|
| 存什么 | 某一时刻的数据快照(二进制) | 每条写命令的日志(文本) |
| 文件大小 | 小 | 大(可重写压缩) |
| 恢复速度 | 快 | 慢(要重放命令) |
| 数据丢失 | 可能丢几分钟 | 取决于 appendfsync,最坏丢 1 秒 |
| 性能影响 | fork 时可能卡顿 | 持续写盘,always 影响明显 |
二、RDB:快照
save 900 1 # 900 秒内至少 1 次写入就存
save 300 10
save 60 10000
dbfilename dump.rdb
生成快照时 Redis 会 fork 一个子进程,由子进程写文件,主进程继续服务。fork 本身是阻塞的,耗时与内存大小正相关(内存越大越慢),这是 RDB 最大的风险点。Linux 的 copy-on-write 让子进程与父进程共享内存页,但写入频繁时会触发页复制,内存占用可能短时翻倍。
所以:内存 30GB 的实例,fork 可能阻塞几百毫秒,要评估是否能接受。
三、AOF:命令日志
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec # always / everysec / no
| 策略 | 行为 | 丢失窗口 |
|---|---|---|
always | 每条命令都 fsync | 几乎不丢,性能最差 |
everysec | 每秒 fsync 一次 | 最多丢 1 秒(推荐) |
no | 交给操作系统 | 可能丢几十秒 |
生产环境用 everysec,是性能与安全的平衡点。always 在写入量大的场景会让 QPS 掉一个数量级。
AOF 会不断变大(记录了所有写命令),需要重写:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
重写同样靠 fork 子进程,把当前数据「翻译」成最小命令集。
四、混合持久化(推荐)
Redis 4.0+ 支持:
aof-use-rdb-preamble yes
AOF 文件的前半部分是 RDB 格式的快照,后半部分是增量命令。好处是恢复快(先加载 RDB)且丢得少(增量命令补齐)。开启 AOF 时建议同时打开这个选项。
五、恢复流程
Redis 启动时:
- 如果 AOF 开启,优先加载 AOF(
appendonly.aof),因为它的数据更完整。 - 否则加载 RDB(
dump.rdb)。 - AOF 文件损坏时,可以用
redis-check-aof --fix修复。 - RDB 文件损坏基本无法修复,只能靠备份。
备份策略:定期把 dump.rdb / appendonly.aof 拷贝到另一台机器或对象存储。持久化只解决「进程重启」,不解决「磁盘坏了」「误删实例」。
六、主从与持久化
- 从库默认也会持久化,但通常建议从库关闭 RDB 保存、只保留 AOF 或都不开,由主库负责持久化,减少从库
fork卡顿。 - 主库关闭持久化 + 主从切换,有丢数据风险:新主可能没有旧主最后的数据。
WAIT命令可以让写入同步到 N 个副本,但对性能有影响。
七、该不该开持久化
| 用途 | 建议 |
|---|---|
| 纯缓存(丢了能回源) | 可以只开 RDB,甚至不开 |
| 会话/购物车(丢了影响体验) | AOF everysec + 定期备份 |
| 队列/计数(丢了是事故) | AOF everysec + 主从 + 备份,且业务要能补偿 |
| 严格不能丢 | 不该用 Redis 做主存储 |
最后一条很重要:Redis 的定位是内存数据库,即使全开持久化,也不能提供关系型数据库级别的事务与一致性保证。
八、常见故障
MISCONF Redis is configured to save RDB snapshots...:RDB 保存失败(磁盘满、权限错),Redis 停止写入。要么修好磁盘,要么临时CONFIG SET stop-writes-on-bgsave-error no(不建议长期)。fork失败 / 延迟飙升:内存过大或vm.overcommit_memory设置不当,建议设为 1。- AOF 文件巨大:检查重写是否被禁用,或写入量异常。
小结
RDB 快、文件小、可能丢几分钟;AOF 丢得少、恢复慢;生产用 appendonly yes + everysec + aof-use-rdb-preamble yes;持久化不等于备份,必须另有异地备份。