在Redis4.0版本之前,Redis支持两种持久化方式,RDB以及AOF,RDB是通过快照也就是记录所有数据的方式,后者是通过记录redis执行的修改命令的方式。从Redis4.0版本支持RDB以及AOF混合的方式,目的就是为了结合两者优点。所以下面从RDB以及AOF开始介绍。
该方式将内存中的所有数据生成一份副本并存储在硬盘上,这个过程即为 快照。
上面是对redis.conf默认配置,意思是60s内如果有10000个更新命令则执行快照,300s内如果有10个更新命令则执行快照,900s内如果有1个更新命令则执行快照。
——换种理解方式,有一个从0开始计数的秒表,当计时到60s时,如果更新命令达10000个则执行快照,否则继续计时,如果计时到300s时,如果更新命令达300个则执行快照,然后将秒表归零重新计时。
save:同步地进行快照,过程中阻塞客户端的请求。当数据较多时,可能导致redis长时间不响应。
bgsave:后台(background)异步地进行快照,可以继续响应客户端的请求。该过程因为是异步的进行,执行该命令将立即返回结果,可通过lastsave命令查询最近执行快照的成功时间。
save命令也就是调用redis进程去执行快照,这里来看一下bgsave是怎么实现的?
从第2步开始调用fork函数时操作系统会调用copy-on-write策略,那么什么是copy-on-write策略?
copy-on-write即复制父进程后子父进程共享同一个内存数据,当父进程更新某片数据时,操作系统将该片数据复制一份给父进程操作,也就是子进程快照的是执行fork这一刻的内存数据。(不需要复制一份一模一样的内存数据供子进程进行操作)
快照后的数据,完全无法解读 (默认dump.rdb)
注意:前提必须是设置了自动快照条件(redis.conf的save配置)且没有开启AOF持久化。只要设置了,即使未满足自动快照条件,也会触发一次快照。
当设置了主从模式时,Redis会在复制初始化时自动进行快照。
AOF持久化默认关闭,通过设置appendonly yes开启持久化。该方式每执行一次更新指令,就会将指令写入硬盘的AOF文件中。但随着时间的推移,AOF文件中的日志越来越长,服务器重启Redis后重放AOF日志的过程将非常耗时,可能导致重启后的一段时间无法对外提供服务。
其实不然,由于操作系统的缓存机制,数据先是被写入到系统的硬盘缓存(好像有叫AOF缓冲区,下面直接称AOF缓冲区),Redis将在指定时间将AOF缓冲区的数据写入到硬盘AOF文件。时间可通过下列参数进行配置:
# appendfsync always 每次执行都会同步
appendfsync everysec (Redis默认,每秒执行一次同步)
# appendfsync no 由操作系统决定,默认30s
上面说到可以通过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
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文件。
如果个人理解有误,欢迎指正。