從單線程到云原生:Redis 二十年演進全景與內在機理深剖

——從 1.0 到 7.2,一窺數據結構、網絡模型、持久化、復制、高可用與生態協同的底層脈絡

(一)序章:為什么是 Redis
1999 年,Salvatore Sanfilippo 在開發一個實時訪客分析系統時,發現傳統磁盤型數據庫無法在毫秒級響應 100 萬并發連接。于是,他寫了一個將全量數據放在內存、用 C 語言實現、單線程處理命令、支持簡單文本協議的服務——這就是 Redis 的原型。二十年后,Redis 已不僅僅是“緩存”的代名詞,而是橫跨緩存、消息總線、流處理、機器學習特征存儲、實時排行榜、地理位置服務等眾多場景的“瑞士軍刀”。

本文不貼源碼,也不給調參清單,而是回到設計哲學:為什么 Redis 選擇單線程?為什么后來又要引入多線程 I/O?為什么跳表而不是 B+ 樹?AOF 與 RDB 能否合二為一?主從復制與哨兵、集群、Raft 之間的演進邏輯是什么?帶著這些問題,我們穿越版本號,拆解 Redis 的骨骼與血脈。

(二)數據結構:不止是 key-value
2.1 字符串(SDS)
Redis 沒有復用 C 字符串,而是自建簡單動態字符串 SDS。預分配、惰性釋放、二進制安全、O(1) 長度獲取,這些看似微小的優化,奠定了所有復合類型的基石。

2.2 字典
哈希表 + 漸進式 rehash。負載因子 1 時開始擴容,0.1 時縮容;rehash 期間采用“分槽遷移”策略,避免一次性拷貝導致延遲抖動。

2.3 跳表
實現有序集合 ZSET 的核心。多層索引、概率平衡、范圍查詢 O(logN)。跳表比 B+ 樹省內存,且實現簡單,但范圍查詢的 CPU cache 局部性稍遜。Redis 在 7.0 引入 listpack + 跳表混合編碼,將元素 < 64 字節且個數 < 128 的小 ZSET 壓縮為連續內存塊,從而減少 30% 內存。

2.4 壓縮列表 → quicklist → listpack
早期 list 用 ziplist 保存,連鎖更新問題嚴重;3.2 引入 quicklist(雙向鏈表 + ziplist 節點);5.0 以后用 listpack 取代 ziplist,徹底消除連鎖更新。

2.5 HyperLogLog、Bitmap、Geo、BloomFilter、TDigest、CuckooFilter
這些模塊化數據結構展示了 Redis “數據結構服務器”的定位:把學術界算法工程化,暴露成幾條命令即可落地業務。

(三)網絡模型:單線程、I/O 多路復用、最近的多線程
3.1 單線程事件循環
Reactor 模式 + epoll/kqueue。命令執行階段在單線程完成,天然避免鎖。瓶頸不在 CPU,而在系統調用和內存帶寬。

3.2 連接風暴與 I/O 多線程
6.0 引入 I/O 多線程:主線程仍負責命令執行,網絡 read/write 可由線程池并行化。通過“無鎖隊列 + 原子操作”傳遞 client 對象,避免上下文切換開銷。實測在 128 并發連接、value 1 KB 場景下,QPS 從 12 萬提升到 45 萬。

3.3 TLS、Unix Socket、RESP3
TLS 握手開銷大,Redis 通過“延遲啟動 TLS”優化:先接受普通連接,AUTH 成功后再升級。RESP3 引入屬性、推送、大數類型,為客戶端提供類型安全與流式通知。

(四)持久化:RDB、AOF 與混合范式
4.1 RDB 快照
fork + copy-on-write。父進程繼續服務,子進程遍歷哈希表寫磁盤。大實例 fork 延遲可達百毫秒,Redis 7 引入 “lazy free” 后臺線程異步釋放頁表,減少 80% 阻塞時間。

4.2 AOF 日志
4.0 以前 AOF 是命令重放;4.0 支持 RDB-AOF 混合:前半段是 RDB,后半段是增量命令。重寫時用 “copy-on-write + pipe” 邊生成邊傳輸,避免雙倍內存。

4.3 fsync 策略
always、everysec、no。云盤場景下 everysec 也可能阻塞毫秒級,Redis 6.2 支持 “aof-fsync-in-thread” 將 fsync 移到后臺線程。

4.4 重啟恢復流程
先加載 RDB 構建基線,再重放 AOF 增量。Redis 7.2 引入 “AOF manifest” 記錄多個 AOF 文件順序,實現并行加載,提速 40%。

