花婆婆 發表於 2025-11-14 09:13:05

Redis 底层运行机制与原理流程分析

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、核心架构:事件驱动与单线程模型</a></li><li><a href="#_label1">二、内存数据结构与动态编码</a></li><li><a href="#_label2">三、内存管理与碎片整理</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">1. 内存分配器</a></li><li><a href="#_lab2_2_1">2. 内存淘汰策略</a></li><li><a href="#_lab2_2_2">3. 主动碎片整理(Active Defrag)</a></li></ul><li><a href="#_label3">四、持久化机制:RDB 与 AOF</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_3">1. RDB(快照持久化)</a></li><li><a href="#_lab2_3_4">2. AOF(日志持久化)</a></li></ul><li><a href="#_label4">五、复制与集群架构</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_5">1. 主从复制流程</a></li><li><a href="#_lab2_4_6">2. 集群(Cluster)原理</a></li></ul><li><a href="#_label5">六、高级特性实现</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_7">1. Lua 脚本引擎</a></li><li><a href="#_lab2_5_8">2. I/O 多线程(Redis 6.0+)</a></li><li><a href="#_lab2_5_9">3. 模块系统</a></li></ul><li><a href="#_label6">总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、核心架构:事件驱动与单线程模型</h2>
<p>Redis 采用 <strong>单线程事件驱动架构</strong>,通过 epoll/kqueue 实现 I/O 多路复用。其核心事件循环(aeEventLoop)持续监听两类事件:</p>
<ol><li><strong>文件事件</strong>:Socket 可读/可写状态(客户端请求/响应)</li><li><strong>时间事件</strong>:定时任务(如过期键清理、持久化触发)</li></ol>
<p>工作流程:主线程通过 epoll_wait() 等系统调用获取就绪事件 &rarr; 调用对应处理器(如 readQueryFromClient 解析命令)&rarr; 执行命令 &rarr; 返回结果。这种设计避免了多线程锁竞争,但需确保单线程操作高效。</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、内存数据结构与动态编码</h2>
<p>Redis 通过 redisObject 结构统一管理数据,其字段包括:</p>
<ul><li><strong>type</strong>:数据类型(String/List 等)</li><li><strong>encoding</strong>:内部编码(如 ziplist/hashtable)</li><li><strong>lru</strong>:LRU 时间戳(内存淘汰用)</li><li><strong>refcount</strong>:引用计数(内存回收依据)</li><li><strong>ptr</strong>:指向实际数据的指针</li></ul>
<p><strong>动态编码优化策略:</strong></p>
<table><thead><tr><th>数据类型</th><th>编码方式</th><th>触发条件</th><th>性能特点</th></tr></thead><tbody><tr><td>String</td><td>int/embstr/raw</td><td>整数 &rarr; int;&le;44字节 &rarr; embstr;大对象 &rarr; raw</td><td>embstr 减少内存分配次数</td></tr><tr><td>List</td><td>quicklist</td><td>Redis 3.2+ 替代 ziplist/linkedlist,由 ziplist 节点+双向链表组成</td><td>平衡内存与操作效率</td></tr><tr><td>Hash</td><td>ziplist/hashtable</td><td>元素少且值小 &rarr; ziplist;超阈值 &rarr; hashtable</td><td>节省小对象内存</td></tr><tr><td>Set</td><td>intset/hashtable</td><td>全为整数 &rarr; intset;否则 &rarr; hashtable</td><td>整数集合压缩存储</td></tr><tr><td>ZSet</td><td>ziplist/skiplist</td><td>元素少且分数小 &rarr; ziplist;否则 &rarr; skiplist</td><td>跳表支持快速范围查询</td></tr><tr><td>Stream</td><td>radix tree + listpack</td><td>基数树索引消息 ID,listpack 存储消息内容</td><td>高效支持消息遍历</td></tr></tbody></table>
<p><strong>编码转换</strong>:当数据量超过阈值(如 ziplist 大小 &gt; hash-max-ziplist-entries)时自动切换编码。</p>
<p class="maodian"><a name="_label2"></a></p><h2>三、内存管理与碎片整理</h2>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>1. 内存分配器</h3>
<p>默认使用 <strong>jemalloc</strong>,其优势:</p>
<ul><li>按内存大小分级(small/large/huge)分配</li><li>减少外部碎片,碎片率通常 &asymp;1.03</li><li>支持后台线程异步释放内存(Lazy Free)</li></ul>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>2. 内存淘汰策略</h3>
<p>当达到 maxmemory 限制时触发:</p>
<ul><li><strong>LRU/LFU 近似算法</strong>:随机采样 5 个键(maxmemory-samples配置),淘汰最符合策略的键</li><li><strong>LFU 实现</strong>:用概率计数器记录访问频率,并随时间衰减</li></ul>
<p class="maodian"><a name="_lab2_2_2"></a></p><h3>3. 主动碎片整理(Active Defrag)</h3>
<ul><li><strong>触发</strong>:碎片率 &gt; active-defrag-threshold-lower(默认 10%)</li><li><strong>过程</strong>:扫描内存 &rarr; 复制碎片化对象到新位置 &rarr; 释放原内存</li><li><strong>限制</strong>:需配合 jemalloc,每周期 CPU 占用 &le; active-defrag-cycle-max(默认 25%)</li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>四、持久化机制:RDB 与 AOF</h2>
<p class="maodian"><a name="_lab2_3_3"></a></p><h3>1. RDB(快照持久化)</h3>
<ul><li><strong>流程</strong>:fork() 子进程 &rarr; 子进程遍历内存生成 RDB 文件 &rarr; 替换旧文件</li><li><strong>COW 优化</strong>:父进程继续处理请求,仅当内存页被修改时复制</li><li><strong>触发</strong>:save(阻塞)、bgsave(后台)、配置自动触发(如 save 900 1)</li></ul>
<p class="maodian"><a name="_lab2_3_4"></a></p><h3>2. AOF(日志持久化)</h3>
<ul><li><strong>流程</strong>:所有写命令追加到 AOF 缓冲区 &rarr; 根据策略(always/everysec/no)同步至磁盘</li><li><strong>重写</strong>:fork() 子进程生成精简版 AOF(只保留当前数据状态)</li><li><strong>混合持久化</strong>(Redis 4.0+):AOF 重写时嵌入 RDB 格式头,加速恢复</li></ul>
<p><strong>性能对比:</strong></p>
<table><thead><tr><th>特性</th><th>RDB</th><th>AOF</th></tr></thead><tbody><tr><td>文件大小</td><td>小(二进制)</td><td>大(文本命令)</td></tr><tr><td>恢复速度</td><td>快</td><td>慢</td></tr><tr><td>数据安全</td><td>可能丢失快照间数据</td><td>最多丢失 1 秒数据</td></tr></tbody></table>
<p class="maodian"><a name="_label4"></a></p><h2>五、复制与集群架构</h2>
<p class="maodian"><a name="_lab2_4_5"></a></p><h3>1. 主从复制流程</h3>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025111409113988.png" /></p>
<ul><li><strong>复制积压缓冲区</strong>:主节点维护环形缓冲区(默认 1MB),保存近期写命令</li><li><strong>无磁盘复制</strong>:RDB 数据直接流式传输到从节点,跳过磁盘 I/O(repl-diskless-sync yes)</li></ul>
<p class="maodian"><a name="_lab2_4_6"></a></p><h3>2. 集群(Cluster)原理</h3>
<ul><li><strong>分片机制</strong>:16384 个哈希槽均匀分布到节点</li><li><strong>Gossip 协议</strong>:节点间定期交换状态(PING/PONG/MEET/FAIL 消息)</li><li><strong>故障转移</strong>:当主节点下线,从节点发起投票选举新主节点</li></ul>
<p class="maodian"><a name="_label5"></a></p><h2>六、高级特性实现</h2>
<p class="maodian"><a name="_lab2_5_7"></a></p><h3>1. Lua 脚本引擎</h3>
<ul><li><strong>原子性</strong>:单线程执行脚本期间阻塞其他命令</li><li><strong>执行环境</strong>:伪客户端模式调用 Redis 命令</li><li><strong>复制</strong>:主节点传播 EVALSHA + 脚本 SHA1,从节点通过 repl_scriptcache_dict 缓存</li></ul>
<p class="maodian"><a name="_lab2_5_8"></a></p><h3>2. I/O 多线程(Redis 6.0+)</h3>
<ul><li><strong>线程分工</strong>:I/O 线程负责网络读写,主线程执行命令</li><li><strong>配置</strong>:io-threads 4 启用线程,io-threads-do-reads yes 启用读线程化</li><li><strong>效果</strong>:吞吐量提升 2 倍,但命令仍串行执行保证正确性</li></ul>
<p class="maodian"><a name="_lab2_5_9"></a></p><h3>3. 模块系统</h3>
<ul><li><strong>加载</strong>:MODULE LOAD /path/to/module.so</li><li><strong>API</strong>:RedisModule_CreateCommand 注册新命令</li><li><strong>交互</strong>:通过模块 API 访问核心数据结构(如 RedisModule_StringSet)</li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>总结</h2>
<p>Redis 的底层运行机制是一个精心设计的系统工程:</p>
<ul><li>以内存为核心,提供了极快的访问速度。</li><li>精巧的数据结构,在速度与内存之间取得了最佳平衡。</li><li>单线程 Reactor 模型,避免了并发复杂性,配合 I/O 多路复用轻松应对高并发。</li><li>灵活可配的持久化方案(RDB, AOF, 混合),满足了不同场景下的数据安全需求。</li><li>渐进式的优化策略(渐进式 rehash、惰性删除、后台线程化),保证了服务的平滑运行。</li></ul>
頁: [1]
查看完整版本: Redis 底层运行机制与原理流程分析