深入学习Redis(2):持久化 (5)

深入学习Redis(2):持久化

状态可以通过info persistence查看:

深入学习Redis(2):持久化

只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个参数同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。

自动触发bgrewriteaof时,可以看到服务器日志如下:

深入学习Redis(2):持久化

文件重写的流程

文件重写流程如下图所示(图片来源:):

深入学习Redis(2):持久化

关于文件重写的流程,有两点需要特别注意:(1)重写由父进程fork子进程进行;(2)重写期间Redis执行的写命令,需要追加到新的AOF文件中,为此Redis引入了aof_rewrite_buf缓存。

对照上图,文件重写的流程如下:

1) Redis父进程首先判断当前是否存在正在执行 bgsave/bgrewriteaof的子进程,如果存在则bgrewriteaof命令直接返回,如果存在bgsave命令则等bgsave执行完成后再执行。前面曾介绍过,这个主要是基于性能方面的考虑。

2) 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的。

3.1) 父进程fork后,bgrewriteaof命令返回”Background append only file rewrite started”信息并不再阻塞父进程,并可以响应其他命令。Redis的所有写命令依然写入AOF缓冲区,并根据appendfsync策略同步到硬盘,保证原有AOF机制的正确。

3.2) 由于fork操作使用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然在响应命令,因此Redis使用AOF重写缓冲区(图中的aof_rewrite_buf)保存这部分数据,防止新AOF文件生成期间丢失这部分数据。也就是说,bgrewriteaof执行期间,Redis的写命令同时追加到aof_buf和aof_rewirte_buf两个缓冲区。

4) 子进程根据内存快照,按照命令合并规则写入到新的AOF文件。

5.1) 子进程写完新的AOF文件后,向父进程发信号,父进程更新统计信息,具体可以通过info persistence查看。

5.2) 父进程把AOF重写缓冲区的数据写入到新的AOF文件,这样就保证了新AOF文件所保存的数据库状态和服务器当前状态一致。

5.3) 使用新的AOF文件替换老文件,完成AOF重写。

3. 启动时加载

前面提到过,当AOF开启时,Redis启动时会优先载入AOF文件来恢复数据;只有当AOF关闭时,才会载入RDB文件恢复数据。

当AOF开启,且AOF文件存在时,Redis启动日志:

深入学习Redis(2):持久化

当AOF开启,但AOF文件不存在时,即使RDB文件存在也不会加载(更早的一些版本可能会加载,但3.0不会),Redis启动日志如下:

深入学习Redis(2):持久化

文件校验

与载入RDB文件类似,Redis载入AOF文件时,会对AOF文件进行校验,如果文件损坏,则日志中会打印错误,Redis启动失败。但如果是AOF文件结尾不完整(机器突然宕机等容易导致文件尾部不完整),且aof-load-truncated参数开启,则日志中会输出警告,Redis忽略掉AOF文件的尾部,启动成功。aof-load-truncated参数默认是开启的:

深入学习Redis(2):持久化

伪客户端

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzxgzs.html