Redis設計與實現——數據結構與對象

簡單動態字符串(SDS)

SDS 的結構定義
  • len:記錄當前字符串的實際長度(不包含 \0),獲取長度的時間復雜度為 O(1)
  • free:記錄未使用的空間大小,用于優化內存分配。
  • buf[]:實際存儲字符的數組,末尾自動追加 \0(兼容 C 字符串函數)。
SDS 的核心特性
  • 預分配與惰性釋放

    • 空間預分配:當 SDS 需要擴容時,Redis 會額外分配未使用空間(free)以減少內存重分配次數:

      若擴容后 len < 1MB:分配 len 的等量空間(總空間 = len + free + 1 = 2 * len + 1)。

      若擴容后 len ≥ 1MB:固定分配 1MB 未使用空間(總空間 = len + 1MB + 1)。

    • 惰性空間釋放:當 SDS 縮短時,不立即回收內存,而是通過 free 記錄剩余空間,供后續操作復用。

  • 二進制安全:SDS 的 buf 可以存儲任意二進制數據(包括 \0),因為長度由 len 字段記錄,而非依賴 \0 判斷結束。

  • 兼容 C 字符串函數:SDS 的 buf 末尾自動追加 \0,可直接使用 <string.h> 中的函數(如 strcmp())。

  • 杜絕緩沖區溢出:所有修改操作(如拼接)前會檢查剩余空間(free),不足時自動擴容。

鏈表

