结论先行 故障由 AOF 尾部 65 bytes 损坏引起。完成原文件备份后,使用同版本 Redis 镜像运行 redis-check-aof --fix,截断损坏尾部,Redis 最终恢复到 loading:0,并成功返回 PONG。
记录还原了一次 Redis 无法正常完成数据加载的处理过程。由于 dump.rdb 只有约 507 KB,而主要数据集中在约 6.3 GB 的 append.aof 中,直接删除 AOF 并不可取;修复的关键是先确认损坏位置,再以最小代价截断异常尾部。
故障概览
Redis 启动后长时间处于数据加载状态,客户端执行 PING 时无法得到正常响应。运行环境如下:
|------------------|------------------------------------|
| Redis 版本 | 5.0.12 |
| 部署方式 | Docker |
| 服务端口 | 17002 |
| AOF 文件 | /home/docker/redis/data/append.aof |
| 文件大小 | 约 6.3 GB |
现场现象
启动后执行 PING:
(error) LOADING Redis is loading the dataset in memory
随后在启动日志中发现明确的 AOF 格式错误:
Bad file format reading the append only file
初步判断 Redis 能读取 AOF,但文件中存在无法解析的内容,需要进一步确认损坏发生在主体还是尾部。
排查与判断
- 检查 Redis 持久化状态
info persistence
返回结果中出现 loading:1,说明 Redis 仍在加载数据,尚未进入可服务状态。
- 核对启动日志
Reading RDB preamble from AOF file...
Reading the remaining AOF tail...
Bad file format reading the append only file
日志显示 RDB preamble 已读取,错误出现在后续 AOF tail 阶段,因此可以将问题范围收敛到 AOF 尾部增量数据。
- 比较持久化文件大小
append.aof ≈ 6.3 GB
dump.rdb ≈ 507 KB
AOF 远大于 RDB,说明主要数据依赖 append.aof。此时如果直接删除 AOF,可能造成大量数据缺失。
排查结论 本次故障属于 AOF 尾部损坏,修复目标是保留前部有效数据,仅移除无法解析的尾部字节。
修复实施
操作前提醒 redis-check-aof --fix 会修改并截断文件。务必先停止 Redis,并为原始 AOF 创建完整备份。
- 停止 Redis 容器
docker stop redis5.0.12
- 备份原始 AOF 文件
cp /home/docker/redis/data/append.aof \
/home/docker/redis/data/append.aof.bak
- 使用同版本工具修复 AOF
docker run --rm -it \
--user root \
-v /home/docker/redis/data:/data \
redis:5.0.12 \
redis-check-aof --fix /data/append.aof
这里使用 redis:5.0.12 镜像,确保检查工具与故障实例的 Redis 版本一致。数据目录以 /data 挂载,修复命令直接作用于 append.aof。
修复结果
|---------|--------------------------------|
| 检查项 | 结果 |
| AOF 总大小 | 6,723,298,839 bytes |
| 有效位置 | ok_up_to = 6,723,298,774 |
| 损坏范围 | 文件尾部 65 bytes |
| 修复结果 | Successfully truncated AOF |
结果解读 有效数据一直持续到 6,723,298,774 字节位置,仅尾部 65 bytes 被截断。相对于整个 AOF 文件,损坏范围很小,主体数据基本完整。
恢复与验证
- 重新启动 Redis
docker start redis5.0.12
- 观察数据加载状态
info persistence
启动初期仍可能看到 loading:1;等待加载完成后,状态应变为:
loading:0
- 验证服务响应
ping
PONG
恢复确认 Redis 已完成数据加载,PING 返回 PONG,服务恢复正常。
原因分析
从日志和修复结果看,本次属于 AOF 尾部损坏。常见诱因包括:
- Redis 写入 AOF 的过程中异常退出
- Docker 容器被强制停止
- 宿主机异常重启
- 磁盘写入过程被中断
本次只有最后 65 bytes 损坏,说明异常更可能发生在一次尚未完整落盘的尾部写入中;修复工具截断这一小段后,其余数据仍可被正常加载。
后续优化建议
- 恢复后重写 AOF
BGREWRITEAOF
重新生成结构干净、体积更合理的 AOF 文件。
- 配置自动 AOF 重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 1gb
- 优化宿主机内存参数
vm.overcommit_memory=1
同时关闭 Transparent Huge Pages(THP):
echo never > /sys/kernel/mm/transparent_hugepage/enabled
- 建立定期备份机制
定期备份 RDB 与 AOF 文件,并确保备份可恢复,避免单一持久化文件成为故障恢复的唯一依赖。
经验总结
- 看到 LOADING 不要只等待:应同步检查启动日志和 info persistence。
- AOF 是主要数据来源时,不要直接删除;先备份,再判断可修复范围。
- 使用与实例一致的 Redis 版本运行 redis-check-aof,降低工具差异带来的风险。
- 修复完成不等于恢复完成:必须等待 loading:0,并用 PING 等方式验证服务。
- 恢复后及时执行 BGREWRITEAOF,并完善自动重写和备份策略。