Contents

Redis持久化机制

Warning
本文最后更新于 May 4, 2022,文中内容可能已过时,请谨慎使用。

Redis 最常见的一个用处就是当作缓存服务器,将后端数据库中的数据存入内存中,再直接从内存中读取数据是一个非常高效的方式。但是内存存储模式有一个问题,掉电后会丢失数据,所以作为一个数据库来用的话必须考虑一旦服务器宕机,内存中数据的保存。

Redis的持久化机制分为 AOF(Append Only File) 日志和 RDB 快照。

AOF

简介

AOF 是靠保存Redis服务器所执行命令日志的方式对Redis里的数据进行持久化。Redis 采用了一种写后日志的模式,即先执行命令,把数据写入内存,然后才记录日志。

https://img1.kiosk007.top/static/images/blog/redis_aof.png
Redis AOF 过程
redis_aof

传统的数据库日志,例如 redo log(重做日志),记录的是修改后的数据,而AOF里记录的是 Redis 收到的每一条命令,这些命令以文本形式保存。

这样先执行、后写日志有一个好处,就是让系统先执行了命令,只有命令执行成功,才会被记录到日志中。否则,Redis会直接向客户端报错。所以,这样可以便面出现记录错误命令的情况。

除此之外,AOF 还有一个好处,他在命令执行后才记录日志,所以不会阻塞当前的写操作

缺点:如果刚执行完一个命令,还没有来得及记录日志,则这个命令对应的数据有可能丢失。

配置

在 redis.conf 配置文件的 APPEND ONLY MODE 下面:

redis_aof_config

这里的 appendonly 为 no ,表示 redis 默认使用的是 rdb 方式进行持久化,如果想要开启 AOF 持久化,这里需要改成 yes。


appendfilename 是 aof 文件名,默认是 “appendonly.aof”

回写机制

AOF 提供了三种回写机制,也就是 AOF 配置文件中 appendfsync 的三个可选值。

  • Always,同步回写:每个命令执行完,立马同步地将日志写回磁盘。
  • Everysec,每秒回写:每个写命令执行完,只是先把日志写到AOF文件的内核缓冲区,每一秒把缓冲区中的内容写入磁盘;
  • No,操作系统控制回写:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区的内容写回到磁盘。
配置项写回时机优点缺点
Always同步写回可靠性高每个写命令都需要落盘,性能影响大
Everysec每秒写回性能适中宕机时会丢失1s的数据
No操作系统控制性能好宕机时丢失数据可能会比较多

问题

  1. 日志文件存太大了怎么办?

随着接收的命令越来越多,AOF 文件会越来越大,这不仅是因为有些文件系统支持单个文件的最大大小比较有限1。另一方面,单个文件太大,在恢复的时候会比较慢。这时候就需要 AOF 重写机制 了。

AOF 重写机制在重写的时候,根据数据库的现状创建一个新的 AOF 文件,也就是读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。比如说,很多redis命令都是对同一个键值对进行修改,只记录一个最终状态即可。这样在日志恢复时,只用执行这一条代表最终状态的命令即可。


  1. AOF 重写会阻塞吗?

和 AOF 日志由主线程写回不同,重写的过程是由后台子进程 bgrewriteaof 来完成,所以不会阻塞主线程。


  1. AOF重写的时机?

AOF 文件重写触发机制:通过 redis.conf 配置文件中的 auto-aof-rewrite-percentage:默认值为100,以及auto-aof-rewrite-min-size:64mb 配置,也就是说默认Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

RDB

简介

内存快照机制是把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。恢复时是将快照文件直接读到内存里。

和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,所以在做数据恢复的过程中是把 RDB 文件读入内存,即可恢复。

配置

在redis.conf 配置文件中的 SNAPSHOTTING 下面:

redis_rdb_config

快照时机

rdb 的快照时机分为自动触发和手动触发。

  1. 自动触发: 上图配置文件中的save就是配置 Redis RDB 的持久化条件。
save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存
save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存
save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存
  1. 手动触发: 手动触发的方式有两种。
    1. save:该命令会阻塞当前 Redis 服务器,执行 save 命令期间,Redis 不能处理其他命令,直到RDB过程结束
    2. bgsave:该命令执行时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。

Redis 内部的所有 RDB 都采用 bgsave 的方式,不会阻塞Redis本身

和 AOF 相比,快照的恢复速度快,但是,快照的频率不好把握,频率太低,宕机时可能造成过多的数据丢失,频率太高消耗也大。

Redis 4.0 混合 AOF 和内存快照方式

该方案具体是内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。这样一来,快照不用很频繁的执行,避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说不用频繁的记录所有的操作,因此避免了文件过大的情况,也可以避免重写开销。



  1. https://developer.aliyun.com/article/244149 ↩︎