鏈表的定義與結構
  • 鏈表結點
    • 雙向鏈接:每個節點包含指向前驅和后繼的指針,支持雙向遍歷。
    • 值類型靈活value 字段為 void* 類型,可指向任意數據(字符串、整數、對象等)。
  • 鏈表對象(list
    • 頭尾指針:直接訪問頭尾節點,使 LPUSHRPUSH 等操作時間復雜度為 O(1)
    • 長度字段len 直接記錄節點數量,無需遍歷即可獲取長度(時間復雜度 O(1))。
    • 多態性支持:通過函數指針實現值的復制、釋放和比較,支持不同類型數據的存儲。
鏈表的特性
  • 雙向無環鏈表

    • 雙向:每個節點包含前驅和后繼指針,支持雙向遍歷。

    • 無環:頭節點的 prev 和尾節點的 next 均為 NULL,避免循環引用。

  • 高效的頭尾操作

    • 頭部插入/刪除:直接通過 list->head 操作,時間復雜度 O(1)。

    • 尾部插入/刪除:直接通過 list->tail 操作,時間復雜度 O(1)。

  • 多態性與類型安全

    • 存儲任意數據:節點值通過 void* 指針存儲,支持字符串、整數、對象等。

    • 自定義函數:通過 dupfreematch 函數實現類型相關的操作,例如:

      dup:深拷貝節點值(如復制一個 SDS 字符串)。

      free:釋放節點值占用的內存(如銷毀一個 Redis 對象)。

      match:比較節點值與給定值是否相等。

字典

字典的結構定義
  • 哈希表(dictht

    • size:哈希表的大小,初始為 4,每次擴容為當前大小的 2 倍。
    • sizemask:哈希掩碼,用于計算鍵的索引(hash & sizemask)。
    • table:指向哈希桶數組的指針,每個桶是一個鏈表(鏈地址法)。
  • 哈希節點(dictEntry

    • key:指向鍵的指針(如 SDS 字符串)。
    • v:值的聯合體,支持指針、整數、浮點數等類型。
    • next:指向沖突鏈中的下一個節點。
  • 字典對象(dict

    • ht[2]:兩個哈希表,正常操作使用 ht[0],Rehash 時逐步遷移到 ht[1]
    • rehashidx:記錄 Rehash 的進度(從 0 到 ht[0].size-1)。
    • type:指向 dictType 結構的指針,包含鍵和值的操作函數(如哈希函數、鍵比較函數)。
核心機制與算法
  • 哈希函數:Redis 默認使用 MurmurHash2 算法計算鍵的哈希值。

  • 鍵沖突解決

    • 鏈地址法:哈希沖突的節點通過鏈表連接,新節點插入鏈表的頭部(時間復雜度 O(1))。

    • 負載因子load_factor = ht[0].used / ht[0].size,觸發擴容的默認閾值是 load_factor ≥ 1(可配置)。

  • 漸進式 Rehash:當哈希表需要擴容或縮容時,Redis 通過漸進式 Rehash 避免一次性遷移所有數據導致的阻塞:

    • 準備階段:為 ht[1] 分配新空間;設置 rehashidx = 0,表示 Rehash 開始。

    • 遷移階段:Redis 遷移 ht[0].table[rehashidx] 的所有節點到 ht[1]rehashidx 遞增,直到所有桶遷移完成。

    • 完成階段:釋放 ht[0],將 ht[1] 設置為 ht[0];重置 ht[1] 為空表,rehashidx = -1

跳躍表Skiplist

跳躍表的定義與結構
  • 跳躍表節點(zskiplistNode

    • ele:存儲元素的唯一標識(如用戶 ID),類型為 SDS 字符串。
    • score:排序分值(如用戶的積分),支持浮點數。
    • backward:指向前驅節點,用于從尾到頭遍歷。
    • level[]forward——指向后繼節點的指針;span——當前層到下一個節點的跨度,用于計算元素排名。
  • 跳躍表對象(zskiplist

    • header:頭節點,包含所有可能的層級(默認 32 層),初始化時各層 forward 指向 NULL
    • tail:尾節點,支持快速逆序遍歷。
    • length:記錄元素數量,獲取長度的時間復雜度為 O(1)。
    • level:記錄當前跳躍表的最高層,決定查找路徑的起始層。
跳躍表的核心特性
  • 多層鏈表結構

    • 層級隨機生成:每個節點的層數在插入時隨機確定(冪次定律:層數越高概率越低),確保高層級稀疏分布。

    • 查找路徑優化:從最高層開始查找,逐步降層,跳過大量節點(類似二分查找)。

  • 排序與唯一性

    • 按分值排序:節點按 score 升序排列,相同 score 的節點按 ele 的字典序排列。

    • 成員唯一性ele 唯一,插入重復 ele 時直接更新 score

  • 范圍查詢支持

    • ZRANGE、ZRANK:利用 span 字段快速計算排名或遍歷區間。

    • ZREVRANGE:通過 backward 指針逆序訪問。

Redis 中的應用
  • 有序集合(Sorted Set)

    • 底層實現:當有序集合元素較多時,使用跳躍表(zset 結構包含跳躍表和字典,字典用于 O(1) 查找 ele 對應的 score)。

    • 典型命令ZADD——插入元素;ZRANGE——按排名范圍獲取元素;ZRANK——獲取元素排名。

  • 集群節點管理:集群模式下,跳躍表用于維護槽(Slot)與節點的映射關系。

整數集合

整數集合的結構定義
  • encoding:編碼方式,決定每個元素占用的字節數,INTSET_ENC_INT16INTSET_ENC_INT32INTSET_ENC_INT64
  • length:集合中元素的數量。
  • contents[]:元素的實際存儲數組,元素按值從小到大排序,且無重復。
核心機制:動態升級
  • 觸發條件:當插入一個無法用當前編碼表示的整數時,整數集合自動升級編碼。

  • 升級步驟

    • 計算新編碼:根據插入值的大小選擇最小兼容編碼。
    • 擴容內存:重新分配空間,計算新編碼下的總字節數(length * new_encoding_size)。
    • 數據遷移:從后向前依次將舊元素轉換為新編碼,避免覆蓋問題。
    • 插入新元素:根據新元素的值插入到正確位置(保持有序性)。
    • 更新結構:修改 encoding 字段,完成升級。
Redis 中的應用
  • 集合鍵(Set Key):當集合元素全為整數且數量小于 set-max-intset-entries(默認512)時,Redis 使用整數集合。
  • 性能優化:小規模整數集合的內存效率遠超哈希表(如存儲 100個int16僅需 200 + 8 字節,而哈希表需至少 100個entry)。

壓縮列表Ziplist

壓縮列表的結構
  • 頭部元數據

    • zlbytes(4字節):整個壓縮列表占用的內存字節數。

    • zltail(4字節):尾節點(最后一個Entry)的偏移量(便于快速定位尾節點)。

    • zllen(2字節):節點數量(若值 ≤ 65535則為實際數量,否則需遍歷計算)。

  • 節點(Entry)結構

    • prevlen:前驅節點的長度(字節數),用于逆向遍歷。

    • encoding:當前節點的數據類型和長度編碼。

    • content:實際存儲的數據(整數或字節數組)。

  • 結束標記:0xFF標識壓縮列表的結尾。

核心機制與操作
  • 編碼方式

    • 整數編碼:根據數值范圍選擇最小編碼(如int16_tint24_tint32_tint64_t)。

    • 字符串編碼:短字符串(長度 ≤ 63字節):encoding占1字節(2 + 6);長字符串:encoding占2或5字節,記錄長度。

  • 連鎖更新(Cascade Update)

    • 觸發條件:插入或刪除導致某個節點的prevlen從1字節擴展為5字節(或反之)。

    • 影響:可能引發后續多個節點的prevlen更新,最壞時間復雜度為 O(N^2)

    • 優化:實際場景中概率極低,Redis未做特殊處理。

Redis 中的應用
  • 列表鍵(List Key):當元素均為小整數或短字符串,且數量小于 list-max-ziplist-entries(默認512)時,使用壓縮列表。
  • 哈希鍵(Hash Key):當字段和值均為小數據,且字段數小于 hash-max-ziplist-entries(默認512)時,使用壓縮列表。
  • 有序集合(Zset):早期版本中,小規模有序集合使用壓縮列表存儲元素(分值相鄰存儲),現已被快速列表(Quicklist)替代。

對象

對象類型(type
類型常量對象類型底層數據結構示例命令
REDIS_STRING字符串對象SDS、整數、embstr 編碼的 SDSSET, GET, INCR
REDIS_LIST列表對象壓縮列表(Ziplist)、雙向鏈表LPUSH, RPOP, LRANGE
REDIS_HASH哈希對象壓縮列表、字典(Dict)HSET, HGET, HKEYS
REDIS_SET集合對象整數集合(Intset)、字典SADD, SMEMBERS
REDIS_ZSET有序集合對象壓縮列表、跳躍表(SkipList)+ 字典ZADD, ZRANGE
編碼方式(encoding
編碼常量說明適用對象類型
REDIS_ENCODING_INT整數編碼(long 類型)字符串對象
REDIS_ENCODING_EMBSTRembstr 編碼的 SDS(短字符串)字符串對象
REDIS_ENCODING_RAWSDS 字符串(長字符串)字符串對象
REDIS_ENCODING_HT字典(哈希表)集合、哈希對象
REDIS_ENCODING_ZIPLIST壓縮列表列表、哈希、有序集合對象
REDIS_ENCODING_INTSET整數集合集合對象
REDIS_ENCODING_SKIPLIST跳躍表 + 字典有序集合對象
REDIS_ENCODING_QUICKLIST快速列表(Redis 3.2+,鏈表+壓縮列表)列表對象
REDIS_ENCODING_STREAM流(Stream,Redis 5.0+)流對象
對象的核心機制
  • 類型檢查與命令多態

    • 類型檢查:執行命令前,Redis 檢查操作的鍵的值對象類型是否匹配。

    • 多態命令:同一命令對不同編碼的對象執行不同操作。

  • 內存優化:動態編碼轉換

    對象類型初始編碼轉換條件轉換后編碼
    字符串對象EMBSTR字符串長度增加至 >44字節RAW(SDS)
    列表對象ZIPLIST元素數量 > list-max-ziplist-entries或元素長度 > list-max-ziplist-valueQUICKLIST
    哈希對象ZIPLIST字段數量 > hash-max-ziplist-entries或字段/值長度 > hash-max-ziplist-valueHT(字典)
    集合對象INTSET插入非整數元素或元素數量 > set-max-intset-entries(默認512)HT(字典)
    有序集合對象ZIPLIST元素數量 > zset-max-ziplist-entries或元素長度 > zset-max-ziplist-valueSKIPLIST + 字典
  • 內存管理:引用計數與共享對象

    • 引用計數(refcount

      對象被創建時 refcount=1

      對象被引用時 refcount++(如被加入數據庫、被客戶端緩存)。

      對象被解除引用時 refcount--,當 refcount=0 時釋放內存。

  • 共享對象:Redis 預先創建 0~9999 的整數對象供全局共享,減少重復創建。

  • 空轉時間(lru)與淘汰策略

    • LRU 模式lru 字段記錄對象最后一次被訪問的時間戳(精度為秒),用于 volatile-lruallkeys-lru 淘汰策略。

    • LFU 模式lru 字段分為兩部分(高 16 位分鐘級時間戳,低 8 位訪問頻率),用于 volatile-lfuallkeys-lfu

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

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

相關文章

NeurIPS 2025 截稿攻略

會議資訊 NeurIPS&#xff0c;全稱神經信息處理系統大會&#xff0c;是一個關于機器學習和計算神經科學的國際會議。NeurIPS是CCF&#xff08;計算機學會&#xff09;推薦的A類會議&#xff01;是機器學習領域內最具難度、水平最高且影響力最強的會議之一。它與ICML&#xff0…

Java中堆棧

文章目錄 Java中堆棧1. 棧&#xff08;Stack&#xff09;特點示例 2. 堆&#xff08;Heap&#xff09;特點示例 3. 核心區別4. 常見問題5. 內存可視化示例內存布局示意圖&#xff1a; 總結 Java中堆棧 在 Java 中&#xff0c;“堆棧” 通常指的是堆&#xff08;Heap&#xff0…

【類拷貝文件的運用】

常用示例 當我們面臨將文本文件分成最大大小塊的時&#xff0c;我們可能會嘗試編寫如下代碼: public class TestSplit {private static final long maxFileSizeBytes 10 * 1024 * 1024; // 默認10MBpublic void split(Path inputFile, Path outputDir) throws IOException {…

打破產品思維--被討厭的勇氣--實戰5

課程&#xff1a;B站大學 記錄產品經理實戰項目系統性學習&#xff0c;從產品思維&#xff0c;用戶畫像&#xff0c;用戶體驗&#xff0c;增長數據驅動等不同方向理解產品&#xff0c;從0到1去理解產品從需求到落地的全過程&#xff0c;測試左移方向&#xff08;靠近需求、設計…

【Autosar SecOC 1.信息安全原理介紹】

這里寫目錄標題 1 背景2 了解黑客攻擊原理3 SecOC實現數據的真實性與完整性校驗3.1 數據身份驗證完成真實性驗證3.2 防止重放攻擊 1 背景 在今天的車載網絡中&#xff0c;大部分數據傳輸是在沒有任何特殊安全措施的情況下進行的。因此&#xff0c;一旦能夠直接訪問車輛的總線&a…

基于SpringBoot的校園周邊美食探索及分享平臺【附源碼+數據庫+文檔下載】

一、項目簡介 本項目是一個基于 SpringBoot Vue 的校園周邊美食探索與分享平臺&#xff0c;專為在校大學生開發&#xff0c;集美食推薦、好友互動、收藏分享于一體。 通過平臺&#xff0c;用戶可以探索學校周邊的美食店鋪、發布美食鑒賞、添加好友進行交流分享。同時&#x…

無償幫寫畢業論文

以下教程教你如何利用相關網站和AI免費幫你寫一個畢業論文。畢竟畢業論文只要過就行&#xff0c;脫產學習這么多年&#xff0c;終于熬出頭了&#xff0c;完成畢設后有空就去多看看親人好友&#xff0c;祝好&#xff01; 一、找一個論文模板(最好是overleaf) 廢話不多說&#…

15 個 Azure DevOps 場景化面試問題及解答

問題 1. 解釋 Azure DevOps YAML 管道的典型結構。 您可以從管道的整體結構開始&#xff0c;從觸發器開始。您也可以選擇解釋它可能包含的不同類型的階段&#xff1a;構建、測試、掃描、部署等。 Azure DevOps YAML 管道結構示例 觸發器指示管道運行。它可以是持續集成 (CI) 或…

Java 大視界 -- Java 大數據機器學習模型在元宇宙虛擬場景智能交互中的關鍵技術(239)

&#x1f496;親愛的朋友們&#xff0c;熱烈歡迎來到 青云交的博客&#xff01;能與諸位在此相逢&#xff0c;我倍感榮幸。在這飛速更迭的時代&#xff0c;我們都渴望一方心靈凈土&#xff0c;而 我的博客 正是這樣溫暖的所在。這里為你呈上趣味與實用兼具的知識&#xff0c;也…

本地不安裝oracle,還想連oracle

1.首先要用navicat,或者toad打開連接數據庫 2.安裝oracle客戶端&#xff0c;有時候OCI.dll需要看數據庫版本&#xff0c;我們Oracle數據庫是12C&#xff0c;可以用這個版本 3. 4.配置環境變量 變量名&#xff1a;NLS_LANG變量值&#xff1a;SIMPLIFIED CHINESE_CHINA.ZHS16GBK …

LabVIEW車牌自動識別系統

在智能交通快速發展的時代&#xff0c;車牌自動識別系統成為提升交通管理效率的關鍵技術。本案例詳細介紹了基于 LabVIEW 平臺&#xff0c;搭配大恒品牌相機構建的車牌自動識別系統&#xff0c;該系統在多個場景中發揮著重要作用&#xff0c;為交通管理提供了高效、精準的解決方…

deque底層數據結構以及和queue的異同

文章目錄 底層數據結構原理關鍵組成部分操作效率與其他容器的對比適用場景C STL中的實現細節總結 deque和queue的異同相同點不同點 deque&#xff08;雙端隊列&#xff09;是一種具有高效兩端插入和刪除操作的數據結構&#xff0c;常見于C標準庫&#xff08;STL&#xff09;和其…

WordPress 網站上的 jpg、png 和 WebP 圖片插件

核心功能 1. 轉換 AVIF 并壓縮 AVIF 將您 WordPress 網站上的 jpg、png 和 WebP 圖片轉換為 AVIF 格式&#xff0c;并根據您設置的壓縮級別壓縮 AVIF 圖片。如果原始圖片已經是 WordPress 6.5 以上支持的 AVIF 格式&#xff0c;則原始 AVIF 圖片將僅被壓縮。 2. 轉換 WebP 并…

Docker Volumes

Docker Volumes 是 Docker 提供的一種機制&#xff0c;用于持久化存儲容器數據。與容器的生命周期不同&#xff0c;Volumes 可以獨立存在&#xff0c;即使容器被刪除&#xff0c;數據仍然保留。以下是關于 Docker Volumes 的詳細說明&#xff1a; 1. 為什么需要 Volumes&#…

西電 | 2025年擬錄取研究生個人檔案錄取通知書郵寄通知

各位考生&#xff1a; 我校2025年碩士研究生錄取工作已結束&#xff0c;根據相關工作管理規定&#xff0c;現將個人檔案轉調及錄取通知書郵寄信息確認等有關事宜通知如下&#xff1a; 一、個人檔案轉調 &#xff08;郵寄檔案請務必使用EMS&#xff09; 1.全日制考生 錄取類…

ExcelJS庫的使用

ExcelJS 安裝 npm install exceljs新的功能! Merged fix: styles rendering in case when “numFmt” is present in conditional formatting rules (resolves #1814) #1815. Many thanks to andreykrupskii for this contribution!Merged inlineStr cell type support #15…

時空注意力機制深度解析:理論、技術與應用全景

時空注意力機制作為深度學習領域的關鍵技術&#xff0c;通過捕捉數據在時間和空間維度上的依賴關系&#xff0c;顯著提升了時序數據處理和時空建模能力。本文從理論起源、數學建模、網絡架構、工程實現到行業應用&#xff0c;系統拆解時空注意力機制的核心原理&#xff0c;涵蓋…

wxWidgets 3.2.8 發布,修復了GTK下,wxStaticText顯示文本異常的問題

詳細如下&#xff1a; 3.2.8 是穩定的 3.2 系列中的最新維護版本&#xff0c;現已在 GitHub 上提供&#xff0c;您可以從中下載帶有 所選 Windows 的庫源和文檔以及二進制文件 編譯器&#xff0c;例如 Microsoft Visual C、MinGW-w64 和 TDM-GCC。您還可以閱讀更新的文檔 版本&…

網頁Web端無人機直播RTSP視頻流,無需服務器轉碼,延遲300毫秒

隨著無人機技術的飛速發展&#xff0c;全球無人機直播應用市場也快速擴張&#xff0c;從農業植保巡檢到應急救援指揮&#xff0c;從大型活動直播到智慧城市安防&#xff0c;實時視頻傳輸已成為剛需。預計到2025年&#xff0c;全球將有超過1000萬架商用無人機搭載直播功能&#…

思維鏈框架:LLMChain,OpenAI,PromptTemplate

什么是思維鏈,怎么實現 目錄 什么是思維鏈,怎么實現思維鏈(Chain of Thought)在代碼中的實現方式1. 手動構建思維鏈提示2. 少樣本思維鏈提示3. 自動思維鏈生成4. 思維鏈與工具使用結合5. 使用現有思維鏈框架:LLMChain,OpenAI,PromptTemplate思維鏈實現的關鍵要點思維鏈(C…