Redis 核心源碼解析:從設計哲學到企業級應用實踐

一、Redis 的核心設計哲學

Redis 的成功源于其?「用內存換時間」?的核心理念,圍繞以下三個核心原則構建:

  1. 極簡主義:單線程模型避免鎖競爭,代碼保持高度內聚。

  2. 性能至上:所有數據常駐內存,網絡層采用事件驅動模型。

  3. 可擴展性:模塊化設計,通過插件機制支持新功能。


二、源碼目錄結構解析

從 Redis 7.0 源碼看核心模塊:

redis/src
├── ae.c              # 事件循環(核心)
├── anet.c            # 網絡抽象層
├── dict.c            # 哈希表實現
├── object.c          # 數據類型封裝
├── rdb.c             # RDB持久化
├── aof.c             # AOF持久化
├── server.c          # 服務端主邏輯
├── networking.c      # 客戶端連接處理
└── modules           # 模塊化擴展

三、核心模塊源碼深度解析
1.?事件驅動模型:單線程為何能扛10萬QPS?

Redis 采用?Reactor 模式?實現高并發,核心代碼在?ae.c

// 事件循環主邏輯(ae.c)
void aeMain(aeEventLoop *eventLoop) {eventLoop->stop = 0;while (!eventLoop->stop) {aeProcessEvents(eventLoop, AE_ALL_EVENTS | AE_CALL_BEFORE_SLEEP);}
}// 處理事件(精簡版)
int aeProcessEvents(aeEventLoop *eventLoop, int flags) {// 1. 獲取最近要到期的時間事件shortest = aeSearchNearestTimer(eventLoop);// 2. 等待文件事件(epoll_wait/kevent等)numevents = aeApiPoll(eventLoop, tvp);// 3. 處理文件事件(網絡請求)for (j = 0; j < numevents; j++) {fe = &eventLoop->events[eventLoop->fired[j].fd];fe->rfileProc(...); // 處理讀事件fe->wfileProc(...); // 處理寫事件}// 4. 處理時間事件(如過期鍵清理)processed += processTimeEvents(eventLoop);
}

技術要點

  • 基于?epoll/kqueue?實現多路復用

  • 單線程順序處理事件,避免鎖開銷

  • 時間事件與文件事件協同調度


2.?內存管理:如何實現高效數據存儲?

核心結構?redisObject(object.c):

typedef struct redisObject {unsigned type:4;        // 數據類型(string/hash等)unsigned encoding:4;    // 編碼方式(優化存儲)unsigned lru:24;        // LRU時間戳int refcount;           // 引用計數void *ptr;              // 數據指針
} robj;// 字符串類型示例(sds.h)
struct sdshdr {int len;        // 已用長度int free;       // 剩余空間char buf[];     // 柔性數組
};

編碼優化策略

  • String:int編碼(存儲整數時) vs embstr編碼(短字符串) vs raw編碼

  • Hash:ziplist(元素少時) vs hashtable

  • Sorted Set:skiplist + dict 實現 O(logN) 查詢


3.?持久化機制:RDB與AOF如何協同工作?

RDB 快照生成(rdb.c)

