Redis 哈希表的核心——`dictEntry` 結構體

接上一篇

Redis 哈希表的本質:數組里存的是什么

Redis 哈希表的核心——dictEntry 結構體,是真正承載我們存儲的鍵值對數據的那個結構。

它的定義非常簡潔,但設計得很巧妙。以下是其 C 語言代碼(在 Redis 源碼 src/dict.h 中):

typedef struct dictEntry {void *key; // 鍵union {    // 值(是一個聯合體)void *val;uint64_t u64;int64_t s64;double d;} v;struct dictEntry *next; // 指向下一個哈希表節點,形成鏈表
} dictEntry;

讓我們逐字段分解它的樣子和作用:


1. void *key (鍵)

  • 類型void *,一個指向任意類型的指針。
  • 作用: 存儲鍵(Key)。
  • 細節: Redis 中的鍵絕大多數情況下都是 SDS (Simple Dynamic String) 類型。所以,這里通常指向一個 SDS 字符串的結構體。使用 void * 使得字典的實現非常通用,理論上可以存儲任何類型的鍵,但 Redis 自身主要用字符串作為鍵。

2. union v (值 - 聯合體)

這是最精妙的部分。v 是一個聯合體(union)。聯合體的特點是所有成員共享同一塊內存空間,空間大小由最大的成員決定。這意味著,在任何一個時刻,這個字段只能存儲其中一種類型的值。

  • void *val:

    • 這是最常用的成員。它是一個指針,指向 Redis 中表示的“值”對象。
    • Redis 中的所有數據類型(字符串、列表、哈希、集合、有序集合等)在底層都是用 redisObject 結構體(robj)來表示的。這個 val 指針就指向一個 robj
    • 通過 robj,Redis 才能知道這個值是什么類型(type)、用什么編碼(encoding),以及如何操作它。
  • uint64_t u64:

    • 存儲一個 64 位無符號整數
    • 應用場景: 當哈希表被用于一些 Redis 的內部功能時,可以直接存儲整數,避免額外的指針開銷(既省內存,又免去了一次指針尋址,速度更快)。例如,用于記錄數據庫的過期時間戳。
  • int64_t s64:

    • 存儲一個 64 位有符號整數
    • 應用場景: 同上,用于存儲整數值。
  • double d:

    • 存儲一個 雙精度浮點數
    • 應用場景: 用于直接存儲浮點數值。

使用聯合體的好處:

  • 節省內存:一塊內存,多種用途。如果不用聯合體,就需要為每種可能的值類型都定義一個字段,會浪費大量空間。
  • 高效:對于整數和浮點數,可以直接內聯存儲,省去了創建 robj 對象和指針引用的開銷,性能更高。

3. struct dictEntry *next (下一個節點指針)

  • 類型: 指向另一個 dictEntry 結構體的指針。
  • 作用用于解決哈希沖突,形成鏈表(拉鏈法)。
  • 細節: 當兩個或多個鍵通過哈希函數計算出的數組索引(桶位置)相同時,就會發生哈希沖突。這些發生沖突的鍵值對會通過 next 指針連接成一個單向鏈表,掛在數組的同一個桶上。查找時,如果找到的桶里有多個節點,就需要遍歷這個鏈表,用 key 來進行精確匹配。

一個具體的例子

假設我們執行命令 SET mykey "Hello",這個鍵值對在全局哈希表中就會由一個 dictEntry 來表示:

  1. key 指針:指向一個 SDS 結構,里面存儲著字符串 "mykey"
  2. v.val 指針:指向一個 redisObject (robj)。
    • 這個 robjtypeOBJ_STRING
    • 它的 ptr 指針又指向一個 SDS 結構,里面存儲著字符串 "Hello"
  3. next 指針:假設 "mykey" 沒有發生哈希沖突,那么這個指針就是 NULL

內存結構簡化圖示:

