"线上Redis明明开了AOF,为什么宕机后丢了两小时的数据?"——去年夏天一个凌晨,我被这个报警电话惊醒。当时我们的订单系统Redis集群突然崩溃,重启后发现aof_rewrite_in_progress标志位卡在1,而最近一条完整AOF日志停留在两小时前。你以为的AOF持久化,可能和你理解的完全不是一回事。
真实场景:高并发下的AOF隐患
我们当时的环境:
- Redis 6.2集群,混合持久化(RDB+AOF)
- 峰值QPS 12万,平均单个实例内存占用8GB
appendfsync everysec配置,理论上最多丢1秒数据
问题出现在大促期间:凌晨2点流量突增触发自动扩容,新节点加入集群时老节点突然崩溃。恢复后发现appendonly.aof文件最后有效记录停留在23:47,而崩溃发生在01:53——整整丢了126分钟的数据。
根因:AOF重写触发时的数据黑洞
- 你以为AOF重写只是后台默默生成新文件?太天真了! 看这段监控脚本抓到的异常:
# !/bin/bash while true; do redis-cli info persistence | grep -E 'aof_enabled|aof_rewrite_in_progress' redis-cli info memory | grep used_memory_human sleep 1 done当出现以下组合时危险就来了:
aof_rewrite_in_progress:1持续超过60秒used_memory_human波动剧烈- 突然出现
aof_current_size清零
- 根本原因是AOF重写期间的双缓冲机制:
- 主线程继续把新命令写入AOF旧缓冲区(AOF buf)
- 子进程通过
fork生成内存快照写新AOF文件
- 一旦重写失败,清空的缓冲区数据就真的丢了
致命配置:这些参数组合会放大风险
这是我们当时踩坑的配置(错误示范):
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 1gb aof-rewrite-incremental-fsync no # 这个最致命!对比优化后的配置:
auto-aof-rewrite-percentage 70 # 提前触发重写 auto-aof-rewrite-min-size 4gb # 减少重写频率 aof-rewrite-incremental-fsync yes # 必须开启! aof-load-truncated yes # 崩溃后救急用关键差异:
- 原配置导致单次重写数据量过大(实测8GB内存重写需要47秒)
- 禁用增量fsync时,操作系统可能将整个AOF文件写入队列(我们实测卡顿了11秒)
数据丢失的完美风暴
通过
redis-benchmark模拟出的故障时间线:阶段 原配置耗时 优化后耗时 fork子进程 2.3s 1.8s RDB部分生成 28.4s 19.7s AOF缓冲切换 9.1s 3.2s 全程阻塞时间 41.6s 26.3s 当原配置遇到内存压力时,
避坑指南:AOF持久化必须知道的七件事
aof_delayed_fsync指标:超过100就要告警no-appendfsync-on-rewrite yes:除非你能容忍分钟级数据丢失aof-rewrite-incremental-fsync必须开启:这是写入性能和数据安全的权衡点aof_rewrite_in_progress:从库接替主库时若遇重写会数据错乱redis-check-aof --fix能救急但会丢数据最佳实践:我们的三阶段解决方案
现在我们的系统里多了这段保护逻辑(Python示例):
def safe_rewrite_aof(conn): if conn.info('persistence')['aof_rewrite_in_progress']: raise Exception("已有重写在进行中") mem_usage = conn.info('memory')['used_memory'] if mem_usage > 6 * 1024**3: # 超过6GB时 conn.bgsave() # 先做RBA快照 timeout = min(30, mem_usage / (100*1024**2)) # 每100MB给1秒 if not conn.execute_command('BGREWRITEAOF', 'TIMEOUT', timeout): conn.execute_command('AOF SUSPEND') # 紧急刹车核心逻辑:
- 重写前强制检查内存用量
- 动态计算超时时间(8GB内存约80秒)
- 超时后立即中止防止雪崩
- AOF不是开箱即用的持久化方案,而是需要精心调校的精密仪器。你在项目中是怎么平衡AOF的安全性和性能的?欢迎分享你的实战经验——特别是那些教科书上永远不会写的"脏技巧"。