Redis持久化详解

Redis支持的持久化方式

在Redis4.0版本之前,Redis支持两种持久化方式,RDB以及AOF,RDB是通过快照也就是记录所有数据的方式,后者是通过记录redis执行的修改命令的方式。从Redis4.0版本支持RDB以及AOF混合的方式,目的就是为了结合两者优点。所以下面从RDB以及AOF开始介绍。

(一)RDB持久化方式(全量)

该方式将内存中的所有数据生成一份副本并存储在硬盘上,这个过程即为 快照

触发快照的几种情况如下:
1)根据配置规则进行自动快照

在这里插入图片描述
上面是对redis.conf默认配置,意思是60s内如果有10000个更新命令则执行快照,300s内如果有10个更新命令则执行快照,900s内如果有1个更新命令则执行快照。
——换种理解方式,有一个从0开始计数的秒表,当计时到60s时,如果更新命令达10000个则执行快照,否则继续计时,如果计时到300s时,如果更新命令达300个则执行快照,然后将秒表归零重新计时。

2)执行save或bgsave命令(主动快照)

save同步地进行快照,过程中阻塞客户端的请求。当数据较多时,可能导致redis长时间不响应
bgsave:后台(background)异步地进行快照,可以继续响应客户端的请求。该过程因为是异步的进行,执行该命令将立即返回结果,可通过lastsave命令查询最近执行快照的成功时间。

save命令也就是调用redis进程去执行快照,这里来看一下bgsave是怎么实现的?

  1. 首先查看是否有AOF/RDB子进程正在执行,有的话返回错误。
  2. Redis使用fork函数复制父进程也就是当前进程的副本,子进程。
  3. 父进程继续响应客户端请求,子进程将内存数据写入到硬盘临时文件中。
  4. 当子进程写完数据后用临时文件替换旧的RDB文件。

从第2步开始调用fork函数时操作系统会调用copy-on-write策略,那么什么是copy-on-write策略?
copy-on-write即复制父进程后子父进程共享同一个内存数据,当父进程更新某片数据时,操作系统将该片数据复制一份给父进程操作,也就是子进程快照的是执行fork这一刻的内存数据。(不需要复制一份一模一样的内存数据供子进程进行操作)
在这里插入图片描述
快照后的数据,完全无法解读 (默认dump.rdb)
在这里插入图片描述

3)执行FLUSHALL命令清除数据库所有数据

注意:前提必须是设置了自动快照条件(redis.conf的save配置)且没有开启AOF持久化。只要设置了,即使未满足自动快照条件,也会触发一次快照。

4)执行复制时

当设置了主从模式时,Redis会在复制初始化时自动进行快照。

(二)AOF持久化方式(增量)

AOF持久化默认关闭,通过设置appendonly yes开启持久化。该方式每执行一次更新指令,就会将指令写入硬盘的AOF文件中。但随着时间的推移,AOF文件中的日志越来越长,服务器重启Redis后重放AOF日志的过程将非常耗时,可能导致重启后的一段时间无法对外提供服务。

先来看一个问题,AOF是否直接将命令记录在AOF文件中?

其实不然,由于操作系统的缓存机制,数据先是被写入到系统的硬盘缓存(好像有叫AOF缓冲区,下面直接称AOF缓冲区),Redis将在指定时间将AOF缓冲区的数据写入到硬盘AOF文件。时间可通过下列参数进行配置:

# appendfsync always 每次执行都会同步
appendfsync everysec (Redis默认,每秒执行一次同步)
# appendfsync no 由操作系统决定,默认30s
下面我们具体来看看AOF重写

上面说到可以通过AOF重写来优化AOF文件,举一个例子来看看重写究竟怎么优化了我们的AOF文件?
下面我们对key进行了3次修改,但前两条都是没有必要的,AOF重写就是帮我们将前两条去掉,这样就能帮我们节省不必要的空间。

set key 1	    经过AOF重写
set key 2     ------------->    set key 3
set key 3

AOF重写主要是以下两种方式:
1)可通过BGREWRITEAOF命令手动重写AOF
2)自动重写AOF的相关配置(自动执行BGREWRITEAOF命令):
Redis自动重写AOF文件的条件设置(redis.conf)

# 当前AOF文件超过上传重写时AOF文件大小的多少百分比时再次重写
auto-aof-rewrite-percentage 100
# 达到多少时进行重写
auto-aof-rewirte-min-size 64mb
AOF文件重写过程
  1. Redis使用fork函数复制父进程也就是当前进程的副本,子进程。
  2. 父进程继续响应客户端请求,同时写入更新命令到AOF缓冲区 (注意下面没有画出来,上面已经解释过了) 以及AOF重写缓冲区。
  3. 子进程遍历内存数据,将每个键值的最新状态输出到临时文件。当子进程写完后,通知父进程。
  4. 父进程调用信号处理函数,将阻塞父进程对外读写能力 (极短时间) 将AOF重写缓存区中的内容追加到新的AOF文件中。
  5. 最后替换掉旧的AOF文件。

在这里插入图片描述
appendonly.aof中存储的数据 (可读性好)
在这里插入图片描述

现在我们已经分别认识了RDB以及AOF持久化方式,下面来具体总结一下其各自的优缺点:

RDB

  • 优:数据小,恢复快
  • 缺:无法保证最后一次快照以后的数据不会丢失

AOF

  • 优:可读性好、数据不易丢失
  • 缺:数据大,恢复时间长

(三)混合持久化方式

如果使用RDB,可能会导致数据丢失。如果使用AOF,重放AOF日志性能相对RDB又较慢,Redis重启会花更多时间。在Redis4.0后,推出了混合持久化的方式,将RDB与AOF相结合。

通过aof-use-rdb-preamble yes开启

混合持久化依旧是是通过bgrewriteaof命令完成的,不同之处在于,fork出的子进程先将内存数据以RDB的方式写入AOF文件,通知父进程,再通过AOF的方式将AOF重写缓冲区追加到AOF文件中,最后完成替换。即前半段存储的是RDB格式,后半段存储的是AOF格式(因此存储的大部分是RDB文件,提高了Redis重启后加载速度,也保证了快照之后的日志也能够被记录,缺点就是会导致可读性变差)。
在这里插入图片描述
开启了混合持久化之后,在Redis重启加载时,如果发现AOF文件是以RDB格式开始,则在加载完RDB格式后,会再加载AOF格式。如果未开启,则直接加载AOF文件。

appendonly.aof
在这里插入图片描述

如果个人理解有误,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值