除了RDB持久化,Redis还提供AOF持久化功能。RDB持久化是通过保存数据库状态,而AOF持久化是通过保存Redis服务器的写命令来记录数据库状态。
一,AOF持久化的实现:
AOF持久化功能的实现可以分为三步:命令追加,文件写入,文件同步。
- 命令追加(append)
当AOF持久化功能处于打开状态时,服务器在执行一次写命令之后,会以协议格式将被执行的写命令追加到数据库状态的 aof_buf缓存区的末尾。
struct redisServer{
//AOF缓存区
sds aof_buf;
};
二,AOF文件的写入和同步:
Redis服务器进程就是一个事件循环,这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发命令回复,而时间时间则负责执行像serverCron函数这样需要定时运行的函数。
因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓存区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否将缓存区的内容写入和保存到AOF里面。
flushAppendOnlyFile由appendfsync选项控制:
- always:服务器的每个事件循环都要讲aof_buf缓存区的内容写入到AOF文件,并且同步AOF文件。所以always的效率是最慢的一个。从安全的角度,即使出现故障停机,AOF持久化也只会丢失一个事件循环中所产生的命令数据。
- everysec: 服务器的每个事件循环都要讲aof_buf缓存区的内容写入到AOF文件,并且每秒子进程中对AOF文件进行同步。就算宕机,也只会丢失一秒钟的数据。
- no: 服务器的每个事件循环都要讲aof_buf缓存区的内容写入到AOF文件,何时对AOF文件同步,则有操作系统控制。 速度最快。
三,AOF重写:
AOF重写并不需要对旧的AOF文件进行任何读取,分析,写入操作。而是读取现在数据库状态。
RPUSH list 'a'
RPUSH list 'b'
RPUSH list 'c'
RPUSH list 'd'
是使用一条 RPUSH list 'a' 'b' 'c' 'd' 去代替 数据库的4条命令。
注意: 如果元素超过64个元素,则使用多条命令。
四,AOF后台重写:
Redis不希望AOF重写造成服务器无法处理请求,所以决定把AOF重写重写放在子进程执行。
但这里有个问题,当子进程进行文件重写时,数据库中只有k1一个键,但当子进程完成AOF重写后,服务器中出现k1,k2,k3,k4。因此服务器状态和AOF文件数据不一致。
为了解决这个问题,Redis出现AOF重写缓存区
- AOF缓存区的内容会定期被写入和同步AOF文件。
- 创建子进程开始,服务器执行的所有命令都会被记录到AOF重写缓存区。