Redis 7持久化RDB和AOF的原理机制讲解(图文教程)
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1.概述</a></li><li><a href="#_label1">2.RDB</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">2.1 快照原理</a></li><li><a href="#_lab2_1_1">2.2 触发机制</a></li><li><a href="#_lab2_1_2">2.3 文件处理</a></li><li><a href="#_lab2_1_3">2.4 优缺点</a></li></ul><li><a href="#_label2">3.AOF</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_4">3.1 工作流程</a></li><li><a href="#_lab2_2_5">3.2 重写机制</a></li></ul><li><a href="#_label3">4.混合持久化</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>1.概述</h2><p>Redis是一个<strong>基于内存的数据库</strong>,这意味着其主要数据存储和操作均在内存中进行。这种设计使得Redis能够提供<strong>极快的读写速度</strong>(通常达到微秒级别),适用于高性能场景,如缓存</p>
<ul><li>然而,由于内存的易失性(断电后数据会丢失),Redis提供了<code>持久化机制</code>:将内存中的数据保存到磁盘中,确保数据在Redis服务重启或崩溃后能够恢复。通过持久化,可以避免数据丢失,提高数据的可靠性</li><li>Redis提供两种持久化方式<ul><li><strong>RDB(Redis Database)</strong>:生成数据集的快照实现持久化</li><li><strong>AOF(Append Only File)</strong>:记录所有写操作命令,以追加方式写入文件</li></ul></li></ul>
<p class="maodian"><a name="_label1"></a></p><h2>2.RDB</h2>
<p>RDB指的是Redis的一种持久化机制,其核心是生成Redis数据在某个时间点的<code>快照</code></p>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>2.1 快照原理</h3>
<p style="text-align:center">由于Redis是单线程应用程序,在线上环境时,不仅要处理来自客户端的请求,还要执行内存快照操作(进行文件IO)。单线程同时处理客户端请求和文件IO时会严重降低服务器性能,甚至阻塞客户端请求。因此,Redis使用 <strong>fork</strong> 和 <strong>写实拷贝(Copy On Write)</strong> 机制来实现<code>快照持久化</code><br /><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480254.png" /></p>
<blockquote><p>fork</p></blockquote>
<p> Redis在进行RDB持久化时会调用fork函数来创建一个子进程负责完成,父进程则继续处理客户端请求。子进程在创建之初和父进程共享同一数据段</p>
<p style="text-align:center"> Linux操作系统的内存空间被分为很多种片段,每个片段又被分为很多个页面,每个页面4KB<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480283.png" /></p>
<blockquote><p>写实拷贝</p></blockquote>
<p style="text-align:center"> 当父进程对数据段中的某一数据页面进行修改操作时,Linux操作系统会将该数据页面复制一份分离出来,然后对该页面进行修改,最后父进程指向指向修改后的页面。随着被修改的页面越来越多,内存空间不断膨胀,最多达到原来的两倍<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480340.png" /><br /> 从子进程被创建出来的那一刻起,直至拷贝结束,子进程始终指向原始的数据段且所有原数据段不会被修改。所以,在整个拷贝过程中 <strong>RDB快照 = 子进程看到的所有数据页面的瞬间状态集合</strong></p>
<p style="text-align:center"> 拷贝完成后,子进程会被销毁,同时<strong>没有指针指向的数据页面也会被销毁</strong><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480357.png" /></p>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>2.2 触发机制</h3>
<p>Redis RDB的触发机制分为自动触发和手动触发两种方式</p>
<ul><li>自动触发<ul><li>在redis.conf中通过save指令配置阈值。当在指定时间内发生足够数量的键修改时自动触发bgsave<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480227.png" /></li><li>正常关闭Redis<div class="jb51code"><pre class="brush:sql;"># 默认执行save(阻塞式)
> shutdown
# 或
> shutdown save
# 触发流程:
1. 停止接受新连接
2. 执行save(不是bgsave)
3. 保存完成后退出
</pre></div></li></ul></li><li>手动触发<ul><li><strong>save命令</strong>:同步阻塞式触发,执行期间Redis服务器不处理任何请求,直到RDB文件创建完成(不推荐)</li><li><strong>bgsave命令</strong>:异步非阻塞式触发,Redis会fork一个子进程执行持久化操作,主进程继续处理请求</li></ul></li></ul>
<p class="maodian"><a name="_lab2_1_2"></a></p><h3>2.3 文件处理</h3>
<p style="text-align:center"> RDB文件保存在<code>dir</code>配置指定的目录下(默认/var/lib/redis),文件名通过<code>dbfilename</code>配置指定(默认dump.sql)<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480266.png" /><br /> 在RDB备份过程中,fork出的子进程会将内存数据写入临时文件,临时文件默认命名规则为temp-< pid >.rdb,其中< pid >是子进程的进程ID。当子进程完成RDB文件写入后,Redis会用原子性的rename操作将临时文件重命名为正式RDB文件并删除原文件<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480251.png" /></p>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>2.4 优缺点</h3>
<p><code>优点</code></p>
<ul><li><strong>恢复速度快</strong>:RDB是数据的二进制快照,恢复时直接加载到内存</li><li><strong>备份时对服务影响小</strong>:使用bgsave命令时,Redis通过fork子进程在后台保存数据,主进程可以继续处理客户端请求,几乎无阻塞</li><li><strong>存储高效</strong>:RDB 文件使用二进制格式并支持LZF压缩</li></ul>
<p><code>缺点</code></p>
<ul><li><strong>非实时一致性</strong>:RDB保存的是某个瞬间的快照,如果保存过程中有大量写入,快照可能不反映完全一致的业务状态</li><li><strong>可能丢失更多数据</strong>:如果Redis意外宕机,从上一次RDB保存到宕机之间的所有数据修改都会丢失</li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>3.AOF</h2>
<p style="text-align:center">AOF持久化通过将Redis服务器接收到的每个写命令追加到文件末尾来实现<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480282.png" /></p>
<div class="jb51code"><pre class="brush:sql;"># 开启AOF
appendonly yes
</pre></div>
<p class="maodian"><a name="_lab2_2_4"></a></p><h3>3.1 工作流程</h3>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480315.png" /></p>
<ul><li><strong>命令追加</strong>:当Redis执行写命令时,该命令会以Redis协议格式追加到内存中的AOF缓冲区(aof_buf)。缓冲区会根据配置策略决定何时将内容同步到磁盘</li><li><strong>文件写入与同步</strong>:AOF缓冲区内容会被写入到AOF文件,具体同步到磁盘的时机由appendfsync参数控制:<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480392.png" /><ul><li>always:每次写命令后同步,数据安全性最高但性能影响较大</li><li>everysec:每秒同步一次,平衡性能与安全性(默认配置)</li><li>no:由操作系统决定同步时机,性能最好但可能丢失较多数据</li></ul></li></ul>
<p class="maodian"><a name="_lab2_2_5"></a></p><h3>3.2 重写机制</h3>
<blockquote><p><code>作用:</code>解决AOF文件不断增长导致的存储空间占用和恢复效率问题。通过重写,可以生成一个更紧凑的AOF文件,仅包含重建当前数据集所需的最小命令集合(例如,对同一个键多次修改会记录多条命令,而重写机制会合并这些操作,仅保留最终状态的命令)</p></blockquote>
<p style="text-align:center"> 父进程通过fork创建一个子进程来完成AOF文件的重写,确保主进程继续处理客户端请求。子进程会读取当前数据库的<strong>快照数据</strong>,并将其转换为一系列Redis命令写入新的临时AOF文件<br /><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480336.png" /><br /> 在重写过程中,主进程会将新接收到的写命令同时写入现有的AOF 缓冲区<code>aof_buf</code>(保证原有 AOF 文件正常更新)和AOF重写缓冲区<code>aof_rewrite_buf</code>(保证新命令不会丢失)</p>
<p> 当子进程完成重写后,会通知主进程。主进程会将 AOF 重写缓冲区中的命令追加到新生成的临时 AOF 文件中,最后原子性地替换旧文件</p>
<p style="text-align:center"> 在Redis7.0.15版本,AOF文件保存在<code>dir + appenddirname</code>配置指定的目录下(默认/var/lib/redis/appendonlydir)。文件前缀名通过<code>appendfilename</code>配置指定(默认appendonly)<br /><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480348.png" /></p>
<ul><li><strong>appendonly.aof.1.base.rdb</strong>:作为Redis AOF(Append-Only File)持久化机制的基准文件,存储某一时刻数据库的完整快照。格式为RDB,体积较小且加载速度快,用于重建数据的基础状态</li><li><strong>appendonly.aof.1.incr.aof</strong>和<strong>appendonly.aof.2.incr.aof</strong>:记录基准文件生成后的增量写操作命令,以文本形式追加存储。多个增量文件按操作顺序编号(如<code>.1.incr.aof</code>、<code>.2.incr.aof</code>),Redis 重启时会按顺序重放这些命令以恢复最新数据</li><li><strong>appendonly.aof.manifest</strong>:描述AOF文件的组成和顺序的清单文件<img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010209480380.png" /></li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>4.混合持久化</h2>
<p> Redis 混合持久化结合了 RDB(快照)和 AOF(日志)两种持久化方式的优势,在保证数据安全性的同时兼顾性能</p>
<div class="jb51code"><pre class="brush:sql;"># 开启混合持久化
aof-use-rdb-preamble yes
</pre></div>
<ul><li><strong>基础RDB文件优先加载</strong>:appendonly.aof.1.base.rdb作为全量快照数据文件,会优先被加载。该文件包含某一时间点的完整数据快照,恢复时作为基准数据集</li><li><strong>增量AOF文件后续应用</strong>:appendonly.aof.1.incr.aof作为增量操作日志,在基础RDB加载完成后被重放。该文件记录自 RDB 快照生成后的所有写操作,用于恢复最新数据状态</li></ul>
頁:
[1]