Redis持久化RDB和AOF
前言
Redis
的高速建立在数据存储在内存中, 但是断电的话, 就会导致数据丢失的问题.
为此我们需要对数据进行持久化到硬盘中, 用于数据恢复.Redis
提供了两种持久化存储方案, Redis
在启动时会优先加载AOF
文件恢复数据.
AOF(Append Only File)
: 记录每次执行的命令到日志中, 恢复数据时重新执行一次日志文件中的命令.RDB(Redis Database Backup)
: 将数据库的所有数据直接写入磁盘
RDB ( Redis Database Backup )
RDB
会将当前Redis
中所有存储的数据持久化到dump.rdb
文件中.
save 持久化 ( 阻塞 )
Redis
是单线程的, 所以save
命令一旦执行, 其时间复杂度是O(n)
, 数据量一大, Redis
就会阻塞后面的请求.
所以一般不直接使用save
命令进行持久化.
bgsave 持久化 ( fork子进程 )
Redis
提供了bgsave
命令, fork
一个子进程来进行save
. 这样就不会阻塞住原本的进程.fork
后的子进程执行save
命令, 会创建一个临时RDB
文件, 待持久化完毕后, 覆盖之前的RDB
文件.
但是fork
这个操作, 仍然是阻塞的,
save seconds changes ( 定时持久化 )
Redis
的配置文件中, 还提供了另一种RDB
持久化方式, 格式: save <seconds> <changes>
1 | # save "" # 关闭 RDB |
表示seconds
秒内改变了changes
次数据, 则自动bgsave
.
缺点也很明显, 无法控制生成RDB的频率
最佳配置 ( 开启 RDB 时 )
1 | # 1. 开启默认的 save 策略, save 60 10000 视数据量而定 |
值得注意的是, 即使在配置文件中关闭RDB
自动持久化, 在以下情况, 仍会产生RDB
文件.
- 主从复制之全量复制时, 会生成RDB文件
debug reload
重启Redis, 会生成RDB文件redis-cli SHUTDOWN
保存退出时, 如果没有开启AOF, 则自动执行bgsave
AOF(Append Only File)
Redis
开启AOF
持久化的时候, 每次写操作都会追加到日志文件中. 这个顺序写操作是很快的.
并且, AOF
记录是直接写在操作系统层面的cache
内存上的, 不是直接写入磁盘的. 基于内存的操作也是很快的.
1 | # 1. 打开 AOF 持久化 |
这里有三种配置方式, 一般生产环境都用everysec
.
因为你既然用了Redis
, 那肯定是为了应对超高并发的读写操作. 如果你用了always
, 那相当于每次都写入磁盘, 就失去了读写内存带来的高性能优势了.
当然AOF
日志文件不可能无限增长, 下面介绍下如何压缩重写AOF
文件.
手动重写
假设要执行以下命令
1 | set a a |
那么AOF
肯定不会傻傻的将这3
条命令写到AOF
文件中, 因为只要保证set a c
即可.
忽略中间态, 这就是AOF
重写.
可以极大的减少AOF
文件大小, 加快AOF
恢复速度.
要手动重写, 只需要执行bgrewriteaof
命令即可.
- 首先,
Redis
会fork
一个子进程. - 基于当前内存中的数据, 而不是之前的
AOF
文件, 来生成一个新的AOF
文件. - 此时
Redis
仍在接收写请求, 会往内存、旧AOF
文件、新AOF
文件, 三个地方写入日志. - 新
AOF
文件生成完毕, 则会将内存中的AOF
日志追加写入新AOF
文件. - 用新
AOF
文件覆盖旧AOF
文件, 保证只有一个AOF
文件.
这里为什么要基于当前内存中的数据, 而不是之前的AOF
文件, 来生成一个新的AOF
文件呢?
因为这个AOF
很容易出现破损的情况, 比如断电, 磁盘满了.
然后新AOF
文件是根据破损的旧AOF
文件生成的, 又是破损的AOF
文件.
所以干脆基于内存已有数据生成新AOF
文件.
然后Redis
还提供了一个命令修复破损的AOF
记录, redis-check-aof --fix my.aof
自动重写
Redis
在2.4
之后提供了自动重写AOF
的功能, 就不用再去手动执行bgrewriteaof
了.
配置文件/etc/redis.conf
中提供了满足一定条件就自动重写的配置.
1 | # 1. 当 AOF 文件大于某个值时进行重写 |
我们可以在redis-cli
客户端查看info
信息.
1 | info persistence |
当同时满足以下条件时, AOF
文件会自动重写.
1 | aof_current_size > auto_aof_rewrite_min_size |
最佳配置 ( 开启 AOF 时 )
1 | # 1. 开启 AOF |
当 RDB 遇到 AOF
RDB
快照生成和AOF
重写操作是互斥的, 同一时间只能有一个执行.- 当同时有
RDB
和AOF
文件的时候, 优先使用AOF
文件进行数据恢复.
数据备份和恢复
不管是RDB
还是AOF
, 每次生成都会覆盖掉原有的旧文件.
那么我们就需要定时的把旧的备份文件移动到别的目录下, 避免被覆盖掉.
- 每小时复制一份
RDB
到备份目录下, 只保留48
小时的数据 - 每天复制一份
RDB
到备份目录下, 只保留1
个月的数据 - 每晚将服务器上所有
RDB
发送到远程的云存储上.
既然有备份, 就会要恢复. 恢复AOF
数据只要将AOF
文件复制到Redis
数据目录下, 然后重启Redis
即可.
恢复RDB
数据的方案就有点复杂了.
- 停止
Redis
, 修改配置文件appendonly no
. - 复制
RDB
备份到Redis
数据目录下, 重启Redis
, 确认数据恢复. - 在命令行热修改配置
config set appendonly yes
, 开启AOF
. - 停止
Redis
, 修改配置文件appendonly yes
, 重启Redis
当Redis
开启AOF
的时候, 是优先使用AOF
恢复数据的. 即使AOF
文件被删除, 也会基于重启后的数据生成一份新的AOF
文件, 然后覆盖掉你复制进来的有数据的RDB
文件, 变成一个空的RDB
文件.
所以我们才需要提前先手动把AOF
关闭. 上面的恢复步骤这么复杂, 就是为了规避这个case
带来的问题.