Redis持久化整理

RDB快照

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

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

 

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

Redis持久化整理

rdbcompression:导出rdb数据库文件压缩字符串和对象,默认是yes,会浪费CPU但是节省空间; rdbchecksum:导入时是否检查;

 

产生快照的方式:

  • 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客户端执行命令save或bgsave可以生成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]

 

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文件存储如下:

Redis持久化整理

 

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

 

格式如下:

Redis持久化整理

 

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

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

Redis持久化整理

 

执行set操作

Redis持久化整理

  

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

Redis持久化整理

 

执行bgrewriteaof操作:

Redis持久化整理

 

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

Redis持久化整理

 

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

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

Redis持久化整理

 

上一篇:redis的另一个分支 keydb


下一篇:安装XAMPP遇到的问题及解决方法