Redis持久化机制和AOF重写原理

Redis持久化机制和AOF重写原理

leo 560 2021-04-10

Redis持久化

Redis官方提供了两种持久化方法。

  • 快照(Snapshot)
  • AOF(Append Only File)只追加日志文件

快照(Snapshot)

1.特点

这种方式是将某一时刻的所有数据写入磁盘,保存的文件以.rdb格式存储。因此这种方式也可称为RDB方式。这也是Redis默认开启的持久化方式

2.快照生成方式

  • 客户端方式:BGSAVE和SAVE指令。
  • 服务器配置自动触发。

a) BGSAVE

当收到客户端的BGSAVE指令时,Redis会调用fork函数来创建一个子进程,然后子进程负责将快照写入磁盘,父进程则继续处理客户端的指令请求。

fork:是一个用于创建子进程的函数。当一个进程调用fork创建一个子进程时,底层操作系统将会创建一个该进程的副本,在刚开始时父子进程共享内存,直到父进程或子进程第一次对内存进行写操作之后,被写入的内存的共享结束。

b) SAVE

当收到客户端的SAVE指令时,Redis主进程负责将快照写入磁盘,期间将不响应任何客户端指令(阻塞)。

c) 服务器配置

通过在redis.conf配置文件中配置save选项,Redis会在save选项条件满足时自动触发一次BGSAVE指令。如果设置了多个save选项,那么当任意一个选项满足时,都会触发一次BGSAVE指令。

d) SHUTDOWN指令

当收到客户端的SHUTDOWN指令时,Redis会执行一个SAVE指令。执行完成后关闭服务器。

AOF(Append Only File)只追加日志文件

1.特点

这种方式是将客户端发送的所有写命令记录到日志文件中,AOF持久化会将被执行的写命令追加到AOF日志文件的末尾,以此来记录数据的变化。因此,只要从头到尾执行一次AOF中的所有指令,就可以恢复AOF文件记录的数据。

2.开启AOF持久化

a) 修改配置文件

将配置文件中的appendonly选项改为yes

可以修改appendfilename选项指定生成的文件名称。以.aof结尾。

3.日志追加频率

  • always【谨慎使用】

    每个写命令都会同步写入到磁盘,严重降低Redis速度。

  • everysec【推荐】【默认】

    每秒执行一次将多个写命令同步写入到磁盘。可以保证最多丢失一秒内产生的数据。

  • no【不推荐】

    完全由操作系统决定何时同步,不会对任何Redis性能带来任何影响。会丢失不定量的数据。

4.修改日志同步频率

修改配置文件中的appendfsync选项,选项值为前面三个值中的一个。

AOF文件的重写

1.AOF带来的问题

持久化文件会随着写指令的增加而变得越来越大。例如调用incr num100次,文件中保存了100条指令,其实99条是多余的,因为要恢复数据库的状态只需执行一条set num 100就够了。为了压缩AOF持久化文件,Redis提供了AOF的重写机制。

2.AOF重写

用来一定程度上减小AOF文件的体积。

3.触发重写方式

  • 客户端指令

    执行BGREWRITEAOF命令,不会阻塞Redis。

  • 服务器配置自动触发

    修改配置文件中的auto-aof-rewrite-percentageauto-aof-rewrite-min-size选项。

    如果配置auto-aof-rewrite-percentage为100,auto-aof-rewrite-min-size为64mb,那么当AOF文件大于64mb,并且AOF文件的体积比上一次重写后体积大了100%时,会自动触发重写。

4.重写原理

重写AOF时,并没有读取旧的AOF文件,而是将内存中的数据用命令的方式重写了一个新的AOF文件替换旧的AOF文件。

重写流程:

  1. Redis调用fork,子进程根据内存中的数据快照,往临时文件中写入重建数据库状态的命令。
  2. 父进程继续处理客户端请求,除了将写命令追加到原来的文件中,同时将其缓存起来。这样可以保证子进程如果重写失败不会出现问题。
  3. 当子进程写入完成后通知父进程,父进程就将缓存中的命令写入到临时文件中。
  4. 父进程将临时文件替换旧的AOF文件并重命名,后续的命令追加到新的AOF文件中。

重写流程

总结

两种持久化方式既可以单独使用,也可以同时使用,也可以都不使用。

无论使用AOF还是快照持久化机制,将数据写到硬盘都是必要的,除了持久化之外,用户还应该对持久化生成的文件进行备份,增加安全性。