28 August 2015

AOF(append only file)持久化

RDB与AOF区别:

  RDB持久化是通过保存数据库中的键值对来记录数据库状态。

  AOF持久化是通过报错redis服务器所执行的写命令来记录数据库状态。


频率控制

redis服务器在执行写操作时,都会追加一些内容到aof_buffer中,在结束写操作之前都会调用flushappendonlyfile函数,将buffer中的内容写入AOF文件。

flushappendonlyfile函数通过appendfsync参数,来控制同步频率。

  1. appendfsync : always
    //时时,特点:效率最慢,但数据最安全

  2. appendfsync : everysec
    //每秒钟,特点:效率高,最大可能有1秒钟内的数据丢失。

  3. appendfsync : no //不同步,何时同步,由操作系统决定。特点:效率高,数据丢失可能性大。


AOF文件的载入与还原

如果redis服务器开启了AOF持久化,那么服务器会优先使用AOF还原数据。

AOF文件还原数据的过程:

1. 创建一个伪客户端。
2. 从aof文件中每一条命令。
3. 使用伪客户端执行写命令。
4. 判断aof文件是否执行完毕。
5. 载入完毕。

AOF重写

为什么要重写AOF文件?

因为aof持久化是通过保存被执行的命令来记录数据库状态,那么随着时间的推移,文件的体积会越来越大,体积过大的aof文件可能对redis服务器,甚至整个计算机造成影响,并且,如果aof文件过大,进行数据还原的时候所需要的时间也就越多。为了解决aof文件过大的问题,redis提供了重写功能。

什么是AOF重写?

就是redis服务器通过创建一个新的AOF文件来替代现有的AOF文件,新旧2个文件所保存的数据库状态是相同的,但新文件不包含任何浪费空间的冗余代码,所以新AOF文件要比旧文件小的多。

AOF重写实现原理

读取数据库中所有的键值对,然后用一条命令去记录键值对,替代之前的多条命令,这就是实现原理。

后台重写AOF文件

因为AOF重写是大量的写操作,这样会阻塞主进程,这样在重写期间就会导致redis无法响应请求。所以需要开启一个子进程去执行重写的任务。

子进程进行AOF重写期间,父进程可以继续处理命令请求。新的命令可能对现有数据状态进行修改,从而使当前数据库状态与重写后的AOF文件所保存的数据库状态不一致的问题。

如何解决以上问题?

  1. redis设置了一个AOF重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当redis主进程执行一个写命令之后,它会同时将这个写命令发送给AOF缓冲区和AOF重写缓冲区。

  2. 当子进程重写完成以后,会向父进程发送一个信号,父进程接收到信号以后,会调用一个信号处理函数完成2步操作:

    (1). 将AOF重写缓冲区的所有内容写到新的AOF文件中,新的AOF文件所保存的数据库状态跟服务器当前数据库状态一致。

    (2). 对新的AOF文件进行改名,覆盖现有的AOF文件,完成新旧2个AOF文件的替换。

通过以上方案,将数据AOF持久化工作对主进程的阻塞时间降到了最低。


资料参考:《redis设计与实现》黄建宏注