(五)主從復制:全量、部分、PSYNC2
5.1 SYNC 與 PSYNC
2.8 以前全量復制;PSYNC 引入 backlog 環形緩沖區,支持斷線續傳。backlog 大小 = 平均寫速率 * 容忍宕機時間。

5.2 PSYNC2
4.0 解決級聯復制場景下 “主從切換后新主仍能與舊主部分重同步” 的問題。通過 replid + offset 雙標識,實現“多主歷史”追蹤。

5.3 無盤復制
5.0 支持 “diskless replication”,子進程直接把 RDB 通過 socket 流式發送到 replica,省去磁盤臨時文件。

(六)高可用:哨兵、集群、Raft、聯邦
6.1 Sentinel
哨兵本質是分布式仲裁系統:監控、通知、自動故障轉移、配置提供者。raft-style leader 選舉,但不需要持久化日志。

6.2 Cluster
16384 槽位、CRC16 算法映射、客戶端重定向、ASK/MOVED 語義。節點間采用 Gossip + 心跳 + 故障報告機制。擴容/縮容通過 “槽遷移” 實現:遷移過程中 key 臨時存在于源、目標兩節點,客戶端通過 ASKING 命令解決雙重應答。

6.3 RedisRaft
Redis 官方實驗項目,將 Raft 日志嵌入 Redis 內部命令流,實現強一致。犧牲性能換 CP,適用于金融場景。

6.4 聯邦模式
在云廠商實踐中,常見“代理層分片”:twemproxy、codis、predixy。優勢是對客戶端零侵入;劣勢是代理層成為瓶頸,且無法支持多 key 原子事務。

(七)內存管理:jemalloc、內存碎片、逐出策略
7.1 jemalloc vs tcmalloc
jemalloc 的 arena 機制減少多線程競爭,但 4.x 版本存在 huge page 浪費;Redis 6 引入 “activedefrag” 后臺線程,周期性搬遷對象,降低碎片率。

7.2 逐出算法
LRU、LFU、TTL、random。LFU 用 Morris counter 近似 8 位計數器,支持衰減因子。

7.3 內存壓縮
listpack、hash-ziplist、set-intset、HyperLogLog-dense/sparse 編碼,根據元素特征自適應切換。

(八)事務與腳本:從 MULTI/EXEC 到 Lua 再到 Functions
8.1 MULTI/EXEC 與 WATCH
樂觀鎖機制,WATCH 監控 key 版本號,EXEC 時若版本變化則回滾。

8.2 Lua
5.1 解釋器嵌入,腳本以原子方式執行。EVALSHA 緩存字節碼,減少帶寬。

8.3 Functions
Redis 7 推出 “Functions”:腳本持久化到 AOF/RDB,重啟可恢復;支持集群模式自動廣播。解決 Lua 腳本在集群擴容后丟失的問題。

(九)發布訂閱與 Stream:消息總線的兩種范式
9.1 Pub/Sub
無持久化、無 ACK、無回溯,純推模式。適用于高吞吐低可靠場景,例如彈幕、實時股價推送。

9.2 Stream
Kafka-like 日志抽象:消息 ID(毫秒時間戳+序號)、消費組、pending list、ack、claim。支持按 ID 重放,實現 CQRS 與事件溯源。

(十)模塊系統:從 RedisModule 到 RedisML
模塊 API 允許在子線程注冊新命令、新數據結構、新事件。RedisTimeSeries、RedisSearch、RedisJSON、RedisBloom、RedisAI 等模塊讓 Redis 變身時序數據庫、搜索引擎、向量數據庫。

(十一)云原生與可觀測性
11.1 Kubernetes Operator
通過 CRD 定義 RedisCluster、RedisFailover,利用 sidecar 實現自動故障轉移、滾動升級、密碼輪換。

11.2 監控指標
? 內存:used_memory、mem_fragmentation_ratio
? 延遲:latency_percentiles_usec、slowlog
? 復制:master_repl_offset、master_link_down_time_seconds
? 集群:cluster_state、cluster_slots_fail

11.3 追蹤
Redis 7 支持 “keyspace hits/misses” 細粒度指標,結合 eBPF 可定位 hotkey。

(十二)尾聲:下一跳
Redis 8 Roadmap:
? Threaded Lua:腳本跑在獨立線程池,避免長腳本阻塞主循環。
? Diskless Cluster:Gossip 消息也走 RDMA,實現全內存復制。
? SQL-like 查詢:基于 RediSQL 模塊,支持類關系型語法。
? Tiered Storage:SSD 作為二級緩存,LRU 算法跨 DRAM/SSD 兩層。

