模块三:Redis 持久化 📅 2026/7/22 15:16:25 那次凌晨3点我差点被Redis持久化送走——一个老鸟的RDB和AOF血泪史隔壁工位的小王问我哥Redis挂了一次重启后数据丢了半截咋整我点了根烟电子烟眼神深邃这事得从那年我差点被开除说起……一、那个让我想删库跑路的夜晚事情是这样的。那年我还在某电商公司扛着双11的大旗凌晨三点被报警短信炸醒——Redis内存飙到95%主从同步延迟严重更可怕的是我手动执行了BGSAVE之后主进程整整卡了3秒多3秒啊兄弟们在分秒必争的大促场景下这3秒直接导致了一批订单状态更新失败第二天运营小姐姐拿着数据报表来找我的时候那眼神啧啧比我妈看我高考成绩还失望。后来我翻了一天的源码和配置才把这口锅从自己背上卸下来——问题出在持久化策略上。当时我只开了RDB而且save参数配置得特别激进再加上几个大key在fork时把内存折腾得够呛。从那以后我就发誓要把Redis持久化这摊事整得明明白白。今天我就用这段翻车往事把RDB和AOF这对欢喜冤家给你掰扯清楚。二、RDB那个爱拍全家福的直男RDB这东西你可以把它理解成一个直男摄影师的拍照习惯——每隔一段时间对着当前Redis内存里的所有数据咔嚓来一张全量快照存成一个.rdb文件。1. 什么时候会拍照手动拍SAVE这哥们是当场定格主进程啥也不干了就光顾着拍生产环境你敢用我敢叫你祖宗。BGSAVE这才是正常人的操作。主进程说孩儿们你们继续干活然后fork一个子进程去后台慢慢拍。自动拍配置文件里配confsave 900 1 # 900秒内至少变了1个key → 拍一张 save 300 10 # 300秒内至少变了10个key → 拍一张 save 60 10000 # 60秒内至少变了10000个key → 拍一张这个配置其实是或的关系只要满足任意一条就触发了。2. RDB文件长啥样你如果用文本编辑器打开一个.rdb文件当然不建议大概结构是这样的textREDIS 版本号(比如0009) 各个DB的数据 EOF结束标志 CRC64校验和简单说就是我是谁 → 我的数据长啥样 → 我结束了 → 你验验我是不是完整的3. RDB的好与坏优点直男也有春天文件小压缩过的适合丢到云盘里做冷备份恢复起来贼快直接加载就完事了不用重放命令对主进程影响小毕竟fork了子进程去干脏活缺点直男也是真的气人可能丢数据如果10分钟拍一次照那这10分钟里写入的数据万一Redis崩了就没了fork耗时问题这是个大坑如果内存有几十个Gfork子进程的时候虽然用了COW写时复制但fork本身需要拷贝页表这个过程主进程是卡住的。我那次就是吃了这个亏大内存 频繁BGSAVE直接导致主进程阻塞了好几秒。4. 面试官最爱问的BGSAVE时主进程能写入吗能这里面的黑科技叫Copy-On-Write写时复制。我给你打个比方你手里有一本厚厚的《Java编程思想》内存数据现在你要把它复印一份fork子进程。按照常理你得先买一台新复印机然后一页一页翻着复印全量复制这段时间你就干不了别的了。但Redis不是这么干的。它用了COW技术父进程和子进程一开始共享同一本物理书谁都不动的时候大家相安无事。只有当父进程要修改某一页的内容时它才会把那页单独复印一份在新复印的那页上修改写时复制。子进程读到的还是旧的那页。所以父进程可以继续写入但如果有大量写入操作就会触发大量的页面复制内存压力会陡增这也是为什么大key多的场景下BGSAVE期间内存会涨一截的原因。三、AOF那个记流水账的处女座如果说RDB是直男摄影那AOF就是处女座的记账本——把你对Redis做的每一个写操作都原原本本地记下来存成一个.aof文件。1. 三种记账模式AOF的核心配置是appendfsync决定了什么时候把日志写到磁盘策略怎么做的性能安全性我啥时候用always每次写操作都刷盘差最高最多丢1条钱相关的系统丢了数据会掉脑袋的那种everysec默认每秒刷一次盘中等中等最多丢1秒数据绝大多数业务场景我闭眼推荐这个no操作系统说了算好最低可能丢一堆缓存场景丢了也无所谓大多数业务场景我一般无脑everysec省心。上次有个哥们非要挑战always结果QPS直接腰斩被运维大哥追着骂了三条街。2. AOF重写给记账本瘦身记账时间长了AOF文件会越来越大比如你先把key1再改成2再改成3AOF里会把三条set命令都记下来。恢复的时候要一条条重放慢得要死。所以Redis搞了个AOF重写Rewrite说白了就是不看旧的AOF文件怎么写的直接根据当前内存里的数据生成一套新的、最精简的命令集。比如当前key3那重写后的AOF里就只记一条set key 3。触发方式手动BGREWRITEAOF自动配置auto-aof-rewrite-min-size和auto-aof-rewrite-percentage重写流程面试高频主进程fork一个子进程子进程根据当前内存数据生成一个新的AOF文件重点来了重写期间父进程照常接收写请求但它会把新来的写操作同时记录到一个重写缓冲区里子进程干完活了通知父进程父进程把重写缓冲区里的内容追加到新AOF文件的末尾原子地替换掉旧AOF文件这个流程保证了重写期间的数据不丢失也是面试官常问的细节。四、RDB vs AOF到底选哪个这俩货没有绝对的优劣只有合不合适。我画个表直观对比一下对比维度RDBAOF数据完整性可能丢最后一次快照后的数据最多丢1秒everysec下文件大小小压缩过大但可以重写瘦身恢复速度快直接加载慢要一条条重放命令性能影响fork时CPU高但平时无感写入时IO开销大适用场景冷备份、灾难恢复对数据安全性要求高的场景我的真实建议小孩子才做选择成年人两个都要conf# 开启RDB save 900 1 save 300 10 save 60 10000 # 开启AOF appendonly yes appendfsync everysec # AOF自动重写 auto-aof-rewrite-min-size 64mb auto-aof-rewrite-percentage 100为什么要两个都开我跟你讲个真实场景RDB负责每天凌晨做一次全量备份类似系统还原点AOF负责实时记录类似操作日志万一Redis挂了重启的时候会优先加载AOF因为数据更全但如果AOF文件损坏了还能退一步加载RDB不至于全丢。五、Redis 4.0 的混合持久化鱼和熊掌兼得从Redis 4.0开始引入了一种混合持久化模式简直是前面两个方案的缝合怪但缝合得特别好。配置开启confaof-use-rdb-preamble yes原理是啥呢在AOF重写的时候子进程先把当前内存数据以RDB的格式写到AOF文件的开头然后再把重写期间的增量命令以AOF格式追加在后面。这样一来重启恢复的时候先加载RDB部分 →快再重放后面的一小段AOF命令 →补全增量兼顾了恢复速度和数据完整性简直完美。我现在所有生产环境都开这个。六、写给Java开发者的保命建议1. 监控这些指标别等出事了再看bashredis-cli INFO persistence重点关注rdb_last_bgsave_status上次RDB备份成功了吗rdb_last_bgsave_time_sec上次备份花了多久aof_rewrite_in_progressAOF重写是不是卡住了aof_current_sizeAOF文件多大啦超过阈值了吗2. 大key是万恶之源如果你有几个大key比如存了几百万个元素的hash或者zsetfork子进程的时候会特别慢因为fork的时候要拷贝页表页表大小和内存大小成正比。解决方案监控大key用redis-cli --bigkeys拆分大key比如按时间、按用户ID哈希分散到多个key里如果实在拆不了尽量在业务低峰期执行BGSAVE3. 磁盘IO别忽视AOF的everysec策略每秒刷一次盘如果磁盘性能不行比如机械硬盘或者和其他应用共用磁盘就可能出现IO争抢。我的建议用SSD别省那点钱最好把Redis的日志目录单独挂一个磁盘监控磁盘的iowait超过10%就要警惕了4. 备份策略要狡兔三窟我现在的标准配置bash# 每天凌晨2点RDB备份 0 2 * * * redis-cli BGSAVE # 实时AOF appendonly yes appendfsync everysec # 自动重写 auto-aof-rewrite-min-size 64mb auto-aof-rewrite-percentage 100 # 额外把rdb文件同步到云存储做异地备份脚本省略七、万一真的数据损坏了咋办这是终极问题我教你几手起死回生的骚操作AOF文件损坏Redis提供了修复工具bashredis-check-aof --fix appendonly.aof它会扫描AOF文件把不完整的、损坏的命令截掉尽量恢复可用的数据。RDB文件损坏bashredis-check-rdb dump.rdb会告诉你哪个key出了问题但修复能力有限所以RDB备份一定要多做几份。写在最后那个差点被开除的夜晚之后那次事故之后我把持久化策略彻底重构了一遍RDB AOF 双开开启混合持久化大key拆分监控告警配齐后来再也没出过类似的问题。现在每次看到新的Redis集群上线我都会问一句持久化怎么配的 看到对方支支吾吾我就知道又一个差点被送走的曾经的我。技术这东西说白了就是吃一堑长一智。我今天把这些坑都给你刨出来了你要是再踩一遍那就不是技术问题了是态度问题笑。最后送大家一句话持久化配得好半夜睡觉安稳得像猪持久化配不好凌晨三点你就是最亮的那个仔。