【redis深层次探索】AOF持久化

一、说明

AOF持久化功能的实现可以分为命令追加( append) 、 文件写入、 文件同步( sync) 三个步骤。

二、AOF持久化的实现

2.1、命令追加

当AOF持久化功能处于打开状态时, 服务器在执行完一个写命令之后, 会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。

2.2、AOF文件的写入和同步

Redis的服务器进程就是一个事件循环( loop) , 这个循环中的文件事件负责接收客户端的命令请求, 以及向客户端发送命令回复, 而时间事件则负责执行像serverCron函数这样需要定时运行的函数。

服务器在处理文件事件时可能会执行写命令, 使得一些内容被追加到aof_buf缓冲区里面, 所以在服务器每次结束一个事件循环之前, 它都会调用flushAppendOnlyFile函数, 考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件里面。

flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定,如下图所示:
在这里插入图片描述
如果用户没有主动为appendfsync选项设置值, 那么appendfsync选项的默认值为everysec

2.3、AOF持久化的效率和安全性

服务器配置appendfsync选项的值直接决定AOF持久化功能的效率和安全性。

  • 1.当appendfsync的值为always时, 服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件, 并且同步AOF文件, 所以always的效率是appendfsync选项三个值当中最慢的一个, 但从安全性来说, always也是最安全的, 因为即使出现故障停机, AOF持久化也只会丢失一个事件循环中所产生的命令数据。
  • 2.当appendfsync的值为everysec时, 服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件, 并且每隔一秒就要在子线程中对AOF文件进行一次同步。 从效率上来讲, everysec模式足够快, 并且就算出现故障停机, 数据库也只丢失一秒钟的命令数据。
  • 3.当appendfsync的值为no时, 服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件, 至于何时对AOF文件进行同步, 则由操作系统控制。 因为处于no模式下的flushAppendOnlyFile调用无须执行同步操作, 所以该模式下的AOF文件写入速度总是最快的, 不过因为这种模式会在系统缓存中积累一段时间的写入数据, 所以该模式的单次同步时长通常是三种模式中时间最长的。 从平摊操作的角度来看, no模式和everysec模式的效率类似, 当出现故障停机时, 使用no模式的服务器将丢失上次同步AOF文件之后的所有写命令数据。

2.4、AOF文件载入和数据还原

Redis读取AOF文件并还原数据库状态的详细步骤如下:
1) 创建一个不带网络连接的伪客户端( fake client) : 因为Redis的命令只能在客户端上下文中执行, 而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接, 所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令, 伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样。
2) 从AOF文件中分析并读取出一条写命令。
3) 使用伪客户端执行被读出的写命令。
4) 一直执行步骤2和步骤3, 直到AOF文件中的所有写命令都被处理完毕为止。
如下图所示:
图片来自于《redis设计与实现》

三、AOF的重写

3.1、说明

因为AOF持久化是通过保存被执行的写命令来记录数据库状态的, 所以随着服务器运行时间的流逝, AOF文件中的内容会越来越多, 文件的体积也会越来越大, 如果不加以控制的话, 体积过大的AOF文件很可能对Redis服务器、 甚至整个宿主计算机造成影响, 并且AOF文件的体积越大, 使用AOF文件来进行数据还原所需的时间就越多。

为了解决AOF文件体积膨胀的问题, Redis提供了AOF文件重写( rewrite) 功能。 通过该功能, Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同, 但新AOF文件不会包含任何浪费空间的冗余命令, 所以新AOF文件的体积通常会比旧AOF文件的体积要小得多。

四、总结

  • AOF文件通过保存所有修改数据库的写命令请求来记录服务器的数据库状态。
  • AOF文件中的所有命令都以Redis命令请求协议的格式保存。
  • 命令请求会先保存到AOF缓冲区里面, 之后再定期写入并同步到AOF文件。
  • appendfsync选项的不同值对AOF持久化功能的安全性以及Redis服务器的性能有很大的影响。
  • 服务器只要载入并重新执行保存在AOF文件中的命令, 就可以还原数据库本来的状态。
  • AOF重写可以产生一个新的AOF文件, 这个新的AOF文件和原有的AOF文件所保存的数据库状态一样, 但体积更小。
  • AOF重写是一个有歧义的名字, 该功能是通过读取数据库中的键值对来实现的, 程序无须对现有AOF文件进行任何读入、 分析或者写入操作。
  • 在执行BGREWRITEAOF命令时, Redis服务器会维护一个AOF重写缓冲区, 该缓冲区会在子进程创建新AOF文件期间, 记录服务器执行的所有写命令。 当子进程完成创建新AOF文件的工作之后, 服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾, 使得新旧两个AOF文件所保存的数据库状态一致。 最后, 服务器用新的AOF文件替换旧的AOF文件, 以此来完成AOF文件重写操作。

参考资料:《redis设计与实现》

上一篇:【redis深层次探索】RDB持久化
下一篇:【redis深层次探索】Redis的主从复制(及读写分离)
                                                                                    不积跬步,无以至千里;不积小流,无以成江海!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值