Redis 的演進史,是一部在 “性能、功能、一致性” 三角張力中反復權衡的歷史。每一次看似激進的重構,背后都有業務場景的真實痛苦。理解這些權衡,遠比背參數、背命令更有生命力。

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

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

相關文章

得了甲亢軍隊文職體檢能過嗎

根據軍隊文職體檢現行標準&#xff0c;甲亢患者能否通過體檢需分情況判定&#xff0c;核心取決于病情控制狀態、治療結果及穩定時長。結合《軍隊選拔軍官和文職人員體檢通用標準》及補充規定&#xff0c;具體分析如下&#xff1a;?? 一、可直接通過體檢的情況臨床治愈滿1年且…

【編程語言】C、C++、C#深度對比:三種語言的演進歷程與應用場景

一、語言概述與歷史背景 &#xff08;一&#xff09;C語言&#xff1a;系統編程的基石誕生背景 1972年由Dennis Ritchie在貝爾實驗室開發為了重寫UNIX操作系統而創造從B語言演化而來&#xff0c;增加了數據類型設計目標&#xff1a;簡潔、高效、可移植設計哲學 “相信程序員”&…

《計算機網絡》實驗報告五 DNS協議分析與測量

目 錄 1、實驗目的 2、實驗環境 3、實驗內容 3.1 查看和配置本機的DNS系統 3.2 DNS信息測量 3.3 DNS協議分析 4、實驗結果與分析 4.1 查看和配置本機的DNS系統 4.2 DNS信息測量 4.3 DNS協議分析 5、實驗小結 5.1 問題與解決辦法&#xff1a; 5.2 心得體會&#x…

Python工廠方法模式詳解:從理論到實戰

一、工廠方法模式核心概念 工廠方法模式&#xff08;Factory Method Pattern&#xff09;是一種創建型設計模式&#xff0c;屬于經典23種設計模式之一。其核心思想是&#xff1a;定義一個創建對象的接口&#xff0c;但將具體對象的實例化過程延遲到子類中實現。這種模式通過引入…

python爬蟲獲取PDF

【前提&#xff1a;菜鳥學習的記錄過程&#xff0c;如果有不足之處&#xff0c;還請各位大佬大神們指教&#xff08;感謝&#xff09;】 1.方法一&#xff1a;網站找到目標數據【單篇PDF】 https://bidding.sinopec.com/tpfront/xxgg/004005/ 按F12&#xff0c;----檢查------…

IFN影視官網入口 - 4K影視在線看網站|網頁|打不開|下載

IFN影視是一個專注于影視內容的網站&#xff0c;提供電影、電視劇、綜藝等各類影視資源的在線觀看服務。該網站以用戶需求為導向&#xff0c;致力于為用戶提供高清、流暢的觀影體驗&#xff0c;并不斷更新內容以滿足不同用戶的觀看習慣和偏好。IFN影視的特色在于其內容豐富、分…

《計算機網絡》實驗報告四 TCP協議分析

目 錄 1、實驗目的 2、實驗環境 3、實驗內容 3.1 利用wget下載新疆大學主頁 3.2 使用wireshark分析TCP報文結構 3.3 使用wireshark分析建立連接的三次握手 3.4 使用wireshark分析釋放連接的四次揮手 4、實驗結果與分析 4.1 利用wget下載新疆大學主頁 4.2 使用wiresh…

知識 IP 的突圍:從 “靠感覺” 到 “系統 + AI” 的變現躍遷

越來越多的知識付費從業者陷入 “努力無成果” 的困局&#xff1a;做了內容、上了課程&#xff0c;卻沒人看、沒人買。核心問題不在于能力不足&#xff0c;而在于仍在用 “靠感覺” 的原始方式打造 IP。在流量內卷、節奏加快的當下&#xff0c;“內容情懷” 已撐不起一門生意&a…

4.Java創建對象有幾種方式?

1.使用 new 關鍵字&#xff08;最常用&#xff09;通過調用類的構造函數直接實例化對象Person person new Person(); // 調用無參構造 Person person new Person("Alice", 25); // 調用有參構造2.反射機制&#xff08;動態創建&#xff09;利用Java反射 API 在運行…

【好題】洛谷 P1600 [NOIP 2016 提高組] 天天愛跑步(倍增LCA+桶)

