Redis RDB 与AOF

时间:2023-01-02 19:10:02
参考书籍《Redis设计与实现》

一丶为什么redis需要持久化

redis 作为一个内存数据库,如果不想办法将存储在内存中的数据,保存到磁盘中,那么一旦服务器进程退出,那么redis数据库中的数据就将丢失。

二丶RDB

redis 提供RDB持久化功能,可以将数据库中的数据保存到磁盘中,避免数据意外丢失。Redis RDB 是将一个时间点的数据库状态保存到RDB文件中,RDB文件时一个经过压缩的二进制文件,通过该文件可以还原申生成RDB时的数据库状态。

1.SAVE与BGSAVE

SAVE和BGSAVE 命令都能生成RDB文件

  • SAVE命令会阻塞redis服务器进程,直到SAVE命令执行完为止,在服务器进程阻塞的期间,服务器无法处理任何命令请求
  • BGSAVE会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程可以继续处理请求命令

Redis 服务在启动的时候会检测RDB文件的存在,并自动载入RDB文件。由于AOF文件更新的频率比RDB高(频率高意味着数据全),所以如果同时具备AOF 和RDB文件,redis服务器会选择AOF文件进行恢复。

BGREWRITEAOF 可以触发AOF持久化,但是不允许和BGSAVE一起执行(因为一起执行意味着大量的磁盘写入操作)

2.RDB自动间隔保存

redis 允许用户通过配置save选项,让服务器每隔一段时间自动执行一次BGSAVE命令。如

save 900 1
save 300 10
save 60 1000

这个配置意味着,如果900秒内对数据库进行至少一次修改,300秒内对数据库至少由十次修改,60秒内有1000次修改,那么redis服务器将自动进行BGSAVE命令的执行。

为了实现这个功能redis服务器会记录两个内容:dirty(距离上一次成功执行save 或者bgsave 数据库进行了多少次修改)和 lastsave (时间戳,记录上一次执行save 或者 bgsave 的时间)。redis 周期性操作函数serverCron每隔100毫秒执行一次,会根据dirtylastsave是否满足 save 900 1等配置的要求,如果满足那么将执行BGSAVE

三丶AOF

除了RDB之外,redis 还有AOF(append only file)持久化的功能,与RDB持久化通过将数据库数据保存到文件中不同,AOF 持久化时通过保存redis服务器执行的修改操作命令来实现的。如

set msg "hello"

对于这条命令,RDB记录的是msg 键和对应的值,但是AOF记录的是set msg "hello"这条命令。AOF持久化可以使用BGREWRITEAOF触发

AOF可以分为如下流程

Redis RDB 与AOF

1.命令追加

服务器在执行完一个写明了后,会以协议格式将被执行的命令追加到redis服务器中的aof_buf末尾

2.AOF 文件写入和同步

redis每次结束一个事件循环之前都会调用flushAppendOnlyFile来判断是否需要将aof_buf里的内容写入到AOF文件中。redis服务器配置的appendfsync 设置可以控制aof 文件写入的时机:

  • always

    将aof缓冲区的所有内容写入并且同步到aof文件

    选择此配置,意味着每次都需要将命令写回磁盘,安全性最高,但是会导致效率很低

  • everysec

    每秒写入aof缓冲区中的内容,并同步aof文件(同步操作由另外一个线程专门进行)

    选择此配置,意味着每秒写回磁盘,最多丢失一秒的数据

  • no

    将aof缓冲区中的内容写入到AOF文件但是不同步,何时同步由操作系统决定

    此配置不会将命令马上写回磁盘,效率高,但是不安全

为了提高文件的写入效率,在现代操作系统中,用户调用write函数,将一些数据写入到文件的时候,操作系统通常会将期望写入的数据保存到一个内存缓冲区中,等缓冲区满或者超过一段事件后,才真正的将缓冲数据写入到磁盘
这样的操作提高的效率,但是带来了数据丢失的风险,所以操作系统提供了fsync 和fdatasync两个同步函数,让用户调用强制让缓冲区写入磁盘,从而确保数据的安全性

3.AOF重写

因为aof文件记录的是数据库执行的修改操作命令,这意味着随着时间的流逝,aof文件中的内容将越来越多。为了解决这个问题redis使用AOF重写——redis服务器可以创建一个新的aof文件来替代现有的aof文件,二者保存的数据库数据相同,但是新的文件不会保存冗余命令(set msg "a" 然后执行set msg "b" 其实aof文件只需要保存set msg "b" )

3.1 AOF 重写原理

AOF重写并不是分析已有文件,而是读取数据库中的数据,将数据转化为命令。首先读取数据库中的键和值,然后使用一条命令来记录键值对,这就是aof重写的实现原理(对于哈希,集合,有序集合,列表键值对,redis一条命令只会记录64个元素,超过64个元素,将使用多条命令记录)

3.2 AOF 后台重写

AOF重写程序将使用子进程的方式执行命令,从而让服务器进程可以继续处理请求。

为了解决重写过程中,键值对被修改的问题,redis使用aof重写缓冲区,在重写过程中,用户修改数据库的命令会被保存到AOF缓冲区和AOF重写缓冲区。子进程完成AOF重写后,会将AOF重写缓冲区中的命令同步到新AOF文件中,这时候新文件保存的内容就和数据库一致了。然后子进程将修改新AOF文件名称,原子的覆盖旧AOF文件。