redis的持久化有3种:
- RDB持久化
- AOF持久化
- RDB-AOF混合持久化
15.1 RDB 持久化
- redis默认使用RDB
- 将数据库中存储的键值对数据存放在一个经过压缩的二进制文件中,文件的扩展类型为
.rdb
- 有几种方式创建rbd文件:
SAVE
- 阻塞服务器并创建 RDB 文件
- 若存在旧的rdb文件则覆盖
BGSAVE
- 以非阻塞的方式创建 RDB 文件
- 以创建子进程的方式创建RDB文件
- 当创建完成后子进程会通知主进程创建完成,并用新文件替换之前的旧文件
- 注意:如果父进程占用的内存数量非常大,那么在fork子进程时仍然可能造成短暂的阻塞
- 通过配置选项自动创建RDB文件
save <seconds> <changes>
服务器在seconds秒内至少执行了changes次修改,那么服务器会自动执行一次BGSAVE
命令- 可以同时使用多个上述命令,任一命令满足时就会执行一次
- 默认配置:
save 60 10000
save 300 100
save 3600 1
- RDB 文件结构
-
-
RDB 文件标识符
-
版本号
- 新版服务器总是能够向下兼容旧版redis服务器生成的RDB文件
-
设备附加信息
- 包含服务器版号、宿主机的架构、创建RDB文件的时间戳、服务器占用的内存数量
-
数据库数据
- 按顺序存放数据库数据,从0到n
- 结构如下:
- 数据库号码
- 键值对总数量
- 带有过期时间的键值对数量
- 键值对数据部分
- RDB 文件将以无序方式记录数据库包含的键值对
- 数据库中的每个键值对都会被划分为最多5个部分:
- 过期时间(可选),毫秒精度的UNIX时间戳
- LRU信息(可选)
- LFU信息(可选)
- 类型
- 键
- 值
-
lua脚本缓存
-
EOF
-
CRC64校验和
- 服务器在读入 RDB 文件时会通过这个校验和来快速地检查 RDB 文件是否出错或者损坏的情况出现
-
- 服务器载入 RDB 文件过程
- redis 服务器启动,在工作目录中查找是否有 RDB 文件,如果有则加载
- 检查文件开头的标识符
- 检查文件的 RDB 版号判断是否支持
- 根据文件中记录的设备附加信息,执行相应的操作和设置
- 检查数据库部分是否为空,若非空,则执行子操作:
- a. 根据数据库号码,切换到正确数据库
- b. 根据键值对总数量、带过期时间的键值对数量 创建数据库底层数据结构
- c. 逐一读取并创建
- 如果服务器启用了复制功能,那么将之前缓存的lua脚本重新加载到缓存中
- 遇到EOF标识,确认 RDB 正文以及全部读取完毕
- 读取文件的CRC64校验和,与载入过程中计算的校验和对比,以此判断数据是否完整
- RDB 持久化的缺陷
- RDB 是一种全量持久化操作,它在创建的时候需要整个服务器包含的数据,这会消耗大量计算资源和内存资源,用户不太可能通过非常高的生成频率来保证数据安全
- RDB 更像是一种数据备份手段
15.2 AOF 持久化
- AOF 提供增量式的持久化功能
- 服务器每次执行完写命令后,都会以协议文本的方式将被执行的命令追加到AOF文件的末尾
- 只需要重新执行 AOF 文件中保存的redis 指令,就可以将数据库恢复
- 在实际的 AOF 文件中,命令都是以 redis 网络协议的方式保存的
15.2.1 打开 AOF 持久化功能
appendonly yes
打开appendonly no
关闭
15.2.2 设置 AOF 文件的冲洗频率
现代操作系统为了提高写入性能,通常会把多次硬盘写合并成一次,这种优化机制会对 AOF 持久化的安全性产生影响。
为了消除这种不确定性,redis提供了 appendfsync <value>
配置,<value>
一共有三种选项:
- always
每执行一个写命令,就 flush 一次 (最多丢失一条命令)
- everysec
每隔 1s flush 一次 (默认值)
- no
不主动对AOF 文件执行冲洗操作,由操作系统决定何时对AOF文件进行冲洗
15.2.3 AOF 重写
redis 服务器经过长期运行后,AOF 文件中将产生大量命令,可以通过重写的方式在减小文件体积的同时页满足逻辑一致。
redis 提供了 BGREWRITEAOF
这个异步命令重写 AOF 文件,fork 一个子进程进行重写
注意:
- 如果用户发送
BGREWRITEAOF
命令时,服务器正在创建RDB文件,那么会等待RDB文件创建完成后再执行(避免同时写硬盘导致机器性能下降) - 如果执行
BGREWRITEAOF
命令的时候又接收到相同的命令,那么会返回rewriting already in progress
的错误
AOF 自动重写配置选项
auto-aof-rewrite-min-size
- AOF 文件体积大于
auto-aof-rewrite-min-size
将触发 AOF 重写 - 默认 64mb
- AOF 文件体积大于
auto-aof-rewrite-percentage
- 当前 AOF 文件的体积比上一次重写后的体积增加了
auto-aof-rewrite-percentage
后将触发重写
- 当前 AOF 文件的体积比上一次重写后的体积增加了
15.2.4 AOF 持久化的优缺点
- 优点
- 与 RDB 持久化可能丢失大量数据相比,AOF 持久化的安全性要高得多,通过使用
everysec
选项,可以将数据丢失的窗口限制在1s内
- 与 RDB 持久化可能丢失大量数据相比,AOF 持久化的安全性要高得多,通过使用
- 缺点
- AOF文件存储的是协议文本,会比包含相同逻辑数据、二进制格式的RDB文件要大得多,生成AOF文件所需要的时间也会比RDB方式更多
- AOF文件恢复的方式是逐一执行redis命令,这使得数据恢复相比RDB慢很多
- AOF重写使用的
BGREWRITE
与 RDB 使用的BGSAVE
一样,fork 一个子进程,在数据库体积较大的情况下,都将占用大量的cpu和内存,导致服务器被短暂阻塞
15.3 RDB-AOF混合持久化
redis4.0 版本引入RDB-AOF混合持久化模式
打开服务器的AOF持久化功能,并且将aof-use-rdb-preamble <value>
选项置为yes
, 那么服务器在执行AOF重写操作的时候,会像执行BGSAVE
命令一样,根据数据库当前状态生成出相应的RDB数据,并且将这些数据写入到新建的AOF文件中。
重写开始后执行的redis命令,将以协议文本的方式追加到新AOF文件末尾。
恢复流程:
既可以得到RDB文件恢复快的优点,又可以得到AOF文件将数据丢失的时间窗口限制在1s之内的有点
目前默认没有打开此功能
15.4 同时使用 RDB 持久化和 AOF 持久化
- redis4.0后同时使用RDB持久化和AOF持久化已经不再必要
- 优先使用RDB-AOF混合持久化
注意:
- redis服务器启动时,会优先使用AOF文件进行数据恢复,只有在没有检测到 AOF 文件时,才考虑使用RDB文件进行数据恢复
15.5 无持久化
如果用户没有显式的开启持久化功能,那么redis服务器会默认使用以下配置进行RDB持久化:
|
|
如果想完全关闭持久化功能,可以使用save ""
取代,服务器将处于完全的无持久化状态中
15.6 SHUTDOWN 关闭服务器
当redis服务器接收到shutdown命令时,将执行:
- 停止处理客户端发送的命令请求
- 根据持久化配置,决定是否执行数据保存操作:
- 如果启用了RDB持久化,且数据库内容和RDB文件已经产生了差别,那么服务器将执行一次
SAVE
命令,用新的RDB文件覆盖。 - 如果启用了AOF持久化或者RDB-AOF混合持久化功能,那么它将冲洗AOF文件
- 如果都没有开启,那么将跳过
- 如果启用了RDB持久化,且数据库内容和RDB文件已经产生了差别,那么服务器将执行一次
- redis服务器退出
可以显式的指定shutdown [save|nosave]
进行持久化操作:
如果指定的是nosave选项,那么将不管持久化配置,直接关闭服务器,这可能丢失最后一次保存后的数据。