AOF(Append Only File)持久化,与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF保存Redis所执行的写命令来记录数据库状态。被写入AOF文件的命令都是以Redis的命令请求协议格式保存的,纯文本格式,打开即可查看。
AOF持久化功能的实现可分为命令追加(append)、文件写入、文件同步(sync)三个步骤。
如果打开AOF功能,服务器在执行完一个写命令后,会以协议格式将被执行的命令追加到服务器状态的aof_buf
缓冲区的末尾。
struct redisServer {
// ...
sds aof_buf;
// ...
};
Redis的服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接受客户端的请求,并向客户端发送回复,而时间事件则负责执行像serverCron
函数这样的定时任务。
服务器在处理文件任务时可能会执行写命令,追加内容到aof_buf
缓冲区,所以服务器在每次结束一个事件循环前,都会调用flushAppendOnlyFile
,考虑是否将缓冲区的内容写入到AOF文件中。
flushAppendOnlyFile函数的行为由服务器配置的
appendfsync
选项的值来决定:always、everysec(默认)、no。
服务器只要读入并重新执行一遍AOF文件中的写命令,就可以还原服务器关闭之前的数据库状态:
- 创建一个不带连接的伪客户端。
- 从AOF文件中分析并读取一条写命令。
- 使用伪客户端执行被读出的命令
- 一直执行步骤2和3,知道AOF文件中的所有命令都被处理完位置。
为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写功能。通过该功能,Redis可以创建一个新的AOF文件来替代现有的AOF文件,新文件不会包含荣誉命令,体积也会小很多。
AOF文件重写不需要对现有AOF文件做任何读取、分析或写入操作,而是通过读取服务器当前的数据库状态实现的。首先从数据库中读取现在的键,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。这就是AOF重写的实现原理。
Redis服务器采用单个线程来处理命令请求,所以将AOF重写程序放到子进程中,这样父进程可以继续处理请求。父子进程会出现数据不一致的问题,Redis服务器设置了一个AOF重写缓冲区,这个缓冲区在创建子进程之后开始使用,但Redis服务器执行完一个写命令后,会通知将写命令发送给AOF缓冲区和AOF重写缓冲区。子进程完成AOF重写操作后,向父进程发送一个信号,父进程将执行以下操作:
- 将AOF重写缓冲区的内容写入新AOF文件。
- 对新的AOF文件改名,覆盖现有的AOF文件。
上一章:10. RDB持久化
下一章:12. 事件