Redis持久化整理

RDB快照

在指定的时间间隔内将内存中的数据集快照写入磁盘,默认的文件名为dump.rdb

在默认情况下,Redis将内存数据库快照保存在名字为dump.rdb的二进制文件中;

在redis.conf配置下可以看出,如下:

rdbcompression:导出rdb数据库文件压缩字符串和对象,默认是yes,会浪费CPU但是节省空间;
rdbchecksum:导入时是否检查;
  • 测试redis-cli SHUTDOWN关闭redis进程后,数据是否恢复

  在redis中保存几条数据

  

  立刻停掉redis进程

  

  重启redis服务,之前保存的数据还在,通过redis-cli SHUTDOWN这种方式去停掉redis,其实是一种安全退出的模式,redis在退出的时候会将内存中的数据立即生成一份完整的rdb快照,dump.rdb;

  

  • 测试kill -9 关闭redis进程后,数据是否恢复

  使用kill -9 将redis进程杀掉,docker搭建的使用docker kill命令,发现redis数据没有进dump文件,之前的数据丢失;

  

   

  重启redis服务,之前保存的数据不在了;

  

产生快照的方式:

  • save m n
    • save m n 表示m秒内数据集存在n次修改 时,自动触发bgsave命令;  
    • 可以对 Redis 配置文件进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集,改动包括新增或者修改,不包括查询,自动保存一次数据集:
save 900 1 则表明在 900 秒内,至少有一个键发生改变,就会触发 RDB 持久化
save 300 10 则表明在 300 秒内,至少有10个键发生改变,就会触发 RDB 持久化
save 60 10000 则表明在 60 秒内,至少有10000个键发生改变,就会触发 RDB 持久化

  满足以上任意一个条件,Redis 就会自动触发bgsvae命令进行持久化工作;关闭RDB只需要将所有的save保存策略注释掉即可;

  • 可以手动执行命令生成RDB快照,进入redis客户端执行命令savebgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件

  save和bgsave对比:

命令 save bgsave
IO类型 同步 异步
是否阻塞redis其它命令 否(在生成子进程执行调用fork函
数时会有短暂阻塞)
复杂度 O(n) O(n)
优点 不会消耗额外内存 不阻塞客户端命令
缺点

会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止

需要fork创建子进程,消耗内存,RDB持久化过程由子进程负责,会在后台异步进行快照操作,快照同时还可以响应客户端请求

  配置自动生成rdb文件后台使用的是bgsave方式;

缺点

  • 每次快照是一次全量备份,fork子进程进行后台操作,子进程存在开销;
  • 在快照持久化期间修改的数据不会被保存,可能丢失数据;

AOF(append-only file)

如果Redis 因为某些原因而造成故障停机,那么服务器将丢失最近写入、且仍未保存到快照中的那些数据,从 1.1 版本开始,Redis 增加了一种完全耐久的持久化方式: AOF 持久化将修改每一条指令追加文件的方式记录进文件appendonly.aof中, 重启时再重新执行AOF文件中的命令达到恢复数据的目的,写入过程宕机,也不影响之前的数据,可以通过 redis-check-aof检查修复问题;

aof文件存储如下:

$6
SELECT
$1
0
*3
$3
set
$2
k1
$3
111

上面的是基于RESP协议存储的文本,RESP 协议在Redis1.2被引入,直到Redis2.0才成为和Redis服务器通信的标准;RESP 是一个支持多种数据类型的序列化协议:简单字符串(Simple Strings),错误( Errors),整型( Integers), 大容量字符串(Bulk Strings)和数组(Arrays);

当程序读入这个 AOF 文件时, 它首先执行 SELECT 0 命令 —— 这个 SELECT 命令是由 AOF 写入程序自动生成的, 它确保程序可以将数据还原到正确的数据库上,然后再执行后面的保存的命令;

以星号* 为首字符,接着是表示数组中元素个数的十进制数;

