Redis提供了 AOF ( Append Only Hie )持久化功能。与 RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存 Redis服务器所执行的写命令来记录数据库状态的。
一、AOF持久化的实现
1.1 命令追加
当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式 将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾
SET KEY VALUE
*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n
1.2 AOF文件的写入与同步
1.2.1 事件循环(loop)
服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接收客户端 的命令请求,以及向客户端发送命令回复,时间事件则负责执行像serverCron函数这 样需要定时运行的函数
服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函 数,考虑是否需要将aof_buf缓冲区中的内容写人和保存到AOF文件里面
1.2.2 flushAppendOnlyFile函数
flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定
always:
将aof_buf缓冲区中的所有内容写入并同步到AOF文件
效率最慢,但是最安全
everysec(默认):
将aof_buf缓冲区中的所有内容写人到AOF文件,如果上次同步AOF文件的时间 距离现在超过一秒钟,那么再次对AOF文件进行同步,并且这个同步操作是由一个线 程专门负责执行的
足够快,最多丢失一秒钟的命令数据
no:
将aof_buf缓冲区中的所有内容写人到AOF文件,但并不对AOF文件进行同步, 何时同步i操作系统来决定
写入最快,但是同步时长最长,服务器将丟失上次同步AOF文件之后的所有写命令数据
二、AOF文件的载入和数据还原
因为AOF文件里面包含了重建数据库状态所需的所有写命令,所以服务器只要读人并重新执行一遍AOF文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。
步骤
1.创建一个不带网络连接的伪客户端(因为Redis的命令只能在客户端 上下文中执行)
2.从AOF文件中分析并读取出一条写 命令。
3.使用伪客户端执行被读出的写命令
4.一直执行步骤2和步骤3,直到AOF 文件中的所有写命令都被处理完毕为止
三、A〇F重写
AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运 行时间的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控 制的话,体积过大的AOF文件很可能对Redis服务器、甚至整个宿主计算机造成影响,并 且AOF文件的体积越大,使用AOF文件来进行数据还原所需的时间就越多
为了解决AOF文件体积膨胀的问题,Redis提供了 AOF文件重写(rewrite)功能。通 过该功能,Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个 AOF文件所保存的数据库状态相同,但新AOF文件不会包含任何浪费空间的冗余命令,所 以新AOF文件的体积通常会比旧AOF文件的体积要小得多。
3.1 AOF文件重写的实现
aof_rewrite
AOF文件重写并不需要对现有的AOF文件进行任何读取、分析或者写人操作,这个 功能是通过读取服务器当前的数据库状态来实现的
遍历数据库中的所有的键,忽略已过期的键。他会将所有的读取命令(string,list等等)一一执行,并使用相应的写入命令重写进新的aof文件
注意:
因为这个函数会进行大量的写人操作,所以服务器直接调用这个函数的线程将被长时间阻塞
3.2 AOF后台重写
AOF重写程序放到子进程里执行
子进程进行AOF重写期间,服务器进程(父进程)可以继续处理命令请求
子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性
注意:
进程在进行AOF重写期间,服务器 进程还需要继续处理命令请求,而新的命令可能会对现有的数据库状态进行修改,从而使得 服务器当前的数据库状态和重写后的AOF文件所保存的数据库状态不一致
3.2.1 AOF重写缓冲区
了解决这种数据不一致问题,Redis服务器设置了一个AOF重写缓冲区,这个缓冲区 在服务器创建子进程之后开始使用,当Redis服务器执行完一个写命令之后,它会同时将这 个写命令发送给AOF缓冲区和AOF重写缓冲区,等到重写子进程执行完毕后,将AOF重写缓冲区的数据追加到AOF重写文件当中.
3.2.2 文件重写的触发
文件重写的触发
文件重写的触发,分为手动触发和自动触发:
手动触发:直接调用bgrewriteaof命令,该命令的执行与bgsave有些类似:都是fork子进程进行具体的工作,且都只有在fork时阻塞。
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数,以及aof_current_size和aof_base_size状态确定触发时机。
auto-aof-rewrite-min-size:执行AOF重写时,文件的最小体积,默认值为64MB。
auto-aof-rewrite-percentage:执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值。
其中,参数可以通过config get命令查看:
状态可以通过info persistence查看:
只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个参数同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。
关于文件重写的流程,有两点需要特别注意:
(1)重写由父进程fork子进程进行;
(2)重写期间Redis执行的写命令,需要追加到新的AOF文件中,为此Redis引入了aof_rewrite_buf缓存。