Redis 持久化详解
目录
- 一、简介
- 二、RDB持久化
- 2.1、SAVE
- 2.2、BGSAVE
- 2.3、SAVE选项
- 2.4、RDB文件结构
- 2.5、RDB文件载入
- 三、AOF持久化
- 3.1、开启AOF功能
- 3.2、配置AOF文件的冲洗频率
- 3.3、AOF重写
- 3.3.1、BGREWRITEAOF命令(手动)
- 3.3.2、AOF重写配置选项(自动)
- 四、RDB-AOF混合持久化
- 4.1、RDB和AOF的优劣
- 4.2、开启RDB-AOF混合持久化
- 4.3、RDB-AOF混合持久化文件载入
- 结语
一、简介
本文今天主要是Redis的持久化方式,都是关于RDB和AOF,常见的持久方式有:
- RDB持久化
- AOF持久化
- RDB-AOF混合持久化
二、RDB持久化
RDB持久化是Redis默认使用的持久化功能,该功能可以创建出一个经过压缩的二进制文件,它包含了服务器在各个数据库中存储的键值对数据等信息。RDB持久化产生的文件都以 .rdb 后缀结尾,其中 rdb 代表Redis DataBase(Redis数据库)。Redis提供了多种创建RDB文件的方法,主要是下面三种:
- SAVE(阻塞服务器并创建RDB文件)
- BGSAVE(以非阻塞方式创建RDB文件)
- 通过配置选项自动创建RDB文件
2.1、SAVE
用户可以通过执行SAVE命令,要求Redis服务器以同步方式创建一个记录了服务器当前所有数据库数据的RDB文件,这里使用的是无参命令。
127.0.0.1:6379> save
OK
服务器接收到SAVE命令,将遍历所有数据库,并将各个数据库包含的键值对全部记录到RDB文件中。在执行SAVE命令期间,Redis服务器将阻塞,直到RDB文件创建完成为止。如果Redis服务器在执行SAVE命令时已经拥有了相应的RDB文件,那么服务器将使用新创建的RDB文件替换已有的RDB文件,大致流程如下:
2.2、BGSAVE
我们知道Redis在执行SAVE命令时,会阻塞整个服务器,无法为其他客户端提供服务,如果数据量很大,阻塞就更严重了,所以为了解决这个问题,Redis提供了SAVE命令的异步版本BGSAVE命令,它们不同之处在于,BGSAVE命令不会使用Redis的服务进程创建RDB文件,而是使用子进程创建RDB文件。
127.0.0.1:6379> bgsave
Background saving started
大致的执行流程是:
- 创建一个子进程
- 子进程执行SAVE命令,创建新的RDB文件
- 当子进程完成新的RDB文件创建之后,会通知Redis服务器进程(新的RDB文件创建完成)
- Redis服务器使用新的RDB文件替换旧的RDB文件
2.3、SAVE选项
其实用户除了使用上述两种手动创建RDB文件的方式之外,还能通过设置SAVE选项,让Redis服务器在满足指定条件时自动执行BGSAVE命令,SAVE命令选项接收 seconds 和 changes 两个参数,语法如下:
save <seconds> <changes>
- seconds :指定触发持久化操作所需时长
- changes :指定触发持久化操作所需的修改次数
简单来说,如果Redis服务器在 seconds 秒之内,它包含的数据库总共执行了至少 changes 次修改,那么Redis服务器就自动执行一次BGSAVE命令,比如:
save 30 1000
就是Redis服务器在30秒内至少执行了1000次修改,那么就会自动执行BGSAVE命令。实际Redis服务器是支持同时使用多个save选项的,我们可以在配置文件中找到默认的配置:
save 900 1
save 300 10
save 60 10000
当以下任意一个条件被满足是,服务器就会执行一次BGSAVE命令
- 在900s(15分钟)之内,服务器对数据库执行了至少1次修改
- 在300s(5分钟)之内,服务器对数据库执行了至少10次修改
- 在60s(1分钟)之内,服务器对数据库执行了至少10000次修改
2.4、RDB文件结构
通过下面的图,我们了解下RDB文件结构。
- RDB文件表示符 :文件最开头的部分为RDB文件表示符,内容为“REDIS”这5个字符
- 版本号 :RDB文件表示符之后的4个字符长度的数字
- 设备附加信息 :记录生成RDB文件的Redis服务器及其所在平台的信息(如服务器版本、创建RDB的时间戳等)
- 数据库数据 :记录Redis服务器存储的0个或任意多个数据库的数据,一般从0号数据库开始排列
- Lua脚本缓存 :如果开启了复制功能,服务器将在RDB文件的Lua脚本缓存部分报错所有已被缓存的Lua脚本
- EOF :标识RDB正文内容的末尾
- CRC64校验和 :64位整数表示的CRC校验和,用来检查RDB文件是否出错或者损坏
2.5、RDB文件载入
RDB文件载入的流程图如下:
总的来说,无论用户使用哪种方式,如果遇到停机时,服务器丢失的数据量取决于创建RDB文件的时间间隔:间隔越长,停机丢失的数据就越多。所以RDB持久更像是一种备份手段而非一种普通的数据持久化手段,比如离线备份。为了解决可能丢失大量数据这一问题,所以推出了我们即将介绍的AOF持久化模式。
三、AOF持久化
与RDB这种全量式持久化不同,AOF提供的是增量式持久化功能,核心原理是:服务器每次执行完写命令后,都会以协议文本的方式降被执行的命令追加到AOF文件的末尾。当服务器在停机后,只要重新执行AOF中保存的Redis命令,就可以将数据库恢复到停机之前的状态。
3.1、开启AOF功能
用户可以通过服务器的appendonly选项来决定是否打开AOF持久化功能
appendonly <value>
- appendonly yes :开启AOF持久化功能
- appendonly no :关闭AOF持久化功能
如果开启了AOF持久化功能,Redis服务器在默认情况下将创建一个名为 appendonly.aof 的文件作为AOF文件
3.2、配置AOF文件的冲洗频率
当程序通过系统对文件进行写入时,系统并不会直接将数据写入硬盘,而是会将数据写入位于内存的缓冲区中,等到数据达到某些写入条件或者达到某个时限,系统才会将缓冲区的数据刷到硬盘中,从而提高程序的性能,但是也会给程序的写入操作带来不确定性。所以AOF就想用户提供了appendfsync 选项,用来控制系统冲洗AOF文件的频率,语法如下:
appendfsync <value>
appendfsync 的选项有:always、everysec、no 3个值,代表的意义分别如下:
- always :每执行一个写命令,就对AOF文件执行一次冲洗操作
- everysec :每隔1s,就对AOF文件执行一次冲洗操作
- no :不主动对AOF文件进行冲洗操作,由操作系统决定何时对AOF进行冲洗
Redis使用 everysec 作为 appendfsync 选项的默认值,所以没有明确的需求,尽量不要去修改这个选项的值。
3.3、AOF重写
随着服务器不断运行,被执行的命令变得越来越多,那么记录这些命令的AOF文件就变成越来越大,假设对同一个键做了很多的修改操作,那么AOF文件中就会出现很多的冗余命令,比如:
127.0.0.1:6379> set fruit apple
OK
127.0.0.1:6379> set fruit orange
OK
127.0.0.1:6379> set fruit banana
OK
127.0.0.1:6379> sadd set v1
(integer) 1
127.0.0.1:6379> sadd set v2
(integer) 1
127.0.0.1:6379> sadd set v3
(integer) 1
127.0.0.1:6379> srem set v3
(integer) 1
127.0.0.1:6379> sadd set v4
(integer) 1
实际上这些命令对数据库的最终修改效果可以简化为:
set fruit banana
sadd set v1 v2 v4
这就是我们要提到的Redis提供的AOF重写功能,该功能能够生成一个全新的AOF文件,并且文件中只包含恢复当前数据库所需的尽可能少的命令。
3.3.1、BGREWRITEAOF命令(手动)
用户可以通过执行BGREWRITEAOF 命令来显示地触发AOF重写,该命令是一个异步命令,Redis服务器接收到该命令之后会创建一个子进程,由它扫描整个数据库并生成新的AOF文件,当新的AOF文件生成完毕,子进程就会退出并通知Redis,然后Redis服务器就会使用新的AOF文件替代原来的AOF文件,完成重写操作。这个过程和我们之前RDB异步持久化差不多。不懂的可以看本文的2.2章节
BGREWRITEAOF
- 如果发送BGREWRITEAOF 时,服务器在创建RDB文件,那么AOF重写操作会延到RDB文件创建完毕之后
- 如果发送BGREWRITEAOF 时,已经在做重写操作,那么就会报错,提示AOF重写操作已经在处理了
3.3.2、AOF重写配置选项(自动)
除了手动执行BGREWRITEAOF 命令创建AOF文件之外,还可以通过设置一下两个配置选项让redis自动触发BGREWRITEAOF 命令。
auto-aof-rewrite-percentage 100 #文件体积增大100%就自动重写
auto-aof-rewrite-min-size 64mb #文件体积小于64mb不会重写
- auto-aof-rewrite-min-size:设置触发自动重写AOF文件所需的最小的文件大小
- auto-aof-rewrite-percentage:设置触发自动重写AOF文件所需要的文件大小增大的比例
四、RDB-AOF混合持久化
4.1、RDB和AOF的优劣
上面我们介绍了Redis的两种持久化方式
- RDB持久化,生成的RDB文件比较小,使用RDB文件进行恢复时速度非常快,但是RDB的全量式持久化模式可能会让服务器丢失大量数据
- AOF持久化,存储的是协议文本,文件会比较大,并且使用AOF文件进行恢复时相对较慢(通过执行AOF文件中的命令),但是AOF持久化丢失的数据可以控制在1秒内
4.2、开启RDB-AOF混合持久化
从Redis4.0开始引入了RDB-AOF混合持久化模式,这种模式还是基于AOF模式构建的,需要的两个条件是:
- 开启了AOF持久化功能
- 设置 aof-use-rdb-preamble yes
满足这两个条件后,如果Redis在执行AOF重写操作时(上面介绍过),就会像执行BGSAVE命令那样,根据数据库当前的状态生成相应的RDB数据,并且将这个数据写入到新建的AOF文件中,那些在重写之后的命令,则会继续以协议文本的方式追加到AOF文件的末尾,也就是说,我们的服务器生成的AOF文件由两部分组成,最前面是RDB格式的数据,后面则是AOF格式的数据。
4.3、RDB-AOF混合持久化文件载入
开启了RDB-AOF混合持久化模式的Redis服务器启动并载入AOF文件时,它会检查AOF文件的开头是否包含RDB格式的内容:
- 如果包含,那么就会先载入开头的RDB数据,然后在载入之后的AOF数据
- 如果不包含,那么就直接载入AOF数据
大致的流程图如下:
结语
从Redis4.0之后我们应该优先使用RDB-AOF混合持久化,如果是Redis4.0之前的版本,RDB更像是数据备份,AOF更接近数据持久化,可以优先使用AOF持久化,并将RDB当做辅助(比如手动)数据备份手段。