redis灵魂拷问:聊一聊AOF日志重写

“ AOF日志重写到底会不会阻塞主线程?”redis

01

缓存

AOF介绍

redis的AOF日志,是redis持久化的一种方式,它是一种write after log,即先执行命令后记录日志。这样的好处是日志不会记录执行失败的命令,同时记录日志不会阻塞当前命令执行。markdown

记录AOF是在主线程中执行的,因此也会阻塞主线程。这个跟AOF的写回策略有关,这个配置项参数叫appendfsync,在redis.conf文件中,默认值是everysec。下面是3种写回策略的比较:数据结构

redis灵魂拷问:聊一聊AOF日志重写
这样,咱们就须要在性能和可靠性之间作一些取舍了。app

当redis上执行的命令愈来愈多,AOF日志文件会变得很大,这样AOF文件追加命令会很慢,并且操做系统对文件大小也有必定的限制,再者若是使用AOF作主从同步或数据恢复的话,由于命令记录太多会致使耗时很长。redis解决这个问题的手段就是AOF日志重写。ide

02

性能

AOF重写介绍

在redis.conf文件中,有下面2个参数来控制AOF重写:操作系统

auto-aof-rewrite-percentage 100 #AOF文件大小较上次重写超过100%时进行重写
auto-aof-rewrite-min-size 64mb #aof文件大小超过64m时重写

下面咱们执行6条命令:线程

192.168.59.146:6379> set name jinjnzhu
OK
192.168.59.146:6379> set password 123456
OK
192.168.59.146:6379> set name jinjunzhu1
OK
192.168.59.146:6379> set password 1234567
OK
192.168.59.146:6379> set name jinjunzhu2
OK
192.168.59.146:6379> set password 12345678
OK

以后咱们查看name和password的值:日志

192.168.59.146:6379> get name
"jinjunzhu2"
192.168.59.146:6379> get password
"12345678"

这2个key的值被赋予了最新的一次赋值,虽然咱们执行了6条命令,可是AOF重写后日志文件就剩了最后2条命令。

03

AOF重写对性能的影响

在上小节的介绍中,若是AOF文件较上次重写超过了100%,就要进行重写。可是若是日志特别大,AOF重写后把日志写回磁盘也是一个很是耗时的操做,那么AOF重写是否会阻塞主线程呢?

AOF重写并非在主线程中,而是redis会fork一个bgrewriteaof子进程,这样就不会阻塞主线程执行了。

fork子进程的过程是要在主线程中执行的,这时候主线程须要拷贝内存页表,这个页表记录了虚拟内存和物理内存的映射关系,若是内存很大,拷贝过程花费的时间就会很大,而这个拷贝过程当中主线程是阻塞的。

fork子进程完成后,主线程和bgrewriteaof子进程使用的是同一起内存空间,这时若是有新的写请求到来,而且写命令是已经存在的key,主线程会使用CopyOnWrite的方式,为这个key申请新的内存空间,进行写操做。若是这个key是一个bigkey,那也会耗时不少。

下面我画了一个简单的图,主线程fork出bgrewriteaof子进程时,复制了一个页表给子进程用,跟本身指向相同的内存空间。可是AOF重写过程当中收到了foo这个key的写命令,这时主线程须要拷贝一份数据到新的内存空间进行修改。

redis灵魂拷问:聊一聊AOF日志重写

在AOF重写的过程当中,若是有新的写命令到来了,会影响AOF重写吗?

固然不会,新的写命令不只会记录到AOF日志的缓存区,还会记录到重写的新AOF日志缓存区,这样当AOF重写结束后,把从新缓存区数据写到新AOF文件,就不会丢失了。

往期文章回顾:

《redis灵魂拷问:聊一聊redis底层数据结构》

《redis灵魂拷问:怎样搭建一个哨兵主从集群》

相关文章
相关标签/搜索