AOF与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,aof持久化是通过保存redis服务器所执行的写命令来记录数据库状态的。被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的。
AOF持久化的实现
AOF持久化的实现可以分为命令追加(append),文件写入,文件同步(sync)三个步骤。
1.1 命令追加
当AOF持久化功能处于打开状态,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区末尾:
struct redisServer{ //... //AOF缓冲区 sds aof_buf //... };
例如 redis>SET KEY VALUE
那么服务器在执行这个set命令之后,会将以下协议内容追加到aof_buf缓冲区的末尾:
*3 $3 SET $3 KEY $5 VALUE
1.2 AOF文件的写入与同步
redis服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而时间事件则负责执行像serverCron函数这样需要定时运行的函数。
因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓冲区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否需要将
aof_buf缓冲区的内容写入和保存到AOF文件里面。
def eventLoop(): while true: //处理文件事件,接收命令请求以及发送命令回复 //处理命令请求时可能会有新内容被追加到aof_buf缓冲区 processFileEvents() //处理时间事件 processTimeEvents() //考虑是否将aof_buf中的内容写入和保存到AOF文件里面 flushAppendOnlyFile()
flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定,各个不同值产生的行为如下表所示:
appendfsync默认值是everysec,可以参考redis.conf配置文件
假设服务器在处理文件事件期间,执行了一些写命令。如果这时flushAppendOnlyFile函数被调用,假设服务器当前的appendfsync的值是everysec,并且距离上次同步AOF文件已经超过1秒钟,那么服务器会先将aof_buf中的内容写入到AOF文件中,然后再对AOF文件进行同步。
1.3 AOF文件的载入与数据还原
因为AOF文件里面包含了重建数据库状态所需的所有写命令,所以服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。
redis读取AOF文件并还原数据的具体步骤如下:
1)创建一个不带网络连接的伪客户端:因为redis的命令只能在客户端上下文中执行,而载入aof文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用伪客户端来执行aof文件保存的写命令,伪客户端执行命令的效果和带网络连接客户端执行命令的效果完全一样。
2)从AOF文件中分析并读取一条写命令
3)使用伪客户端执行被读出的写命令
4)一直执行步骤2和步骤3,知道文件读取完毕
1.4 AOF重写
其实就是为了解决AOF文件体积膨胀的问题,Redis提供了AOF文件重写功能。
aof重写程序是放在子进程里执行的