Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记

前言

本文主要内容:
Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第1张图片
SAVE和BGSAVE的区别:
Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第2张图片
RDB和AOF的选择:
Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第3张图片
内容为《深入分布式缓存:从原理到实践》的相关读书笔记。

持久化

Redis的持久化有两种方式:全量模式RDB和增量模式AOF。

全量模式RDB

基于全量模式的持久化Redis作为一个有状态节点,其“状态”可以用实例内部所有db的key-value值来定义,每一次Redis处理一个数据访问写命令修改了db的key-value数据时,Redis就发生了一次状态变迁。基于全量的持久化即在持久化触发的时刻,将当时的状态(所有db的key-value值)完全保存下来,形成一个snapshot,如图所示。

Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第4张图片

当Redis重启时,通过加载最近一个snapshot数据,可将Redis恢复至最近一次持久化时的状态上。

RDB写入流程

全量写入包含两种方式:SAVE和BGSAVE,两者逻辑如图所示:
Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第5张图片
SAVE可以由客户端显式触发,也可以在redis shutdown时触发,无论以哪种形式触发,SAVE本身都是以普通命令的方式执行——单进程串行化地执行一个一个命令。SAVE的执行过程就是把Redis的当前状态写入磁盘作为快照保存的过程,期间其他所有命令不会并发执行,所以即便写入磁盘的过程持续时间很长,数据的状态始终是一致的,不会发生变更。

BGSAVE可以由客户端通过命令显示触发、可以通过配置由定时任务触发(例如当上次持久化离现在已经积累了一定次数的变更且间隔时间超过一定值),也可以在master-slave的分布式结构下由slave节点触发(主从同步)。

BGSAVE命令执行始于fork出一个子进程,在子进程成功启动之后修改一些redisServer对象的状态之后执行完毕,Redis进程的主循环接着处理后续命令。将Redis数据状态写入磁盘的工作由子进程并发地完成,这个写入操作可能会持续数秒到几十分钟不等,期间不影响Redis对外服务的可用性。

对于BGSAVE,写入磁盘快照的状态来源于子进程fork时的Redis数据状态,因此父进程一旦完成fork,后续执行的新的客户端命令对数据状态产生的变更(如修改了某个key-value值)将不会反应在本次快照文件中,无论这些后续命令在子进程完成文件写入之前还是之后。子进程写入文件面对的是父进程在fork时的数据库状态副本,该副本在整个磁盘写入期间不会发生变更。BGSAVE相比于SAVE的优势是持久化期间可以持续提供数据读写服务,作为代价,子进程fork时,涉及父进程内存的复制,其存在期间会增加服务器内存的开销,当内存开销高到不得不使用虚拟内存时,BGSAVE的fork会阻塞服务器运行,造成秒级以上的不可用。因此,使用BGSAVE需保证Redis服务器空闲内存足够。

RDB数据恢复

从Redis启动到进入前文所述事件处理主循环时,Redis会从本地磁盘加载之前持久化的文件,将内存置于文件所描述的数据“状态”时,再受理后续来自客户端的数据访问命令。

增量模式AOF

基于全量的持久化保存的是数据的“状态”,而增量持久化保存的则是状态的每一次“变迁”。当初始状态给定,经过相同的“变迁”序列之后,最终的状态也是确定的。因此基于增量持久化数据,可以通过对给定初始状态之后的变迁回放,恢复出数据的终态。在Redis中,增量持久化称为AOF(append-only file)方式,在此基础上以rewrite机制优化性能。如图所示,Redis仅对数据的变化进行存储。

Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第6张图片

写入流程Redis的增量持久化在主循环中的每次处理完写命令的执行之后,通过propagate函数触发,如图所示。

Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第7张图片
propagate方法将当前命令的内容append到redisServer对象的aof_buf变量中。主循环在下一个迭代进入多路复用的select方法前,Redis会通过flushAppendOnlyFile方法将aof_buf的内容write到AOF对应的文件中。但write操作只是将数据写到缓存中,什么时候从缓存真正落地到磁盘上,取决于操作系统。只有显式调用fsync()方法才能强制地让操作系统落地数据到磁盘。

