因为子进程在进行AOF重写时,主进程没有阻塞,所以肯定继续处理命令,而这时候的命令会对现在的数据修改,这些修改也是需要写入AOF文件的。这样重写的AOF和实际AOF会出现数据不一致。
为了解决这个问题,redis增加了一个AOF重写缓存(在内存中),这个缓存在fort出子进程之后开始启用,redis主进程在接到新的写命令之后,除了会将这个写命令的协议内容追加到AOF文件之外,还会同时追加到这个缓存中。这样,当子进程完成AOF重写之后,它会给主进程发送一个信号,主进程接收信号后,会将AOF重写缓存中的内容全部写入新AOF文件中,然后对新AOF改名,覆盖老的AOF文件。
在整个AOF重写过程中,只有最后的写入缓存和改名操作会造成主进程的阻塞(要是不阻塞,客户端请求到达又会造成数据不一致),所以,整个过程将AOF重写对性能的消耗降到了最低。
AOF触发条件
最后说一下AOF是如何触发的,当然,如果手动触发,是通过BGREWRITEAOF执行的。如果要用redis的自动触发,就要涉及下面3个变量(AOF的功能要开启哦 appendonlyfile yes):
记录当前AOF文件大小的变量aof_current_size
记录最后一次AOF重写之后,AOF文件大小的变量aof_rewrite_base_size
增长百分比变量aof_rewrite_perc
每当serverCron函数(redis的crontab)执行时,会检查以下条件是否全部满足,如果是的话,就会触发自动的AOF重写:
没有 BGSAVE 命令在执行
没有 BGREWRITEAOF 在执行
当前AOF文件大小 > server.aof_rewrite_min_size(默认为1MB)
当前AOF文件大小和最后一次AOF重写后的大小之间的比率大于等于指定的增长百分比(默认为1倍,100%)
默认情况下,增长百分比为100%。也就是说,如果前面三个条件已经满足,并且当前AOF文件大小比最后一次AOF重写的大小大一倍就会触发自动AOF重写。