dictEntry
+-------------------+     +-------------------------+
| key (void*)    ---|---->| SDS: "mykey"            |
+-------------------+     +-------------------------+
| v (union)        |     +-------------------------+
|   val (void*) ---|---->| redisObject (robj)      |
|   u64           |      |   type: OBJ_STRING      |
|   s64           |      |   encoding: ...         |
|   d             |      |   ptr (void*) -------+  |
+-------------------+     +-------------------------+ |
| next (NULL)      |                              |
+-------------------+                              |vSDS: "Hello"

總結

dictEntry 結構體是 Redis 所有鍵值數據的最終載體,它的設計體現了 Redis 對性能內存效率的極致追求:

  1. 通用性:使用 void* 鍵和聯合體 v,使其能夠靈活存儲各種數據。
  2. 高效性:通過聯合體內聯存儲整數和浮點數,減少內存分配和指針跳轉。
  3. 解決沖突:通過 next 指針實現拉鏈法,簡單可靠。

理解 dictEntry 是理解 Redis 如何高效管理海量數據的關鍵一步。

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

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

相關文章

Jsqlparser + Freemarker + Vue3 數據透視報表設計方案

1. 目標與前置條件目標:基于 JSQLParser FreeMarker Vue3 構建一套“可配置的數據透視報表”能力,實現從任意基礎 SQL/視圖出發,按維度/指標靈活聚合、篩選、排序、分頁、導出,并支持鉆取、聯動、TopN、同比環比等常見分析操作。…

SpringBoot3 Ruoyi芋道管理后臺vben5.0

