ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Redis持久化详解:RDB快照、AOF日志与混合持久化配置实战

Redis持久化详解:RDB快照、AOF日志与混合持久化配置实战 我最早意识到 Redis 持久化不能糊弄是有一次线上缓存集群凌晨因为内存碎片引发连锁崩溃重启之后发现缓存直接回到半个月前的状态。细查下来主节点 RDB 快照策略配的 60 秒内 10000 次写入才触发凌晨低峰期根本攒不够写入次数从节点 AOF 虽然开了但 appendfsync 看着默认配置没动结果每秒刷盘在突发流量下丢了最后几秒写命令。那次事故之后我把Redis 命令原理与应用这个系列的持久化部分彻底重写了一版今天这篇就是基于那轮沉淀整理的。Redis 持久化本质上是解决一个问题内存数据如何安全落地。Redis 所有数据默认存在内存里进程一挂、机器断电、容器被重新调度数据就没了。持久化就是把内存中的数据以某种形式写到磁盘让 Redis 重启后能把数据找回来。这篇文章覆盖 RDB 快照、AOF 日志、混合持久化三种方式从命令原理、配置文件、触发机制到恢复流程、备份策略、故障排查全部讲透。适合三类人看刚接触 Redis 想搞懂持久化机制的初学者正在配置 Redis 生产环境不知道如何选型的后端工程师以及已经被线上数据丢失事故折磨过、想系统性排查问题的运维和 DBA。这篇文章不会只贴配置项然后说这样做就行我会把每个关键选择背后的为什么也一并讲清楚。比如 RDB 的 fork 子进程为什么不会导致内存翻倍AOF 为什么采用写后日志而不是写前日志混合持久化到底是把什么混在了什么里面。这些原理搞懂了配置和排障都是水到渠成的事。1. 持久化的整体定位与设计逻辑1.1 内存数据库为什么绕不开持久化Redis 的核心卖点是快所有读写都在内存完成单线程事件循环下能达到十万级 QPS。但这个快是有代价的内存是易失性存储进程退出、操作系统重启、物理机断电内存中的数据就会全部消失。如果把 Redis 当作纯缓存用丢数据影响可控大不了后端数据库扛一下重新把热点数据加载回缓存即可。但如果把 Redis 当作数据库、消息队列或者分布式锁的存储层来用数据丢失就是事故而且是那种你想解释都不知道怎么解释的事故。我在实际项目中见过好几类因为持久化配置不当引发的诡异问题。最典型的一类是我以为有备份其实等于没有。另一个典型问题是主从架构下从节点重启后因为本地没有完整持久化文件只能向主节点发起全量同步把主节点的 RDB 文件拉过来加载。如果主节点持久化也关了内存里没有完整数据全量同步直接失败主从链路一直处于断连状态。所以持久化不只是防机器挂了丢数据这一层它还承担了主从复制、集群故障恢复、数据迁移等多个环节的基础能力。1.2 RDB 和 AOF 是两条完全不同的技术路线Redis 的持久化从设计上分成两个流派。RDBRedis DataBase是内存数据的二进制快照相当于你在某个时间点把整个 Redis 的内存状态拍了一张照片存成一个压缩的二进制文件。AOFAppend Only File是写命令日志Redis 每执行一条写命令就把这条命令追加到日志文件末尾重启时把日志里的命令重新执行一遍就能恢复出当时的数据状态。这两个方案各有各的哲学。RDB 的思路是定期存档优点是文件体积小、加载速度快缺点是在两次快照之间发生宕机这段时间内的数据会丢。AOF 的思路是全程记账优点是数据丢失窗口可以压到秒级甚至不丢缺点是日志文件随着写入量增长迅速膨胀而且恢复时需要逐条重放命令启动速度比 RDB 慢。早期版本的 RedisRDB 和 AOF 是二选一的关系默认只开 RDB。Redis 4.0 引入了混合持久化把两者融合到同一个 AOF 文件里文件的头部是一个完整的 RDB 快照快照之后追加的是新产生的写命令。这样加载时先快速读 RDB 部分再用增量 AOF 补上最近的变化兼顾了 RDB 的加载速度和 AOF 的低丢失率。现在新项目开持久化我基本都是推荐混合模式。1.3 持久化和主从复制是两个独立但协作的机制这里有个常见的认知误区很多人觉得有了主从复制就不需要持久化了。从节点宕机了可以从主节点同步主节点挂了可以切从那持久化是不是多此一举实际上主从复制本身严重依赖持久化文件。从节点第一次连接主节点或者从节点落后太多主节点都要生成一份 RDB 快照发给从节点这个 RDB 快照就是持久化机制的产物。如果主节点把 save 和 appendonly 全关了主从全量同步时 Redis 会临时生成一个 RDB 文件但这是内存中当前数据的快照如果你在同步完成前主节点崩溃这份快照也不会被保留复制链路直接断裂。生产环境里主节点和从节点都应该开启持久化只是侧重点可以不同。主节点侧重低丢失率建议开 AOF 或混合持久化从节点侧重数据冗余和灾备可以开 RDB 做周期性快照备份。两个机制搭配起来才能构建一条完整的数据安全链路。从能用到扛得住故障差的就是这层理解。2. RDB 快照的原理与实操要点2.1 RDB 的三种触发方式与优先级判断RDB 的触发方式有四种。第一种是人工执行save命令这个命令会阻塞 Redis 主进程直到快照写完才返回期间所有读写请求都会被卡住。数据量大的时候save执行几十秒甚至几分钟都是有可能的线上环境基本没人敢直接敲。第二种是人工执行bgsaveRedis 主进程 fork 出一个子进程由子进程负责把数据写入 RDB 文件主进程继续服务请求这是线上最常用的手动触发方式。第三种是由配置文件里的 save 规则自动触发比如save 900 1表示 900 秒内至少有 1 次键修改就执行 bgsave。第四种是在 Redis 收到shutdown命令正常关闭时如果配置了 RDB会先执行一次 save 再退出。这里需要特别注意save和bgsave的区别。save是同步的直接在主进程里把内存数据遍历写入临时文件整个过程阻塞bgsave是异步的主进程 fork 出子进程子进程完成数据写入主进程继续处理请求。如果你用命令手动触发 RDB永远选bgsave不要选save。有些人习惯用save来做快速备份在小数据量的开发环境里问题不大但一旦数据量上了几个 GB线上就会出现明显的请求超时。2.2 COW 机制bgsave 为什么不会让内存翻倍很多人第一次听到 bgsave 是 fork 子进程来写数据第一反应是内存里有一份完整数据fork 出来一个子进程那内存占用不就变成两倍了吗实际上不是。Linux 的 fork 系统调用结合写时复制Copy-On-WriteCOW机制让这个过程的额外内存消耗远低于想象。fork 创建子进程时并不会真的把父进程的所有内存数据复制一份给子进程。它复制的是页表子进程的页表项和父进程指向相同的物理内存页。这些内存页被标记为只读父子进程共享。之后如果主进程要修改某个内存页比如处理一个新的写命令改变了某个键的值内核发现这个页面被共享会先在物理内存中分配一个新页把旧页内容复制过去再让父进程的页表指向新页。子进程呢它从头到尾看到的还是 fork 那一刻的内存快照因为父进程修改过的页面都已经通过 COW 机制和子进程分道扬镳了。子进程就拿着这份始终不变的快照慢慢序列化成 RDB 文件。所以 bgsave 期间的内存增量不是整个数据集的大小而是主进程在快照生成期间改动了多少数据的近似值。如果你在 bgsave 期间疯狂写入大量新键COW 复制的页面会变多内存峰值就会上涨。这也是为什么线上大实例做 bgsave 之前要么业务低峰期操作要么预留 30% 到 50% 的内存余量。另一种更彻底的规避方式是用 Redis 的fork耗时监控如果 fork 时间过长说明内存页表太大或系统内存压力高需要检查内存碎片和物理内存规格。2.3 RDB 文件的核心配置与备份文件管理RDB 相关的配置项不算多但每个都值得认真确认一遍。dbfilename默认是 dump.rdbdir指定 RDB 文件和 AOF 文件存放目录这个目录必须存在且有写权限否则持久化静默失败。save配置可以有多条满足任意一条就会触发 bgsave如果你不想要自动快照就配置成save 来禁用。生产环境常见的配置是save 900 1、save 300 10、save 60 10000含义分别是 15 分钟内有 1 次写入、5 分钟内有 10 次写入、1 分钟内有 10000 次写入。stop-writes-on-bgsave-error这个配置默认是 yes含义是如果 bgsave 执行失败Redis 会拒绝所有写请求。这个设计的出发点是防止数据持续更新但备份落后太多的极端场景但它很容易让人意外踩坑。比如磁盘写满、权限变更、磁盘 IO 卡死都会导致 bgsave 失败然后线上突然就开始报READONLY You cant write against read only replica或者直接写入报错。排查时先看日志里有没有Background saving error有的话优先处理磁盘问题别急着去调业务代码。如果你能接受备份暂时失败但业务照常写入可以把 stop-writes-on-bgsave-error 设为 no但我不建议这么做因为你会失去对数据可恢复性的确定性。RDB 文件的加载是无感的。Redis 启动时只要dir目录下存在dbfilename指定的文件主进程就会自动加载。加载过程中 Redis 阻塞不接任何请求加载完成后日志会打印DB loaded from disk。如果你发现启动后数据不对先检查日志里有没有Bad file format或Short read or OOM loading DB这两种错误分别对应文件损坏和加载过程中内存不足。3. AOF 日志的机制与实操细节3.1 AOF 为什么是写后日志而不是写前日志AOF 采用的是写后日志write-ahead logging 的反面。Redis 先执行写命令修改内存数据然后把这条命令追加到 AOF 文件的缓冲区再根据刷盘策略决定何时把缓冲区内容真正同步到磁盘。这和 MySQL 的 WALWrite-Ahead Logging正好相反。MySQL 是先把日志写到磁盘再修改数据页防止数据页写入一半崩溃导致无法恢复Redis 是先改内存再写日志。Redis 选择写后日志的原因主要有两个。第一AOF 记录的是已经执行成功的命令不会把语法错误、执行失败的命令写进日志重放时不会出现日志里有但当时没执行成功的脏数据。第二AOF 写日志是在命令执行完之后对当前请求的延迟影响相对可控不会像写前日志那样每次写操作都要先等日志落盘再继续。但写后日志也有代价如果命令执行完、日志还没来得及落盘时进程崩溃这条命令对应的数据变更就会丢。所以 AOF 的关键就在于刷盘策略也就是appendfsync的配置。3.2 appendfsync 三种策略的取舍appendfsync有三个值always、everysec、no。always是每执行一条写命令就立即把缓冲区内容通过 fsync 同步到磁盘数据最安全最多丢失一条命令但性能开销最大。everysec是每秒执行一次 fsync把这一秒内累积的写命令同步到磁盘性能和数据安全性比较均衡最多丢失一秒的写命令。no是把刷盘时机完全交给操作系统由操作系统根据脏页阈值决定何时写回磁盘丢数据的窗口无法预测可能远超过一秒。默认配置是everysec这也是我在绝大多数场景下的推荐配置。理由很简单每秒一次 fsync 的磁盘写入频率对普通固态硬盘来说完全不是瓶颈但数据安全提升了一个量级。只有在业务对数据零丢失有硬性要求、且能接受性能明显下降的时候才考虑always。而no这个值说实话我找不出在生产环境选它的理由它把数据的命运交给了内核的刷盘脏页逻辑什么时候丢、丢多少全是未定义的这和确定性原则完全相悖。这里顺便提一个细节everysec并不是严格每秒刷一次而是 Redis 的后台任务每秒检查一次如果有待刷盘的缓冲区内容就执行 fsync。如果 fsync 耗时超过一秒Redis 会累积延迟此时可能出现日志记录Asynchronous AOF fsync is taking too long的告警。遇到这种情况优先排查磁盘负载而不是直接改配置。3.3 AOF 重写机制文件膨胀的自我修复AOF 是追加日志每一条写命令都会追加进来。时间长了文件必然会膨胀。同一个键被更新一万次AOF 里就会有一万条对该键的写命令但恢复时只需要最后一条。AOF 重写机制就是为了解决这个问题根据当前内存中的数据状态生成恢复这些数据所需的最少命令集写到一个临时文件里再替换掉旧的 AOF 文件。触发 AOF 重写有两种方式。人工执行bgrewriteaof命令Redis 会 fork 子进程执行重写。自动触发依赖两个配置auto-aof-rewrite-percentage默认 100auto-aof-rewrite-min-size默认 64mb。含义是当 AOF 文件大小超过 64MB且比上一次重写后的文件大小增长了 100% 时自动触发重写。实践中我会把 min-size 调大一点比如 1GB避免小实例频繁触发重写造成不必要的磁盘 IO。重写过程有几个容易忽略的细节。子进程重写期间主进程仍然处理写请求新的写命令会被同时追加到旧的 AOF 文件缓冲区和重写缓冲区。重写完成后主进程会把重写缓冲区里的增量命令追加到临时文件末尾再用 rename 原子替换旧文件。如果重写期间主进程崩溃临时文件会被丢弃旧 AOF 文件仍然可用。这个设计的核心思想是重写失败不影响原有的 AOF 文件理解了这个机制你就知道bgrewriteaof其实是一个相当安全的后台操作。3.4 AOF 文件结构与恢复流程AOF 文件是纯文本格式里面是一条一条 Redis 协议格式的命令形如*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n。Redis 启动时如果配置了appendonly yes会优先加载 AOF 文件而不是 RDB 文件。加载时逐条读取命令并执行直到文件末尾。如果文件末尾截断了比如机器突然断电默认配置aof-load-truncated yes会让 Redis 忽略最后一条不完整的命令并正常启动同时日志会给出警告。如果 AOF 文件不仅末尾截断而是在中间就损坏了Redis 不会直接拒绝启动。你可以用redis-check-aof --fix appendonly.aof来修复。它会扫描文件找到第一个损坏的命令把损坏位置之后的所有内容丢弃然后重写文件。注意这个过程会把损坏点之后的数据全部砍掉所以修复前最好先备份原始文件。修复之后启动 Redis再配合bgrewriteaof重写一次让文件恢复到干净状态。AOF 开启后的一个常见误区是appendonly yes 之后 RDB 就没用了。实际上如果你配置的是混合持久化模式AOF 文件的头部就是一份 RDB 快照RDB 相关的配置和备份策略照样有价值。即使不用混合模式周期性的 RDB 备份也可以作为 AOF 文件的补充在 AOF 文件彻底损坏且修复失败时兜底恢复。4. 混合持久化鱼与熊掌的兼得方案4.1 aof-use-rdb-preamble 到底做了什么Redis 4.0 引入的混合持久化用一个配置项就能开启aof-use-rdb-preamble yes。开启之后AOF 文件不再是纯文本命令日志而是变成了RDB 快照 AOF 增量命令的复合文件。文件开头是 RDB 二进制格式的完整数据快照快照的结束位置之后接着追加的是快照生成之后产生的新写命令这部分保持 AOF 文本格式。Redis 启动加载时先识别文件头部是不是 RDB 格式是的话先加载 RDB 部分然后继续按 AOF 格式重放后面的增量命令。如果文件不是混合格式就按纯 AOF 方式加载。这个判断是自动完成的不需要额外配置。加载速度上混合模式比纯 AOF 快得多因为 RDB 部分是二进制数据直接载入而不是逐条执行写命令数据安全上后续的 AOF 增量命令可以做到秒级丢失窗口配合 everysec 刷盘策略基本就是最优组合。4.2 混合持久化对运维习惯的改变开启混合持久化之后AOF 重写的效果更明显了。重写生成的临时文件天然就是RDB 快照 重写期间增量的结构。你不再需要分别维护 RDB 和 AOF 两套备份一个 AOF 文件里就包含了完整的可恢复数据。这带来的运维变化是磁盘上持久化文件从两个变成一个备份命令从同时拷 dump.rdb 和 appendonly.aof变成只拷 appendonly.aof恢复时也不用纠结到底该用哪个文件。文件体积方面RDB 是压缩格式混合后 AOF 文件比纯 AOF 文本小很多磁盘占用和恢复时间都更理想。我在生产环境上现在所有新部署的 Redis 实例都默认开启混合持久化旧实例也在一轮轮升级中完成了迁移。这个配置是 Redis 官方推荐的默认方向新版本 Redis 甚至可以直接配置 appendonly yes 而不用担心普通 AOF 的膨胀问题。4.3 混用模式下的配置清单参考混合持久化的配置不是改一个 aof-use-rdb-preamble 就完事你需要把整个持久化相关的配置项统一梳理一遍。我自己常用的最小配置模板是这样# RDB 配置 save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data/redis # AOF 配置 appendonly yes appendfilename appendonly.aof appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 1gb aof-load-truncated yes aof-use-rdb-preamble yes这套配置下RDB 自动快照仍然生效作为额外的灾备手段。AOF 文件采用混合格式既能快速加载又能把丢失窗口控制在秒级。no-appendfsync-on-rewrite保持 no意思是 AOF 重写期间仍然正常执行 fsync数据安全优先于重写效率。如果你重写期间磁盘 IO 压力非常大可以临时设为 yes 来减少一次 fsync但你要清楚这意味着重写期间丢了最多一秒的数据平时不要动它。5. 数据恢复与备份实践的完整路径5.1 从崩溃到恢复的操作流程一个完整的恢复流程我建议按下面这个顺序走不要慌着重启实例。第一步先确认数据丢失范围。info persistence命令会告诉你 RDB 和 AOF 的状态比如rdb_last_bgsave_status:ok、aof_last_bgrewrite_status:ok以及最近一次保存的时间点。第二步检查持久化文件是否完整。RDB 文件用redis-check-rdb dump.rdb校验AOF 文件用redis-check-aof appendonly.aof校验。第三步确定恢复源。如果开启了 appendonlyAOF 是首选因为它的丢失窗口更小如果 AOF 损坏且修复失败退回 RDB。第四步把文件放到配置文件 dir 指定的目录下文件名严格对应然后启动 Redis。第五步启动后马上执行dbsize和抽查关键键确认数据量符合预期再对外开放流量。这个流程里最容易出错的是目录和文件权限。很多次我们看到数据怎么没恢复的救火现场最后定位到的问题是文件放错了目录或者 Redis 进程用户没有读权限。Redis 启动时如果找不到持久化文件不会报致命错误它会当自己是全新实例启动这时候你看到的是一个空库数据仿佛凭空蒸发。所以恢复前一定要先config get dir确认 Redis 进程实际工作的目录再对照当前的dbfilename和appendfilename。5.2 备份策略的分层设计只有持久化是不够的持久化文件本身也会损坏、会被误删、会跟着机器一起没。所以备份必须分层。第一层是 Redis 自身的持久化文件保证进程级故障能恢复。第二层是定期把持久化文件复制到独立存储。RDB 文件在生成过程中是一个临时文件bgsave 完成后再 rename 成正式文件所以直接拷贝 dump.rdb 得到的一定是完整快照AOF 文件是持续追加写的拷贝时可能拿到半截写入状态稳妥的做法是先执行bgrewriteaof得到一个完整干净的 AOF 文件再拷贝。第三层是异地备份。我习惯每天凌晨低峰期在从节点执行一次 bgsave之后把 dump.rdb 推送到对象存储或另一台机器的备份目录保留最近 7 天。这样即使整个机房不可用也能从异地恢复最近一天的数据。注意备份尽量在从节点做不要在主节点做避免 bgsave 期间的主节点 fork 对业务造成影响。5.3 持久化相关的监控指标info persistence的输出里有几个指标值得长期盯着看。rdb_last_bgsave_status和rdb_last_bgsave_time_sec反映最近一次 RDB 快照是否成功、耗时多久rdb_changes_since_last_save反映上次快照以来积累了多少写操作可以辅助判断当前快照配置是否过于滞后aof_current_size和aof_base_size反映 AOF 文件当前大小和上次重写后的大小能看出文件的增长趋势aof_rewrite_in_progress和aof_rewrite_scheduled反映重写是否正在进行或等待执行。另外还可以看aof_last_bgrewrite_status这个状态如果为 err说明重写失败需要关注磁盘空间和文件权限。监控告警的阈值设置可以参考两个维度fork 耗时和目标文件大小。fork 耗时超过 1 秒就要注意说明内存页表规模大或者系统负载高AOF 文件大小偏离预期增长过快说明 rewrite 触发条件需要调整或者业务写入模式发生了变化。这些指标不需要复杂的监控系统脚本定时轮询或者直接接到现有的监控平台即可。6. 线上持久化常见问题与排查实录6.1 bgsave 一直失败导致 Redis 停止写入现象线上突然无法写入报错提示MISCONF Redis is configured to save RDB snapshots, but its currently unable to persist to disk。这个报错就是stop-writes-on-bgsave-error yes在起作用bgsave 失败后 Redis 主动切断了写路径。排查步骤第一步看磁盘空间df -h检查持久化目录所在分区是否已满。这是我遇到概率最高的原因。第二步看目录权限确认 Redis 进程的运行用户对 dir 目录有写权限。第三步看系统日志有没有 IO 错误。如果磁盘空间确实满了清理旧备份、扩容磁盘之后执行bgsave手动触发一次确认状态恢复为 ok写入就会自动恢复。注意这里有一个细节磁盘满的状态下Redis 自身的日志会反复记录Background saving error但业务日志不一定能看到这种错误所以告警一定要覆盖到 Redis 的错误日志而不是只看业务接口成功率。6.2 AOF 文件损坏之后如何最小化数据丢失现象实例启动失败日志报Bad file format reading the append only file。原因通常是突然断电、磁盘故障或误操作导致 AOF 文件中间的字节异常。处理方式先备份原始文件再执行redis-check-aof --fix appendonly.aof。这个工具会定位到第一个损坏的命令把损坏点之后的内容全部截断。截断之后的数据也就是损坏点之后的所有写入必然丢失此时要评估这部分数据能否从上游业务重放比如消息队列里是否有累积的写操作或者业务是否有补偿机制。修复后启动 Redis确认数据可读再执行bgrewriteaof重写文件让 AOF 文件回到正常状态。这里不建议直接删掉 AOF 文件重启了事除非你确定 AOF 里的数据完全不重要。否则你会得到一个空库而不是一个旧库。6.3 fork 耗时过长导致请求延迟毛刺现象业务监控里偶尔出现几百毫秒的延迟尖刺集中在整点或备份执行的时间点。用latency monitor开启延迟监控或者查看info stats里的latest_fork_usec发现 fork 耗时非常高比如超过 1000 毫秒。原因分析fork 需要复制进程页表页表大小和内存规模正相关。当 Redis 数据量达到几十 GB页表复制耗时就会明显增加。另外如果系统内存已经紧张fork 还会触发系统的内存回收操作进一步加重延迟。缓解方案最直接的是控制单实例内存规模数据量大就把大键拆分到多个实例或者使用 Redis Cluster 把数据分片。其次是调整 Linux 内核参数vm.overcommit_memory 1让 fork 时不会因为内存不足检查而失败同时可以降低 fork 耗时。还有一个实用技巧把 bgsave 和 bgrewriteaof 安排在业务最低峰避免和整点缓存淘汰、定时任务撞车。6.4 主从环境下从节点应该怎么配持久化不少团队的 Redis 主从不配持久化或者只配主节点持久化理由是反正从节点能全量同步主节点。这个想法我在前面说过是危险的。从节点一旦重启它会尝试加载本地持久化文件如果本地没有它只能向主节点请求全量同步。主节点执行全量同步时首先要 bgsave 生成 RDB 快照如果一个集群里多个从节点同时重启主节点会连续多次 bgsave瞬间拉高主节点的 fork 成本、磁盘 IO 和网络带宽。我的建议是从节点同样开启持久化但策略可以和主节点不同。主节点用混合持久化模式确保秒级丢失窗口从节点用 RDB 周期快照就够了因为从节点的主要作用是数据冗余和备份源它实时同步主节点数据即使自己丢了最近几秒的写入重新连上主节点后也能增量追平。关键是不要所有节点都关持久化也不要所有节点都用同样的激进刷盘策略要根据角色分工差异化配置。这里再分享一个我在迁移环境时踩过的坑在从节点执行了slaveof no one把从节点提升为主节点之后以为数据已经完整提升但忘记确认它本地的 AOF 文件是否跟上。结果新的主节点对外服务后发现之前同步的数据还在但最近一段时间的写操作因为没有及时刷盘而丢失了。提升从节点为新的主节点之前务必执行一次bgrewriteaof或者确认aof_last_bgrewrite_status:ok让持久化文件处于完整、可恢复的状态。6.5 误操作 flushall 之后的应急恢复flushall是清空所有库的写命令它会把 RDB 快照里记录的所有键删除也会把 AOF 文件里的命令日志标记为清空。很多人以为执行了 flushall 就只能认倒霉其实还有机会关键在于你执行之后做了什么。如果在flushall之后立刻发现错误在自动 bgsave 触发之前手动执行bgsave会覆盖掉原来的 RDB 文件这是灾难性的。正确做法是立刻停止 Redis 进程或者马上把当前目录下的 dump.rdb 和 appendonly.aof 复制出来不要做任何会触发持久化的操作。然后用之前保存的旧 RDB/AOF 文件恢复。注意 AOF 模式下 flushall 命令本身也会被写入 AOF所以单纯用 AOF 恢复也不行需要用 RDB 快照配合 AOF 增量里 flushall 之前的部分来恢复操作比较复杂。在已经开启 AOF 的实例上阻止方案是先把appendonly no重启实例加载 RDB再恢复 AOF但这个方案需要经验新手最好在测试环境先演练一遍。写在最后的一点经验我自己现在无论部署什么项目Redis 持久化配置都是第一个要确认的项。倒不是觉得 Redis 特别容易崩而是它处在数据链路的关键位置上一旦出问题影响面往往很大。RDB 和 AOF 没有绝对的谁优谁劣混合持久化是目前综合体验最好的方案但核心还是要把触发机制、恢复流程、备份策略、监控告警这一整套都规整好。建议每个人都在测试环境把意外断电、kill -9、磁盘写满、AOF 文件截断这几个场景各演练一遍真正操作过你才知道文档里那些配置项在故障面前意味着什么。等你把这一套都跑通了再遇到 Redis 相关的故障心态会完全不同。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进