Redis的AOF包含3种同步策略:
❑ always:主循环的每个迭代的flushAppendOnlyFile函数中直接同步触发fsync方法,强制数据落地磁盘。该策略会降低Redis吞吐量,使得磁盘的写入成为Redis对外写服务的瓶颈,但由于每个命令都在写入磁盘后才返回,这种模式拥有最高的容错能力。
❑ every second:每秒异步地触发一次fsync方法。fsync方法的执行者是bio线程池中的某个线程。flushAppendOnlyFile函数只是作为生产者将fsync任务放入队列,由bio线程消费并执行。
❑ no:不显式调用fsync,由操作系统决定什么时候落地磁盘。这种模式下,Redis无法决定增量的落地时间,因此容错能力不可控。

对于every second策略,Redis实际的吞吐量仍然和磁盘的写入能力相关,只是1秒钟内的请求可能会被批量一次性落地到磁盘提升写入吞吐量,但Redis的对外写服务吞吐量仍然不可能超过磁盘的写入吞吐量,否则会造成bio任务队列积压,通常为保护内存用量会限制任务队列的长度使得后续提交任务时阻塞。

Redis仍然通过阻塞来处理磁盘吞吐量过低的情况,但阻塞不是发生在任务队列上。Redis在发现bio执行fsync的线程还在执行中的时候,是不会再往队列提交任务的,阻塞发生在write函数上:当bio线程执行fsync时,write方法自然会阻塞。

AOF数据恢复

回放流程AOF的回放时机和全量回放一致,一旦存在AOF, Redis会选择增量回放而不是全量,因为增量持久化的数据持续地写入磁盘,相比定期全量持久化,数据更加“新”。AOF通过loadAppendOnlyFile方法回放数据,回放过程其实就是将AOF中保存的命令重新执行一遍。执行完成后,Redis才进入主循环接收后续来自客户端的新命令。

AOF优化

基于增量模式持久化的优化随着Redis持续的运行,会不断地产生新的数据append到AOF文件中,后者会日积月累越来越大,它占用了大量的磁盘空间,同时会降低Redis启动时的回放加载效率。Redis通过rewrite机制合并历史AOF记录,如图所示。

Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第8张图片
随着Redis持续的执行命令,灰色方框中的增量数据会积累到大于某个状态快照的程度,此时将这些增量用快照来代替,以减少磁盘空间占用。由于快照的状态也是历史增量的变迁结果,所以快照的信息等效于历史增量信息。

Redis的这份快照仍然用cmd的形式来承载,只是将快照的所有key-value值用插入命令来表示。这样一来,rewrite出来的快照文件和普通的AOF文件格式一致,可复用相同的加载逻辑统一处理Redis启动时的数据恢复。rewrite通过bgrewrite方法实现,如图所示。
Redis持久化:RDB和AOF、SAVE和BGSAVE、数据恢复、AOF刷盘策略、AOF的bgrewrite优化-《深入分布式缓存:从原理到实践》读书笔记_第9张图片
图中,主循环运行到定时任务处理时,一旦Redis发现Rewrite条件满足,则通过rewriteAppendOnlyFileBackground函数fork出一个子进程,后者创建完成后获得了Redis主进程的数据状态,子进程将状态写入rewrite的AOF文件中。子进程运行期间,Redis主进程继续对外提供服务,新的增量写入redisServer对象的aof_rewrite_buf_blocks中,待子进程完成后,这部分内容将append到rewrite快照文件末尾,再后续的增量,会写入新的AOF文件中。

整个过程中持久化的数据如下:
❑ 历史AOF:以快照的方式(仍然使用cmd形式,但转换成插入命令)保存;
❑ 快照写入期间的增量:待快照写入完成后append到快照文件末尾;
❑ 再后续的增量:写入新的AOF。

你可能感兴趣的:(技术类书籍读书分享)