Master-slave
发布于 2019-11-08 / 16 阅读
0
0

Redis AOF格式错误问题

问题描述

Redis Version : 3.0.5

Redis服务在启动后无法正常连接,通过redis-cli连接提示

(error) LOADING Redis is loading the dataset in memory

且查看日志可发现Redis服务在频繁地重启,日志中存在报错

Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>

产生原因

Redis在启动时会读取路径下的appendonly.aof(默认名称)文件,并逐条执行其中的命令来恢复Redis数据到内存中。Redis还可以通过.rdb文件来保存数据,rdb搭配aof使用可以最大程度地保证数据不会丢失。

在执行每一条命令时,Redis都会将会改变数据集的命令以特定的格式添加到appendonly.aof文件的末尾,但如果系统在写入数据到磁盘时发生了一些异常情况如系统断电,进程被意外终止等,会导致aof文件的末尾出现乱码,从而使得aof文件无法在Redis启动时被正确地解析。

解决方法

在Redis日志的提示中已经给出问题的解决方法,使用官方提供的redis-check-aof工具即可修复该问题

​
> redis-check-aof --fix appendonly.aof
​
...
AOF analyzed: size=823005246, ok_up_to=823004206, diff=1040
This will shrink the AOF from 823005246 bytes, with 1040 bytes, to 823004206 bytes
Continue? [y/N]: y
Successfully truncated AOF
​
​

扩展

在检查aof文件时,发现该文件的大小达到了接近800M,但其实真实的数据量很小(PS:对于我这个接近800MB的文件,经过BGREWRITEAOF后仅有240kb左右的数据)。由于aof文件的特性,通过官方文档了解到Redis可以自动地去精简这个文件。通过配置

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
​

可以在Redis启动后,如果检测到aof的大小增长了100%并大于64MB时,会在后台运行BGREWRITEAOF命令来重新将最终的数据写到新的aof文件中。

如果按照这样的设置,文件的大小应该不会超过128MB才对,但实际情况却相去甚远,后来在官方的配置文件中找到了答案

# This is how it works: Redis remembers the size of the AOF file after the # latest rewrite (if no rewrite has happened since the restart, the size of # the AOF at startup is used).

Redis会使用上一次rewrite发生后aof文件的大小,如果在运行过程中没有发生过rewrite,则会使用aof被加载时的文件大小。若aof文件在同一运行过程中增长超过100%且大于64MB,则会触发BGREWRITEAOF命令。

但如果服务频繁地重启,就会导致还没有来得及增长至100%就重置aof文件的大小,最终导致aof文件启动时的大小不会在一个运行周期内有机会默认触发BGREWRITEAOF命令,这就会导致aof文件无限制地增大,严重时可能导致磁盘空间被消耗完全。

如果没有频发地重启服务,此问题一般不会出现。但在可能的场景下,通过缩小百分比和最小触发rewrite容量的配置可以一定程度上避免这个问题。由于BGREWRITEAOF的安全性不会影响到Redis的正常运行,所以可以更加频繁地触发该操作来避免文件增长得过大。

auto-aof-rewrite-percentage 75
auto-aof-rewrite-min-size 16mb
​


评论