前言沒做出來&#xff0c;看了很多篇題解后AC了&#xff0c;感覺大部分題解講得不清楚。題目思路結果有兩種求法模擬跑步過程&#xff0c;統計每個節點能觀察到的人數考慮每條路徑會對哪些節點作出貢獻&#xff08;當前路徑的玩家能被觀察到&#xff09;嘗試第一種求法必須遍歷…

valkey之網絡管理架構深度解析

一、連接類型實現體系 valkey通過ConnectionType結構體構建了靈活的網絡連接抽象&#xff0c;支持多種連接類型的統一管理。每種連接類型都通過填充該結構體的函數指針來實現特定功能&#xff0c;形成了面向接口的設計模式。1.1 socket連接 Socket連接提供了最基礎的TCP/IP通信…

【解碼文本世界的“隱形分界線”:Windows與Linux回車換行之謎】

在計算機的文本世界里&#xff0c;回車&#xff08;Carriage Return&#xff0c;CR&#xff09;和換行&#xff08;Line Feed&#xff0c;LF&#xff09;是兩個看似簡單卻意義非凡的字符。它們如同文本中的“隱形分界線”&#xff0c;默默地劃分著段落與行&#xff0c;影響著文…

【Project】ELK 7.17.16 日志分析系統部署

ELK 日志分析系統集群部署 本文檔基于 Rocky Linux 9.4 系統&#xff0c;部署 ELK 7.17.16&#xff08;長期支持版&#xff09;集群 案例準備 1. 節點規劃IP主機名部署組件角色說明192.168.100.150kafka01Elasticsearch、Kibana主節點&#xff08;master&#xff09; 可視化192…

分布式定時任務系列13:死循環是任務觸發的銀彈?

傳送門 分布式定時任務系列1&#xff1a;XXL-job安裝 分布式定時任務系列2&#xff1a;XXL-job使用 分布式定時任務系列3&#xff1a;任務執行引擎設計 分布式定時任務系列4&#xff1a;任務執行引擎設計續 分布式定時任務系列5&#xff1a;XXL-job中blockingQueue的應用 …

Flutter基礎(前端教程①③-單例)

現實類比&#xff1a;公司打印機假設你們公司有一臺共享打印機&#xff1a;非單例&#xff08;重復創建&#xff09;&#xff1a;每個員工都自己買一臺打印機放在工位上結果&#xff1a;浪費錢&#xff0c;占空間&#xff0c;難維護單例&#xff08;唯一實例&#xff09;&#…

力扣刷題 -- 965.單值二叉樹

題目示例&#xff1a; 思路分析代碼實現 bool isUnivalTree(struct TreeNode* root) {if(rootNULL){return true;}if(root->left && root->val ! root->left->val){return false;}if(root->right && root->val ! root->right->val){re…

uni-api交互反饋組件(showToast)的用法

歡迎來到我的UniApp技術專欄&#xff01;&#x1f389; 在這里&#xff0c;我將與大家分享關于UniApp開發的實用技巧、最佳實踐和項目經驗。 專欄特色&#xff1a; &#x1f4f1; 跨平臺開發一站式解決方案 &#x1f680; 從入門到精通的完整學習路徑 &#x1f4a1; 實戰項目經…

借助它,在Web3投資賽道搶占先機

隨著互聯網技術的飛速發展&#xff0c;Web3的概念逐漸成為科技圈和投資界的熱門話題。Web3代表著下一代互聯網的發展方向&#xff0c;它強調去中心化、用戶主權和數據隱私保護。在這一新興領域&#xff0c;如何借助Web3技術搶占投資先機&#xff0c;成為許多投資者關注的焦點。…

驗證大語言模型不會算數但可以編寫算數的程序

摘要&#xff1a;本文通過幾個實例測試了大語言模型在數學計算、排序、統計等方面的能力。結果顯示&#xff0c;對于簡單字符統計、排序等任務&#xff0c;大模型能正確生成實現代碼&#xff0c;但當數據區分度降低時容易出錯。在計算學生分數排名任務中&#xff0c;大模型生成…

概率論與數理統計(八)

參數估計 通過取樣本&#xff0c;并用樣本構造函數&#xff0c;達成估計分布函數參數的目的 矩估計法 本質&#xff1a;用樣本的各階矩代替總體的各階矩&#xff0c;即取&#xff1a; E(X)X ̄1n∑iXiE(X2)1n∑iXi2E(X)\overline{X}\dfrac{1}{n}\sum_i X_i\\ E(X^2)\dfrac{1}…