AOF持久化
AOF,Append Only File
AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。
写入AOF文件的所有命令都是以Redis的命令请求协议格式保存。
1. AOF持久化的实现
AOF持久化的实现分为命令追加、文件写入、文件同步三个部分。
1.1 命令追加
当AOF持久化功能打开时,服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。
struct redisServer{
// ...
// AOF缓冲区
sds aof_buf;
// ...
}
1.2 AOF文件的写入与同步
Redis服务器进程就是一个事件循环(Loop)。
这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复。
这个循环中的时间事件负责执行像serverCron这样需要定时运行的函数。
服务器在每次结束一个事件循环前,都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区的内容写入和保存到AOF文件里面。这个过程可以用下面伪代码表示。

flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定,各个不同值如下图所示,默认值为everysec。

AOF文件的写入指的是将数据写入文件,但操作系统为了提高文件的写入效率,通常会将写入数据暂时放在一个内存缓冲里。
AOF文件的同步指的是操作系统提供fsync、fdatasync同步函数,可以强制操作系统立即将缓冲区中的数据写入到硬盘里面。
下图是AOF持久化的效率和安全性。
[图片上传失败...(image-dd0024-1582442941228)]
2. AOF文件的载入与数据还原
AOF文件包含重建数据库状态的所需的所有写命令,所以服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原服务器关闭之前的服务器状态。
Redis读取AOF文件并还原数据库时,会创建一个不带网络连接的伪客户端。
3. AOF重写
为了解决AOF文件膨胀问题,Redis提供AOF文件重写。Redis服务器会创建一个新的AOF文件替代现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同,但新AOF文件不会包含任何浪费空间的冗余命令。
3.1 AOF文件重写的实现
AOF文件重写不需要对现有AOF文件进行读取、分析、写入,这个功能是通过读取服务器当前的数据库状态来实现。
AOF文件重写的原理是:从数据库中读取键现在的值,然后用一条命令记录键值对,代替之前记录这个键值对的多条命令。
为了避免在执行命令时造成客户端输入缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这4种可能包含多个元素的键时,先检查键包含的元素数量,如果元素的数量超过了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD(默认值为64),那么重写程序将使用多条命令来记录键的值,而不单单使用一条命令。
3.2 AOF后台重写
Redis将AOF重写程序放到子进程中执行:
- 子进程进行AOF重写期间,服务器进程(父进程)可以继续处理命令请求。
- 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。
为了解决AOF重写时,服务器进程继续处理命令请求时,导致服务器现在状态与AOF数据不一致问题,Redis服务器设置了一个AOF重写缓冲区,这个缓冲区在服务器创建AOF子进程之后开始使用,当Redis服务器执行完一个命令后,它会同时将这个写命令发送给AOF缓冲区(aof_buf)和AOF重写缓冲区。也就是说,在子进程执行AOF重写期间,服务器进程需要执行以下三个工作:
- 执行客户端发来的命令。
- 将执行后的写命令追加到AOF缓冲区。
- 将执行后的写命令追加到AOF重写缓冲区。
当子进程完成AOF重写工作后,它会向父进程发送一个信号,父进程在接到该信号后,会调用一个信号处理函数,并执行以下工作:
- 将AOF重写缓冲区的所有内容写入到新的AOF文件中。
- 对新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成新旧两个AOF文件的转换。
在整个AOF后台重写过程中,只有信号处理函数执行时会对服务器进程(父进程)造成阻塞,在其他时候,AOF后台重写都不会阻塞父进程。
以上就是AOF后台重写,也就是BGREWRITEAOF 命令的实现原理。
网友评论