美元符 "$" 后面跟着组成字符串的字节数(前缀长度); 

参考:[https://www.redis.com.cn/topics/protocol.html]

修改配置文件来打开 AOF 功能:

# appendonly yes

加载AOF出错时记录日志

# yes表示如果aof尾部文件出问题,写log记录并继续执行,no表示提示写入等待修复后写入
​aof-load-truncated yes 

每当Redis执行一个改变数据集的命令时(比如 set), 这个命令就会被追加到 AOF 文件的末尾,Redis重新启动时,程序就可以通过重新执行 AOF文件中的命令来达到重建数据集的目的

配置Redis隔多久进行一次将数据fsync到磁盘如下:

  • appendfsync always:每执行一个命令保存一次;每次有新命令追加到 AOF 文件时就执行一次 fsync ;写入和保存都由主进程执行,两个操作都会阻塞主进程,服务器必须阻塞直到命令信息被写入并保存到磁盘之后, 才能继续处理请求;
  • appendfsync everysec:每一秒钟保存一次;写入操作由主进程执行,阻塞主进程,保存操作由子线程执行,不直接阻塞主进程,但保存操作完成的快慢会影响写入操作的阻塞时长;
  • appendfsync no:不保存;写入和保存都由主进程执行,两个操作都会阻塞主进程,保存操作只会在AOF 关闭或 Redis 关闭时执行 或者由操作系统触发,系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行);

参考:[https://redisbook.readthedocs.io/en/latest/internal/aof.html#id9]

  • 测试kill -9杀掉redis进程后,数据是否恢复

  保存数据

  

  此时appendonly.aof文件存储如下:

  

  使用kill -9 将redis进程杀掉,docker搭建的使用docker kill命令,之后再重启redis服务;发现数据被恢复回来了,就是从AOF文件中恢复回来的;

  

AOF破损文件的修复

如果redis在append数据到AOF文件时,机器宕机了,这时候可能会导致AOF文件破损;使用如下命令来修复破损的AOF文件:

redis-check-aof --fix

AOF重写

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件;


Redis配置AOF自动重写频率:

# auto-aof-rewrite-min-size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
# auto-aof-rewrite-percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写

AOF重写触发条件:[https://redisbook.readthedocs.io/en/latest/internal/aof.html#id14]

AOF可以进行手动重写,进入Redis客户端执行命令bgrewriteaof重写AOF;

Redis启动时,先看是否存在aof文件,若存在则优先选择aof文件恢复数据,因为aof一般来说数据更全一点,若aof不存在,则才会查找rdb是否存在;

参考:[https://redisbook.readthedocs.io/en/latest/internal/aof.html#id13]

混合持久化(Redis 4.x以后的特性)

重启 Redis 时,很少使用 RDB来恢复内存状态,因为会丢失大量数据;通常使用 AOF 日志重写,但是重写AOF日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间; 为了解决这个问题,Redis 4.0带来了一个新的持久化选项——混合持久化

通过以下配置可以开启混合持久化:

# aof-use-rdb-preamble yes

开启了混合持久化,在AOF重写时,不再是单纯将内存数据转换为RESP协议的命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换


appendonly.aof文件存储如下:

AOF文件上半部分存储的是RDB的数据,下半部分的是AOF的数据; 

格式如下:

AOF根据配置规则在后台自动重写aof文件,也可以人为执行命令bgrewriteaof重写AOF;

操作前appendonly.aof文件存储如下:

执行set操作

  

执行set操作后appendonly.aof文件存储如下:

执行bgrewriteaof操作:

执行bgrewriteaof操作后appendonly.aof文件存储如下:

Redis在重启时,先重写rdb到内存,然后在重写aof到内存,因此重启效率得到提升;后面的修改操作则通过重写增量AOF日志替代之前的AOF全量文件重写

重启后appendonly.aof文件存储如下:

原文地址:https://www.cnblogs.com/coder-zyc/p/15085089.html