新技術棧(Vue3、Vite6、TypeScript、SpringBoot3/SpringCloud基于Vben5.0最新版本,全面采用Vue3 Vite6 Ant Design Vue TypeScript技術棧,并同時支持SpringBoot3單體架構與SpringCloud微服務架構前端技術棧:Vue3 Vite6 TS A…

K8S - NetworkPolicy的使用

1 前置條件2 控制范圍3 隔離類型4 如何識別5 主要字段6 案例演示 前置條件 網絡策略通過網絡插件來實現。 要使用網絡策略,你必須使用支持 NetworkPolicy 的網絡解決方案。 創建一個 NetworkPolicy 資源對象而沒有控制器來使它生效的話,是沒有任何作用的…

Linux:TCP協議

TCP是一個面向連接的、可靠的、基于字節流的傳輸層協議。文次我們會通過介紹TCP的報頭并通過分析各字段的用途來進一步解釋其核心特性:可靠傳輸: 有確認應答、超時重傳、確保有序。流量控制和擁塞控制: 動態調節發送速率,防止丟包與擁塞。面向…

uniapp使用map打包app后自定義氣泡不顯示解決方法customCallout

前言:使用uniapp開發后在小程序可以正常顯示,但是運行打包成App后就不顯示了,其實這一塊對于uniapp框架開發來說,是有系統性的bug,如果你再開發時使用的是vue文件進行,就會出現這個問題。解決方法&#xff…

【typenum】 22 類型級別二進制對數運算(Logarithm2)

一、源碼 這段代碼實現了一個類型級別的二進制對數運算系統 定義(type_operators.rs) /// A **type operator** for taking the integer binary logarithm of Self. /// /// The integer binary logarighm of n is the largest integer m such /// that …

golang 非error錯誤分類

1.應用級別,可recover這些 panic 一般是 邏輯或使用不當導致的運行時錯誤,Go 程序可以用 recover 捕獲并繼續運行:類型示例描述類型不一致atomic.Value 存不同類型 v.Store(100); v.Store("abc")panic: store of inconsistently ty…

【Ansible】變量與敏感數據管理:Vault加密與Facts采集詳解

1. 變量Ansible利用變量存儲可重復使用的值,可以簡化項目的創建和維護,減少錯誤數量。1.1 變量名稱由字符串組成,必須以字母開頭,并且只能含有字母、數字和下劃線,和其它編程語言很類似。1.2 常見變量要創建的用戶要安…

ROS2下YOLO+Moveit+PCL機械臂自主避障抓取方案

整體運行架構 1.運行相機取像節點 . ./install/setup.bash ros2 launch orbbec_camera gemini_330_series.launch.py depth_registration:true 2.運行根據圖像x,y獲取z的service 基本操作記錄: 創建python包,在src目錄下 ros2 pkg create test_python_topic --bu…

快速入門Vue3——初體驗

目錄 前言 一、搭建環境 1.1、安裝Node.js 1.2、安裝Vite 二、項目創建 三、運行項目 四、集成Pinia 4.1、Pinia介紹 4.2、Pinia安裝 五、集成VueUse 5.1、vueuse簡介 5.2、vueuse安裝 六、集成Vant 6.1、Vant簡介 6.2、Vant安裝 前言 本專欄主要介紹如何使用…

深入理解Kubernetes核心:標簽與標簽選擇器實戰解析

在管理 Kubernetes 集群時,隨著 Pods、Services 等資源數量的增長,如何有效地組織和篩選它們,成為了一個核心問題。Kubernetes 為此提供了一個簡單卻極其強大的機制:標簽(Labels)和標簽選擇器(L…

哈希和字符串哈希

哈希(Hash) Hash 表 Hash 表又稱為散列表,一般由 Hash 函數(散列函數)與鏈表結構共同實現。與離散化思想類似,當我們要對若干復雜信息進行統計時,可以用 Hash 函數把這些復雜信息映射到一個容…

【Docker基礎】Docker-Compose核心配置文件深度解析:從YAML語法到高級配置

目錄 前言 1 YAML基礎語法解析 1.1 YAML格式簡介 1.2 Docker-compose中的YAML語法規則 1.3 YAML數據類型在Compose中的應用 2 docker-compose.yml文件結構剖析 2.1 基本文件結構 2.2 版本聲明詳解 3 services配置深度解析 3.1 服務定義基礎 3.2 鏡像與構建配置 3.3…

如何判斷是否應該為了一個小功能而引入一個大體積的庫

在軟件開發中,判斷是否應該為了一個看似微小的功能,而引入一個大體積的第三方庫,是一項極其重要的、需要進行審慎的“投入產出比”分析的技術決策。這個決策,絕不能,僅僅基于“實現功能的便利性”,而必須&a…

相機定屏問題分析五:【跳幀異常】照片模式1x以上的焦段拍照之后定屏

【關注我,后續持續新增專題博文,謝謝!!!】 上一篇我們講了: 這一篇我們開始講: 相機定屏問題分析五:【跳幀異常】照片模式1x以上的焦段拍照之后定屏9573412 目錄 一、問題背景 二…

Non-stationary Diffusion For Probabilistic Time Series Forecasting論文閱讀筆記

Non-stationary Diffusion For Probabilistic Time Series Forecasting 摘要 時間序列數據受到潛在的物理動力學和外部影響,其不確定性通常隨時間而變化。現有的去噪擴散概率模型(DDPMs)受到加性噪聲模型(ANM)的恒定方…

解決Docker 無法連接到官方鏡像倉庫

這個錯誤: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)表示 Docker 無法連接到官方鏡像倉庫 registry-1.docker…

解決RAGFlow啟動時Elasticsearch容器權限錯誤的技術指南

文章目錄 問題現象 根本原因分析 解決方案步驟 1. 定位宿主機數據目錄 2. 修復目錄權限 3. 驗證權限狀態 4. 重啟服務 5. 檢查啟動狀態 永久解決方案:優化Docker Compose配置 高級故障排除 技術原理 問題現象 在啟動RAGFlow項目時,執行 docker logs ragflow-es-01 發現Elast…

【C++高階六】哈希與哈希表

【C高階六】哈希與哈希表1.什么是哈希?2.unordered系列容器3.哈希表3.1將key與存儲位置建立映射關系3.1.1直接定址法3.1.2除留余數法(產生哈希沖突)3.2解決哈希沖突的方法3.2.1閉散列(開放定址法)3.3.2開散列&#xff…

Vue 3 +Ant Design Vue 父容器樣式不影響子級,隔離

公共樣式文件 common.scss.zz-ant-status-bar {div {font-size: 12px;padding: 0 8px;} }頁面代碼<div class"zz-ant-status-bar"><a-row><a-col :span"6" ><a-progress :percent"progress.percent" size"small"…