最近一直在看《Redis的设计与实现》一书,做的一些总结吧,以便以后自己复习Redis的知识。
一、介绍
除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能。与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。
例如:
redis>SET msg "hello"
OK
redis>SADD fruits "apple" "banana" "cherry"
OK
redis>RPUSH numbers 128 256 512
(integer) 3
RDB持久化保存数据库的方法是将msg、fruits、numbers三个键的键值对保存到RDB文件中,而AOF持久化保存数据库的方法是将服务器执行的SET、SADD、RPUSH三个命令保存到AOF文件中。
被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的,因为Redis的命令请求协议是纯文本格式。
二、实现
AOF持久化功能的实现可以分为:命令追加(append)、文件写入、文件同步(sync)三个步骤。
2.1 命令追加
当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾:
struct redisServer{
//..
//AOF缓冲区
sds aof_buf;
//..
};
例如:如果执行SET KEY VALUE
redis>SET KEY VALUE
OK
那么服务器在执行SET命令之后,会将一下协议内容追加到aof_buf缓冲区末尾:
*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n
2.2 AOF文件的写入和同步
Redis的服务器进程就是一个事件循环,这个循环中的文件事件负责接收哭护短的命令请求,以及向客户端发送命令回复,而时间时间则负责执行像serverCorn函数这样需要定时运行的函数。
因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓冲区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否将aof_buf缓冲区的内容写入到AOF文件里面,这个过程用伪代码表示为:
def eventLoop():
while True:
#处理文件事件,接收命令请求以及发送命令回复
#处理命令请求时可能会有新内容被追加到aof_buf缓冲区中
processFileEvents()
#处理时间时间
processTimeEvents()
#考虑是否将aof_buf中的内容写入和保存到AOF文件里面
flushAppendOnlyFile()
flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定:
appendfsync选项的值分为:always、everysec、no
- always:将aof_buf缓冲区的所有内容写入并同步到AOF文件
- everysec:将aof_buf缓冲区中所有的内容写入到AOF文件,如果上次同步AOF文件的时间距离现在超过一秒钟,那么再次对AOF文件进行同步,并且这个同步操作是由一个线程专门负责的。
- no:将aof_buf缓冲区中所有的内容写入到AOF文件,但不对AOF文件进行同步,何时同步由操作系统决定。
为了提高文件的写入效率,在现代操作系统中,当用户调用write函数,将一些数据写入到文件的时候,操作系统通常会将写入数据暂时保存在一个内存缓冲区里面,等到缓冲区被填满,或者超过了指定的时间限定时,才将缓冲区的数据同步到磁盘文件中。
这样做虽然提高了效率,但是如果计算机发生停机,那么保存在内存缓冲区里面的写入数据会丢失。
为此,系统提供了fsync和fdatasync两个同步函数,它们可以强制让操作系统将缓冲区中的数据写入到磁盘里面,从而确保写入数据的安全性。
2.3 区别
- 当appendfsync的值为always时,服务器在每个事件循环都要将aof_buf缓冲区中所有的内容写入到AOF文件,并且同步AOF文件,所以always的效率时三个选项中最慢的一个,但是从安全性上讲,always也是最安全的,即使发生停机,AOF持久化也只会丢失一个事件循环中所产生的命令数据。
- 当appendfsync的值为everysec时,服务器在每个事件循环都要讲aof_buf缓冲区的所有内容写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行一次同步。从效率上来讲everysec模式足够快,并且即使发生停机也只会丢失一秒钟的命令数据。
- 当appendfsync的值为no时,服务器在每个事件循环都要讲aof_buf缓冲区中所有的内容写入到AOF文件,至于合适对AOF文件进行同步,则由操作系统控制。所以该模式下AOF文件写入速度是最快的,但是单次同步时间是最长的。并且no模式会丢失上次同步AOF文件之后所有的命令数据。
知之为知之,不知为不知,是知也!