AOF持久化功能的实现跨越分为命令追加、文件写入、文件同步三个步骤。
命令追加:
当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_ buf
缓冲区的末尾。
AOF文件的写入与同步
服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓冲区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件里。
flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定。
appendfsync选项的值 | flushAppendOnlyFile函数的行为 |
---|---|
always | 将aof_buf缓冲区中的所有内容写入并同步到AOF文件 |
everysec | 将aof_buf缓冲区中的所有内容写入到AOF文件,如果上次同步AOF文件的时间距离现在超过1秒钟,那么在此对AOF文件进行同步,并且这个同步操作是由一个线程专门负责进行的 |
no | 将aof_buf缓冲区中的所有内容写入到AOF文件,但并不对AOF文件进行同步 |
AOF文件的载入与数据还原
redis读取AOF文件并还原数据库状态的详细步骤如下:
1、创建一个不带网络连接的伪客户端:因为redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端执行命令。
2、从AOF文件中分析并读取出一条写命令。
3、使用伪客户端执行被读出的写命令。
4、一直执行步骤2、3,直到AOF文件中的所有写命令都被处理完。
AOF重写
因为AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中的内容越来越多,所以需要重写AOF文件。
AOF文件重写的实现
不对原来的AOF文件进行压缩,而是重新以当前数据库存在的键值对进行重写命令。
AOF后台重写
AOF后台重写是不阻碍主线程的情况下,在子线程中完成重写的操作。
但当子线程在完成重写,主线程却依然在插入数据,就会导致新插入的数据并没有存在于重写的AOF文件中。
所以,有一个重写缓冲区的概念,当子线程在重写,主线程执行命令,就把这些命令推入重写缓冲区中,当子线程处理完重写的操作,就执行重写缓冲区的操作,来保证数据的完整性。
总结
AOF文件通过保存所有修改数据库的写命令请求来记录服务器的数据库状态。
AOF文件中的所有命令都以redis命令请求协议的格式保存。
命令请求会先保存到AOF缓冲区里面,之后再定期写入并同步到AOF文件。
appendfsync选项的不同值对AOF持久化功能的安全性以及redis服务器的性能有很大影响。
服务器只要载入并重新执行保存在AOF文件中的命令,就可以还原数据库本来的状态。
AOF重写可以产生一个新的AOF文件,这个新的AOF文件和原有的AOF文件所保存的数据库状态一样,但体积更小。
在执行BGREWRITEAOF命令时,redis服务器会维护一个AOF重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令,当子进程完成创建新AOF文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,是的新旧两个AOF文件所保存的数据库状态一致。最后服务器用心的AOF文件替换旧的AOF文件。