1.AOF重写机制
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,redis引入AOF重写机制
压缩文件体积。AOF文件重写是把redis进程内的数据转换为写命令同步到新AOF文件的过程。
重写后的AOF文件为什么可以变小?
进程内已经超时的数据不再写入文件。
旧的AOF文件含有无效命令,如del key1,hdel key2,srem keys,set a 111,set a222
重写使用进程内数据直接生成,这样新的AOF文件只保留最终的数据的写入名。
多条写命令可以合并为1个。如 lpush list a,lpush list b,lpush list c,
可以转换为lpush list a b c .为了防止单条命令过大造成客户端缓冲区溢出,
对于list,set,hash,zset类数据类型,以64个元素为界限拆分为多条。
AOF重写降低了文件占用空间,更小的AOF文件可以更快被redis加载。
2.AOF重写
AOF重写可以手动和自动触发。
手动触发:直接调用 bgrewriteaof命令
自动触发:根据 auto-aof-rewrite-min-size和auto-aof-rewrite-percentage
参数确定自动触发时机。
auto-aof-rewrite-min-size:表示运行AOF重写时文件最小体积,默认为64M
auto-aof-rewrite-percentage:代表当前AOF文件空间(aof_current_size)和
上一次重写后AOF文件空间(aof_base_size)的比值。
自动触发时机:
aof_current_size>auto-aof-rewrite-min-size
或者:
(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage
aof_current_size 和 aof_base_size 可以在info persistence统计信息中查看。
192.168.1.7:6379> info persistence
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1718942215
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:6385664
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:6389760
aof_current_size:233
aof_base_size:233
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0
3.触发AOF重写时,内部做了哪些事情
(1)执行AOF重写请求
如果当前进程正在执行AOF重写,请求不执行并返回如下响应。
ERR Background append only file rewrite already in process;
如果当前进程真在执行bgsave操作,重写命令延迟到bgsave完成之后再执行。
返回:
Background append only file rewriting scheduled
(2)父进程执行fork创建子进程,开销等同于bgsave;
主进程执行fork操作完成后,继续响应其他命令。所有修改命令依然写入AOF缓冲区
并根据appendfsync策略同步到硬盘,保证原有AOF机制正确性。
由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据。
由于父进程依然响应命令,redis使用AOF重写缓冲区保存这部分数据,防止新AOF
文件生成周期丢失这部分数据。
子进程根据内存快照,按照命令合并规则写入到新的AOF文件,每次批量写入硬盘
数据量由配置 aof-rewrite-incremental-fsync 控制,默认32M;
防止单次刷盘数据过多造成硬盘阻塞。
新AOF文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见:
info persistence 下的aof_*相同统计。
父进程把AOF重写缓冲区的数据写入到新的AOF文件。
使用新AOF文件替换老文件,完成AOF重写。
4.重启加载
AOF和RDB文件都可以用于服务器重启时数据恢复。
流程说明:
(1)AOF持久化开启且存在AOF文件时,优先加载AOF文件。
* DB loaded from append only file 5.84 seconds
(2)AOF关闭是加载RDB文件
* DB loaded from disk 5.85 seconds
(3)加载AOF/RDB文件成功后,redis启动成功。
(4)AOF/RDB文件存在错误时,redis启动失败并打印错误。
5.文件校验
加载损坏的AOF文件时会拒绝启动
Bad file format reading the append only file:make a backup of your AOF file;
then use ./redis-check-aof --fix filename
对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof --fix 命令
进行修复,修复后使用diff -u 对比数据的差异。找出丢失的数据,有些可以人工
修改补全。
aof文件可能存在结尾不完整的情况,比如机器突然掉电导致AOF尾部文件命令写入不全,
redis提供了 aof-load-truncated 配置兼容这种情况,默认开启。
加载AOF时,当遇到此问题时会忽略并继续启动。