// 異步生成RDB(fork子進程)
int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) {if ((childpid = fork()) == 0) {// 子進程執行實際保存retval = rdbSave(filename,rsi);exitFromChild((retval == C_OK) ? 0 : 1);} else {// 父進程記錄狀態server.rdb_child_pid = childpid;}
}

AOF 重寫(aof.c)

// 重寫AOF文件(同樣fork子進程)
int rewriteAppendOnlyFileBackground(void) {if (aofCreatePipes() != C_OK) return C_ERR;if ((childpid = fork()) == 0) {// 子進程重寫if (rewriteAppendOnlyFile(tmpfile) == C_OK) {exitFromChild(0);}}
}

持久化流程對比

RDBAOF
原理內存快照操作日志追加
優點恢復快、文件小數據丟失風險低
缺點數據可能丟失文件大、恢復慢

4.?數據結構:Sorted Set 如何實現高效排序?

核心代碼?t_zset.c

// 跳躍表節點定義
typedef struct zskiplistNode {sds ele;                            // 成員double score;                       // 分數struct zskiplistNode *backward;     // 后退指針struct zskiplistLevel {struct zskiplistNode *forward;  // 前進指針unsigned long span;             // 跨度} level[];                          // 層級數組
} zskiplistNode;// 插入節點核心邏輯
zskiplistNode *zslInsert(zskiplist *zsl, double score, sds ele) {// 1. 隨機生成節點層級(冪次定律)level = zslRandomLevel();// 2. 查找插入位置for (i = zsl->level-1; i >= 0; i--) {while (x->level[i].forward && (x->level[i].forward->score < score || ... )) {x = x->level[i].forward;}update[i] = x;}// 3. 創建新節點并調整指針x = zslCreateNode(level,score,ele);for (i = 0; i < level; i++) {x->level[i].forward = update[i]->level[i].forward;update[i]->level[i].forward = x;}
}

性能優勢

  • 跳躍表平均 O(logN) 時間復雜度

  • 結合哈希表實現 O(1) 成員存在性檢查


四、企業級應用源碼適配案例
案例1:分布式鎖實現(Redlock算法)
// 加鎖命令(基于SET命令)
SET lock_key $unique_id NX PX 30000// 解鎖Lua腳本(保證原子性)
if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end

源碼支撐

  • SET?命令在?t_string.c?實現

  • Lua 腳本執行邏輯在?scripting.c


案例2:熱點數據緩存穿透防御
// 布隆過濾器實現(redisbloom模塊)
BF.ADD hot_items:filter "item_123"
BF.EXISTS hot_items:filter "item_456"

源碼擴展

  • 模塊化開發接口在?redismodule.h

  • 底層使用?dablooms?庫實現


五、Redis 核心架構圖
+-------------------+
|      Client       |
+-------------------+|| 發送命令v
+-------------------+
|    Event Loop     | <--- 文件事件(網絡I/O)
| (ae.c/ae_epoll.c) | 
|                   | <--- 時間事件(過期鍵清理)
+-------------------+|| 命令路由v
+-------------------+
|   Command Table   | ---> 命令處理器(get/set等)
|  (server.c/cmd)   |
+-------------------+|| 數據操作v
+-------------------+
|    Data Store     | ---> 字符串/hash/有序集合等
| (object.c/t_*.c)  |
+-------------------+|| 持久化觸發v
+-------------------+
|  Persistence      | ---> RDB(rdb.c) / AOF(aof.c)
+-------------------+

六、Redis 的局限與優化方向
  1. 內存限制:可通過 Redis Cluster 分片擴展

  2. 單線程瓶頸:Redis 6.0 引入多線程I/O(仍保持命令處理單線程)

  3. 持久化風險:建議 RDB+AOF 混合使用,定期備份

  4. 擴展性:通過 Module 機制集成新功能(如 RedisSearch)


七、總結

通過源碼分析可深入理解 Redis 的?高性能設計精髓

  1. 事件驅動模型:單線程扛高并發

  2. 內存數據結構:精心優化的編碼方式

  3. 可擴展架構:模塊化設計支持二次開發

企業級應用建議:

  • 性能敏感場景:結合跳躍表、哈希表特性設計數據結構

  • 高可用要求:部署 Redis Cluster + Sentinel 監控

  • 混合持久化:RDB 定期快照 + AOF 實時日志

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74406.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74406.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74406.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

GZCTF平臺搭建及題目上傳

前言 我用手里的Ubuntu虛擬機搭建的&#xff0c;大家根據自己的實際情況來吧 安裝及部署 首先&#xff0c;你的虛擬機需要有Docker和Docker-Compose&#xff0c;前者可以看我之前的文章&#xff0c;另外一個可以輸入下面的命令安裝&#xff0c;注意先獲取管理員權限&#xff…

Pycharm社區版創建Flask項目詳解

一、創建工程項目 二、配置工程目錄 新建的空項目下創建目錄。 1、新建app.py文件 2、app.py代碼如下&#xff1a; from flask import Flask, render_templateapp Flask(__name__)app.route("/") def root():"""主頁:return: Index.html"&qu…

CentOS 7 64位安裝Docker

以下是在已有的 CentOS 7 64 位虛擬機上安裝 Docker 并配置華為鏡像源的詳細步驟&#xff1a; 1. 備份原有 Yum 源&#xff08;可選&#xff0c;建議操作&#xff09; # 備份原有倉庫文件 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backu…

運動仿真——phased.Platform

在雷達仿真過程中&#xff0c;運動仿真的必要性&#xff0c;以及運動仿真可以實現哪些功能&#xff0c;在matlab對應的user guide中已經講的很清楚了&#xff0c;這里不再贅述。 本文主要介紹phased.Platform的一些“坑”&#xff0c;和典型的用法。 第一坑&#xff1a;系統對…

緩存刪除三級補償方案:延遲隊列+消息隊列+定時任務兜底

問題背景: 在 Cache-Aside 模式中&#xff0c;更新數據庫后刪除緩存失敗會導致數據不一致。本文提供工業級三級補償方案&#xff0c;實現最終一致性保障。 整體架構: 更新操作觸發 → 一級延遲隊列 → 二級消息隊列 → 三級定時任務方案實現: 一、第一級補償&#xff1a;延遲隊…

從零開始實現 C++ TinyWebServer 數據庫連接池 SqlConnectPool詳解

文章目錄 數據庫連接池是什么&#xff1f;Web Server 中為什么需要數據庫連接池&#xff1f;SqlConnectPool 成員變量實現 Init() 函數實現 ClosePool() 函數SqlConnectRAII 類SqlConnectPool 代碼SqlConnectPool 測試 從零開始實現 C TinyWebServer 項目總覽 項目源碼 數據庫連…

C++題目

1、內存管理 1.內存模型 棧:在執行函數時&#xff0c;函數內局部變量的存儲單元都可以在棧上創建&#xff0c;函數執行結束時這些存儲單元自動被釋放。 堆&#xff1a;就是那些由new分配的內存塊&#xff0c;其釋放由程序員控制&#xff08;一個new對應一個delete&#xff09…

天地圖InfoWindow插入React自定義組件

截至2025年03月21日天地圖的Marker不支持添加Label; 同時Label和Icon是不支持自定義HTMLElement只支持String&#xff1b;目前只有InfoWindow支持自定義HTMLElement; 效果圖 React核心api import ReactDOM from react-dom/client const content document.createElement(div);…

Java并發編程面試匯總

Java并發編程 一、 基礎概念1. 進程與線程的區別是什么&#xff1f;2. 創建線程的幾種方式&#xff1f;3. 線程的生命周期&#xff08;狀態&#xff09;有哪些&#xff1f;4. 什么是守護線程&#xff08;Daemon Thread&#xff09;&#xff1f;5. 線程優先級&#xff08;Priori…

【STM32】第一個工程的創建

目錄 1、獲取 KEIL5 安裝包2、開始安裝 KEIL52.1、 激活2.2、安裝DFP庫 3、工程創建4、搭建框架5、開始編寫代碼 1、獲取 KEIL5 安裝包 要想獲得 KEIL5 的安裝包&#xff0c;在百度里面搜索“KEIL5 下載”即可找到很多網友提供的下載文件&#xff0c;或者到 KEIL 的官網下載&a…

動態規劃~01背包問題

01背包問題 經典的0 - 1背包問題的解決方案。 二維數組的版本 代碼功能概述 0 - 1背包問題指的是有 n 個物品和一個容量為 m 的背包&#xff0c;每個物品有對應的體積 v[i] 和價值 w[i]&#xff0c;需要從這些物品里挑選若干個放入背包&#xff0c;讓背包內物品的總價值達到最…

深入理解Java享元模式及其線程安全實踐

引言 在軟件系統中&#xff0c;當需要處理海量細粒度對象時&#xff0c;直接創建大量實例可能會導致內存消耗激增和性能下降。享元模式&#xff08;Flyweight Pattern&#xff09;通過共享對象內部狀態&#xff0c;成為解決這類問題的經典方案。然而在多線程環境下&#xff0c…

1、mysql基礎篇--概述

關系型數據庫&#xff08;RDBMS&#xff09; 概念特點&#xff1a;數據模型&#xff1a; 概念 建立在關系模型基礎上&#xff0c;有多張表相互連接的二維表組成的數據庫 特點&#xff1a; 1、使用表存儲&#xff0c;格式統一&#xff0c;便于維護 2、使用sql語言操作&#…

如何提升庫存系統的高并發和穩定性:算法與設計模式

庫存系統是企業運營的核心模塊&#xff0c;尤其是在電商、零售和供應鏈管理中&#xff0c;系統的高并發和穩定性直接影響訂單處理的準確性和效率。面對海量訂單、復雜的庫存管理需求&#xff0c;如何在高并發環境下確保庫存數據的準確性和系統的穩定性&#xff1f;本文將從架構…

【多線程】synchronized底層實現的方式

前言 在java 開發中對于鎖的應用非常的常見&#xff0c;如果對于什么時候該用什么鎖&#xff0c;以及鎖實現的原理有所不知道的&#xff0c;或者面試過程中面試官問你不知道怎么回答的&#xff0c;歡迎來看下面的文章 1、synchronized和ReentrantLock的區別 2、synchronized的…

Pytorch中Tensorboard的學習

1、Tensorboard介紹 TensorBoard 是 TensorFlow 開發的一個可視化工具&#xff0c;用于幫助用戶理解和調試機器學習模型的訓練過程。盡管它最初是為 TensorFlow 設計的&#xff0c;但通過 PyTorch 的 torch.utils.tensorboard 模塊&#xff0c;PyTorch 用戶也可以方便地使用 Te…

ETL 自動化:提升數據處理效率與準確性的核心驅動力

在數字化轉型的浪潮中&#xff0c;數據已成為企業戰略資產&#xff0c;高效處理數據的能力直接關系到企業的競爭力。ETL&#xff08;Extract, Transform, Load&#xff09;自動化作為數據處理領域的關鍵技術&#xff0c;正逐漸成為企業在數據時代脫穎而出、實現高效運營與精準決…

std::endl為什么C++ 智能提示是函數?

在使用vscode 的C智能提示后&#xff0c;輸入endl 后&#xff0c;提示的卻是std::endl(basic_ostream<CharT, Traits> &os), 感覺比較奇怪&#xff0c;各種代碼里都是直接用的std::endl 啊&#xff0c; 這里怎么變成函數了呢&#xff1f; 在 C 中&#xff0c;std::en…

簡潔、實用、無插件和更安全為特點的WordPress主題

簡站WordPress主題是一款以簡潔、實用、無插件和更安全為特點的WordPress主題&#xff0c;自2013年創立以來&#xff0c;憑借其設計理念和功能優勢&#xff0c;深受用戶喜愛。以下是對簡站WordPress主題的詳細介紹&#xff1a; 1. 設計理念 簡站WordPress主題的核心理念是“崇…

數據結構篇:空間復雜度和時間復雜度

目錄 1.前言&#xff1a; 1.1 學習感悟 1.2 數據結構的學習之路(初階) 2.什么是數據結構和算法 2.1 數據結構和算法的關系 2.2 算法的重要性 2.3 如何衡量算法的好壞 3.時間復雜度 3.1 時間復雜度的概念 3.2 大O的漸進表示法 O() 4.空間復雜度 5. 常見的時間復雜度和…