Redis底層數據結構與內部實現

目錄

一、RedisDB結構

1、RedisDB在Redis實例中的位置

2、RedisDB結構與核心組件

二、RedisObject結構

1、核心數據結構

1.1 簡單動態字符串 (Simple Dynamic String - SDS)

1.2?字典 (Dict / Hash Table)

1.3?雙端鏈表 (Linked List)

1.4 跳躍表 (Skip List)

1.5?壓縮列表 (ZipList) -?Redis 7.0 起被 Listpack 取代

1.6?緊湊列表 (Listpack) -?*Redis 5.0 引入,7.0 成為小規模列表/哈希/有序集合的默認*

1.7?整數集合 (IntSet)

1.8?快速列表 (QuickList) -?Redis 3.2 引入

2、對象系統(RedisObject)

2.1 結構信息概覽

2.2 核心作用

2.3 類型與編碼映射

2.3.1?字符串 (String)

2.3.2?列表 (List)

2.3.3?哈希 (Hash)

2.3.4?集合 (Set)

2.3.5?有序集合 (Sorted Set)


一、RedisDB結構

Redis 的數據庫由?redisDb?結構體表示,它是 Redis 存儲鍵值對、管理過期時間、實現阻塞操作、事務以及維護數據庫狀態的核心數據結構。每個 Redis 實例默認有 16 個獨立的數據庫(編號 0-15),可通過?SELECT?命令切換。

SELECT <db_index>  # <db_index> 為目標數據庫編號(整數)

1、RedisDB在Redis實例中的位置

一個 Redis 服務器實例 (redisServer?結構) 包含一個?redisDb?數組:

struct redisServer {...redisDb *db;       /* 指向一個 dbnum 大小的 redisDb 數組 */int dbnum;         /* 數據庫數量 (默認 16) */...
};

客戶端狀態 (client?結構) 中有一個指針指向其當前選擇的數據庫:

typedef struct client {...redisDb *db;    /* 指向當前客戶端選擇的數據庫 */...
} client;

當客戶端執行?SELECT 2?時,其?db?指針就被設置為指向?server.db[2]

2、RedisDB結構與核心組件

Redis結構

typedef struct redisDb {dict *dict;                 /* 核心:鍵空間(Keyspace),存儲所有鍵值對 */dict *expires;              /* 過期字典:存儲鍵的過期時間(毫秒時間戳) */dict *blocking_keys;        /* 阻塞鍵:記錄因 B[L/R]POP 等命令阻塞的鍵及等待的客戶端 */dict *ready_keys;           /* 就緒鍵:記錄有數據 PUSH 進來、可解除客戶端阻塞的鍵 */dict *watched_keys;         /* 被 WATCH 監視的鍵:用于事務 CAS 樂觀鎖 */int id;                     /* 數據庫 ID (0-15) */long long avg_ttl;          /* 平均 TTL(統計用) */unsigned long expires_cursor; /* 過期鍵掃描游標(用于周期性刪除) */list *defrag_later;         /* 后續嘗試內存碎片整理的鍵列表 */
} redisDb;

核心組件

1>?dict *dict?(鍵空間 - Keyspace)

  • 作用:?存儲該數據庫中所有鍵值對的核心字典。

  • 鍵 (Key):?Redis 字符串對象(內部是 SDS)。

  • 值 (Value):?指向?redisObject?結構的指針。redisObject?封裝了實際的數據類型(String, List, Hash, Set, ZSet)及其底層實現(SDS, QuickList, Dict, IntSet, SkipList 等)。

  • 操作:?所有對鍵的增刪改查(SET,?GET,?DEL,?EXISTS,?KEYS?等)都直接作用于這個字典。

2>?dict *expires?(過期字典 - Expires Dictionary)

  • 作用:?存儲設置了過期時間 (TTL)?的鍵及其過期時間戳(毫秒精度的 UNIX 時間戳)。

  • 鍵 (Key):?與?dict?中的鍵共享同一個 SDS 對象(指針相同,節省內存)。

  • 值 (Value):?long long?類型的整數,表示鍵的絕對過期時間戳(pexpireat?設置的時間點)。

  • 關鍵機制:

    • 惰性刪除 (Lazy Expiration):?當訪問一個鍵時(GET,?HGET,?LRANGE?等命令),Redis 會先檢查?expires?字典。如果該鍵存在且當前時間已超過其存儲的時間戳,則立即刪除該鍵(從?dict?和?expires?中移除),然后返回?nil?或錯誤。這保證了訪問到的鍵總是未過期的。

    • 定期刪除 (Active Expiration):?Redis 的事件循環 (serverCron?函數) 會周期性(默認每秒 10 次,可配置?hz)地主動掃描?expires?字典:

      • 每次隨機抽取一定數量(默認 20 個)的過期鍵。

      • 刪除其中已過期的鍵。

      • 如果過期鍵比例超過 25%,則重復此過程。

      • 使用?expires_cursor?記錄掃描位置,確保所有鍵都能被掃描到。

    • 過期策略:?Redis 結合了惰性刪除(確保訪問準確性)和定期刪除(回收內存)兩種策略。

3>?dict *blocking_keys?(阻塞鍵字典)

  • 作用:?管理因執行?阻塞式列表彈出命令(如?BLPOP,?BRPOP,?BRPOPLPUSH)而等待數據的客戶端。

  • 鍵 (Key):?被阻塞客戶端等待的列表鍵名(SDS)。

  • 值 (Value):?一個指向鏈表的指針。該鏈表中存放了所有因等待這個鍵的數據而被阻塞的?client?結構(客戶端狀態)。

  • 原理:?當客戶端執行?BLPOP key1 key2 ... timeout?時,如果所有指定列表都為空,客戶端會被阻塞。Redis 會將該客戶端添加到?blocking_keys?中每個指定?key?對應的阻塞客戶端鏈表中,并設置超時計時器。

4>?dict *ready_keys?(就緒鍵字典)

  • 作用:?作為?blocking_keys?的輔助結構,用于高效地處理阻塞解除

  • 鍵 (Key):?一個列表鍵名(SDS)。

  • 值 (Value):?通常為?NULL(不重要),存在即表示該鍵有數據到達。

  • 工作流程:

    1. 當有客戶端向一個空列表執行?LPUSH,?RPUSH?等命令添加數據時,該列表鍵會被標記為就緒(添加到?ready_keys?字典)。

    2. 在 Redis 的事件循環中(beforeSleep?函數),會檢查?ready_keys?字典。

    3. 對于其中每個就緒鍵,Redis 會查找?blocking_keys?中該鍵對應的阻塞客戶端鏈表。

    4. 從鏈表中取出一個(或多個,取決于命令)客戶端,向其返回新添加的數據,并解除其阻塞狀態。

  • 優點:?避免了在每次?PUSH?命令執行時直接遍歷阻塞客戶端鏈表帶來的性能開銷,將解除阻塞的操作集中處理。

5>?dict *watched_keys?(監視鍵字典)

  • 作用:?實現?WATCH?命令,為 Redis 事務提供樂觀鎖 (CAS - Check And Set)?機制。

  • 鍵 (Key):?被客戶端?WATCH?的鍵名(SDS)。

  • 值 (Value):?一個指向鏈表的指針。該鏈表中存放了所有?WATCH?了這個鍵的?client?結構(客戶端狀態)。

  • 事務流程:

    1. 客戶端使用?WATCH key1 key2 ...?監視一個或多個鍵。

    2. 客戶端開啟事務 (MULTI) 并發送命令隊列 (SET,?INCR?等)。

    3. 客戶端提交事務 (EXEC)。

    4. 執行?EXEC?前,Redis 檢查:

      • 遍歷客戶端?WATCH?的所有鍵。

      • 檢查這些鍵在?watched_keys?中的鏈表是否存在(即鍵是否被修改?)。

      • 檢查鍵自?WATCH?后是否被其他客戶端修改過(通過?redisObject?的?lru?字段或專門的?dirty?標志)。

    5. 如果至少有一個被?WATCH?的鍵被修改過,服務器拒絕執行事務隊列 (EXEC?返回?nil),客戶端需要重試。

    6. 如果沒有被修改,則執行事務隊列中的所有命令。

  • 鍵修改觸發:?任何成功修改鍵值的命令(SET,?INCR,?LPUSH,?DEL?等)在執行后,會遍歷?watched_keys?找到該鍵對應的鏈表,將其中所有客戶端的?REDIS_DIRTY_CAS?標志置位,表示該客戶端監視的鍵已被改動,其事務將在?EXEC?時失敗。

6>?int id?(數據庫 ID)

  • 標識該數據庫的編號,范圍是?0?到?server.dbnum - 1(默認?0?到?15)。

  • 客戶端通過?SELECT id?命令在不同數據庫間切換。

7>?long long avg_ttl?(平均 TTL)

  • 數據庫所有設置了 TTL 的鍵的平均剩余生存時間(毫秒)。這是一個統計值,并非實時精確計算,主要用于?INFO?命令輸出,幫助管理員了解數據庫過期鍵的大致情況。

8>?unsigned long expires_cursor?(過期鍵掃描游標)

  • 用于實現定期刪除策略中的漸進式掃描。記錄當前掃描?expires?字典的桶索引 (bucket index),確保每次?serverCron?調用時掃描不同的部分,避免集中掃描導致延遲。

9>?list *defrag_later?(后續碎片整理列表)

  • Redis 的內存碎片整理 (MEMORY PURGE?/?CONFIG SET activedefrag ...) 可能無法一次性完成所有工作。

  • 此列表保存了需要稍后進行碎片整理嘗試的鍵(指向?dict?中鍵的指針)。

  • 碎片整理過程會逐步遍歷這個列表,嘗試對鍵指向的?redisObject?及其底層數據結構(如包含大量小元素的 Hash、List、ZSet)進行內存重排,減少碎片。

二、RedisObject結構

1、核心數據結構

1.1 簡單動態字符串 (Simple Dynamic String - SDS)

用途:?存儲字符串值、整型數據、鍵名、緩沖區等。

設計目標:?解決 C 語言原生字符串的缺陷,提高安全性和效率。

關鍵結構 (簡化):

struct sdshdr {int len;      // 已使用字節長度 (字符串實際長度,不含'\0')int alloc;    // 分配的總字節長度 (不包括 header 和 null terminator)char flags;   // SDS 類型標識 (sdshdr5, sdshdr8, sdshdr16, sdshdr32, sdshdr64)char buf[];   // 柔性數組,存放實際字符串 + '\0'
};

優勢:

  • O(1) 復雜度獲取長度:?直接訪問?len?字段。C字符串是O(n)。

  • 杜絕緩沖區溢出:?修改前檢查?alloc,空間不足自動擴容。

  • 減少內存重分配:?空間預分配 (alloc = len + newlen) 和惰性空間釋放策略優化性能。

  • 二進制安全:?可以存儲包含?'\0'?的任意二進制數據,靠?len?判斷結束。由于二進制數據包括空字符串\0,C沒有辦法存取二進制數據。

  • 兼容 C 字符串:?buf?末尾保留?'\0',可直接使用部分 C 字符串函數。

1.2?字典 (Dict / Hash Table)

用途:?存儲所有鍵值對、哈希類型數據、Set 類型數據(當元素為字符串且非整數時)等。Redis整個數據庫是用字典來存儲的。

核心結構:

  • ?字典 (dict):

typedef struct dict {dictType *type; // 該字典對應的特定操作函數 (hash, keyDup, keyCompare, ...)void *privdata; // 上述類型函數對應的可選參數dictht ht[2];   // 兩張哈希表,存儲鍵值對數據,ht[0]為原生哈希表,ht[1]為 rehash 哈希表long rehashidx; // rehash標識 當等于-1時表示沒有在rehash,否則表示正在進行rehash操作,存儲的值表示hash表 ht[0]的rehash進行到哪個索引值(數組下標)int iterators;  // 當前運行的迭代器數量
} dict;// 包含對該字典操作的函數指針
typedef struct dictType {// 計算哈希值的函數unsigned int (*hashFunction)(const void *key);// 復制鍵的函數void *(*keyDup)(void *privdata, const void *key);// 復制值的函數void *(*valDup)(void *privdata, const void *obj);// 比較鍵的函數int (*keyCompare)(void *privdata, const void *key1, const void *key2);// 銷毀鍵的函數void (*keyDestructor)(void *privdata, void *key);// 銷毀值的函數void (*valDestructor)(void *privdata, void *obj);
} dictType;
  • 哈希表 (dictht):

typedef struct dictht {dictEntry **table;      // 哈希桶數組指針(哈希表數組)unsigned long size;     // 哈希表數組大小 (桶的數量,總是 2^n),初始容量為4,隨著k-v增加,新擴容量為當前量的一倍(4,8,16,32)unsigned long sizemask; // 用于映射位置的掩碼,值永遠等于 (size - 1),索引值=Hash值&掩碼值unsigned long used;     // 已有節點數量,包含next單鏈表的數據
} dictht;
  • 哈希表節點 (dictEntry):

typedef struct dictEntry {void *key;              // 鍵union {                 // 值v的類型可以是以下4種類型void *val;uint64_t u64;int64_t s64;double d;} v; struct dictEntry *next; // 指向下一個節點,形成鏈表 (解決哈希沖突)
} dictEntry;

關鍵機制:

  • 哈希沖突解決:?鏈地址法。相同桶內的節點用鏈表連接。

  • Rehash:

    • 觸發條件:?

      • 負載因子超標:

        • 當?ht[0].used / ht[0].size > dict_force_resize_ratio(默認?5)時強制擴容

        • 或?used / size > 1?且允許 rehash(無迭代器運行)時建議擴容

      • BGSAVE/BGREWRITEAOF 優化:若正在進行子進程持久化操作,負載因子閾值提升至?5(避免父進程 COW 內存復制)

    • 漸進式rehash過程:?漸進式 rehash。分配?ht[1],將?rehashidx?從 0 開始遞增,每次增刪改查操作時,順帶將?ht[0]?中?rehashidx?桶的所有鍵值對遷移到?ht[1]。完成后?ht[1]?變為?ht[0],重置?ht[1]?和?rehashidx

      • 步驟1:初始化rehash

        • 分配ht[1]?空間:新容量 = 第一個大于等于?ht[0].used × 2?的?2^n(如 6 → 8,10 → 16)

        • 設置?rehashidx = 0(標記 rehash 開始)

      • 步驟2:分布遷移數據(每次操作遷移一個桶鏈/鏈表,分散到多次操作中完)

        • 寫操作觸發遷移:新增加的數據在新的hash表h[1]

        • 定時任務遷移:將老數據重新計算索引值后遷移到h[1]。

      • 步驟3:完成遷移

        • 當?ht[0].used == 0?時:

          • 釋放?ht[0].table

          • 將?ht[1]?賦值給?ht[0]

          • 重置?ht[1]?為空表

          • 設置?rehashidx = -1(標記 rehash 結束)

    • 優點:?避免一次性遷移大量數據導致服務停頓。

      擴容方式平均延遲內存峰值適用場景
      傳統一次性 rehash1x小數據集
      Redis 漸進式 rehash2x生產環境大數據實時服務
    • 縮容機制:當?used < size/10?時觸發縮容(避免內存浪費);流程與擴容相同

    • 并發安全策略

      • 查找:同時在 ht[0] 和 ht[1] 中搜索

      • 插入:直接寫入 ht[1](避免重復遷移)

      • 刪除/更新:需同時操作兩個表

    • ?擴容過程示例

假設初始狀態:
ht[0]:size=4,used=3(負載因子 0.75)
插入新鍵值對 → used=4(負載因子=1)觸發擴容

操作ht[0] (size=4)ht[1] (size=8)rehashidx
初始狀態[k1,k2,k3,k4]-1
觸發擴容[k1,k2,k3,k4]分配 size=80
遷移桶0(k1,k2)[NULL,k3,k4][k1,k2]1
遷移桶1(k3)[NULL,NULL,k4][k1,k2,k3]2
遷移桶2(k4)全空[k1,k2,k3,k4]-1 (完成)

1.3?雙端鏈表 (Linked List)

用途:?列表類型數據、發布訂閱、慢查詢、監視器、保存多個客戶端狀態等。

核心結構 (listNode,?list):

typedef struct listNode {struct listNode *prev;struct listNode *next;void *value;
} listNode;typedef struct list {listNode *head;listNode *tail;void *(*dup)(void *ptr);    // 節點值復制函數void (*free)(void *ptr);     // 節點值釋放函數int (*match)(void *ptr, void *key); // 節點值對比函數unsigned long len;           // 鏈表長度
} list;

特點:?O(1) 復雜度訪問頭尾節點,支持雙向遍歷。內存開銷相對較高 (每個節點需要 prev/next 指針)。

1.4 跳躍表 (Skip List)

用途:?有序集合 (Sorted Set) 類型數據的底層實現之一。

設計目標:?在鏈表基礎上提供接近平衡樹的查找效率 (平均 O(logN)),且實現更簡單,范圍查詢更高效。

基本思想:將有序鏈表中的部分節點分層,每一層都是一個有序鏈表。

核心結構 (zskiplistNode,?zskiplist):

//跳躍表節點
typedef struct zskiplistNode {sds ele;                    // 成員值 (字符串SDS)double score;               // 分值(排序依據)struct zskiplistNode *backward; // 后退指針 (雙向鏈表)struct zskiplistLevel {struct zskiplistNode *forward; // 前進指針,指向本層的下一個節點unsigned long span;      // 跨度 (到下一個節點的距離),用于排名} level[];                  // 柔性數組,動態定義層數
} zskiplistNode;typedef struct zskiplist {struct zskiplistNode *header, *tail; // 頭尾節點unsigned long length;        // 節點總數 (不包括頭節點)int level;                  // 當前最大層數 (不包括頭節點層)
} zskiplist;

工作原理:

  • 多層鏈表結構。最底層 (L0) 包含所有元素,是有序鏈表。

  • 上層鏈表是下層的"快速通道",節點數更少。

  • 插入時隨機確定節點的層數 (冪次定律,越高層概率越低)。

  • 查找從最高層開始,比較?score?和?ele,如果下一個節點大于目標值,則下降到下一層繼續查找。

優點:?支持高效范圍查詢 (ZRANGE,?ZREVRANGE),插入刪除相對平衡樹更簡單。

維度跳躍表 (Skip List)平衡樹 (AVL/RB-Tree)
實現復雜度? 簡單(無旋轉操作)? 復雜(需處理旋轉/再平衡)
范圍查詢? 天然支持(鏈表順序遍歷)🔶 需中序遍歷
并發友好性? 更易實現無鎖并發? 鎖粒度大
內存占用🔶 略高(存儲多層指針)? 更緊湊
性能穩定性? 無最壞情況(概率平衡)? 可能退化為 O(n)
調試與維護? 可視化直觀🔶 結構復雜

1.5?壓縮列表 (ZipList) -?Redis 7.0 起被 Listpack 取代

用途 (歷史):?小規模列表、哈希、有序集合的緊湊存儲。

結構:?一塊連續內存,順序存儲多個元素。是一個字節數組,可以包含多個節點(entry)。每個節點可以保存一個字節數組或一個整數。

  • <zlbytes>: 4 字節,列表總字節數(字節長度)。

  • <zltail>: 4 字節,列表尾節點偏移量。

  • <zllen>: 2 字節,節點數量 (超過 65535 時需遍歷)。

  • <entry>: 若干節點。每個節點包含:

    • <prevlen>: 前一個節點的長度 (1 或 5 字節)。

    • <encoding>: 內容編碼 (類型和長度,1/2/5 字節)。

    • <content>: 實際數據。

  • <zlend>: 1 字節,結束標志 0xFF(255)。

優點:?內存緊湊,減少碎片,適合小數據。

缺點 (連鎖更新):?修改中間節點可能導致后續所有節點的?<prevlen>?需要擴展 (1->5 字節),引發多次內存重分配。這是被 Listpack 取代的主要原因。

1.6?緊湊列表 (Listpack) -?*Redis 5.0 引入,7.0 成為小規模列表/哈希/有序集合的默認*

設計目標:?解決 ZipList 的連鎖更新問題,更簡單高效。

結構:?也是一塊連續內存。

  • <總字節數>: 4 字節。

  • <元素數量>: 2 字節。

  • <元素項>: 若干項。每個元素項:

    • <encoding+data>: 編碼 (包含數據類型和長度信息) + 實際數據。

    • <element-tot-len>:?反向保存?當前元素項的總長度 (從?<element-tot-len>?自身末尾到?<encoding>?開頭)。這個長度字段是變長的 (1-5 字節)。

  • <結束符>: 1 字節 (0xFF)。

關鍵改進:

  • 消除連鎖更新:?每個元素項獨立存儲自身長度 (<element-tot-len>),修改一個元素不會影響其他元素的長度字段。

  • 反向長度:?<element-tot-len>?存儲的是從自己末尾到前一項開頭的長度。遍歷時從后向前遍歷效率更高,查找時通常也是定位到某個位置再前后移動。

1.7?整數集合 (IntSet)

用途:?當集合 (Set) 類型的所有元素都是整數且數量不多時使用(保證元素不重復)。

結構:?一塊連續內存。

  • <encoding>: 4 字節,指定元素類型 (INTSET_ENC_INT16,?INT32,?INT64)。

  • <length>: 4 字節,元素數量。

  • <contents>: 按值大小升序排列的整數數組,類型由 encoding 決定。

特點:

  • 內存效率極高。

  • 插入新元素可能導致升級 (upgrade):如果新元素超出當前 encoding 的范圍,則將整個集合升級到更大的 encoding (如 INT16 -> INT32),重新分配內存并遷移數據。降級不支持

1.8?快速列表 (QuickList) -?Redis 3.2 引入

用途:?列表 (List) 類型的默認底層實現、發布與訂閱、慢查詢、監視器等功能。

設計目標:?平衡內存效率和操作性能,替代早期僅使用 ZipList 或 LinkedList 的方案。

結構:?一個由 ZipList (或 Listpack) 構成的雙向鏈表。

typedef struct quicklist {quicklistNode *head;quicklistNode *tail;unsigned long count;        // 所有節點內元素總數unsigned long len;          // quicklistNode 節點數量,即ziplist的個數int fill: QL_FILL_BITS;     // 單個節點最大容量 (ziplist大小限定,由 list-max-ziplist-size 配置)unsigned int compress: QL_COMP_BITS; // 兩端不壓縮的節點數 (節點壓縮深度設置,由 list-compress-depth 配置)...
} quicklist;typedef struct quicklistNode {struct quicklistNode *prev;    // 指向上一個ziplist節點struct quicklistNode *next;    // 指向下一個ziplist節點unsigned char *zl;          // 指向底層 ZipList 或 Listpack (Redis 7.0+)unsigned int sz;            // zl 指向的 ZipList/Listpack 的字節大小unsigned int count: 16;     // 該節點內元素個數unsigned int encoding: 2;   // 編碼方式:1--ziplist,2--quicklistLZF壓縮unsigned int container: 2;  // 容器類型(存放數據方式):NONE, ZIPLIST, LISTPACK (Redis 7.0+)unsigned int recompress: 1; // 是否被壓縮過 (臨時狀態)...
} quicklistNode;

工作原理:

  • 每個?quicklistNode?節點包含一個 ZipList 或 Listpack。每個ZipList(或Listpack)都能存儲多個元素。

  • fill?參數控制單個節點最大元素數或大小。超過限制時分裂節點。

  • compress?參數控制兩端不壓縮的節點數。中間節點可使用 LZF 壓縮節省內存。

  • 插入/刪除操作盡量在節點內部的 ZipList/Listpack 完成。節點過大時分裂,過小時合并相鄰節點。

優點:?綜合了雙向鏈表 (易于兩端操作,節點分裂/合并) 和 ZipList/Listpack (內存局部性好,小數據高效) 的優勢,并通過壓縮進一步節省內存。

2、對象系統(RedisObject)

Redis 使用?redisObject?結構體來統一表示數據庫中的所有值對象 (Value)。

2.1 結構信息概覽

typedef struct redisObject {unsigned type:4;      // 對象類型 (REDIS_STRING, REDIS_LIST, REDIS_HASH, REDIS_SET, REDIS_ZSET)unsigned encoding:4;  // 底層數據結構編碼 (如 REDIS_ENCODING_INT, REDIS_ENCODING_HT, REDIS_ENCODING_ZIPLIST...)unsigned lru:LRU_BITS; // LRU 時間戳 (或 LFU 計數與時間) - 用于內存淘汰int refcount;          // 引用計數 - 用于內存回收 (垃圾回收)void *ptr;            // 指向底層實現數據結構的指針 (SDS, dict, quicklist, zset...)
} robj;

1> 4位type

對象類型:REDIS_STRING(字符串)REDIS_LIST (列表)REDIS_HASH(哈希)REDIS_SET(集合)REDIS_ZSET(有序集合)

當執行type命令時,便是讀取RedisObject的type字段獲取對象類型(type key)。

2> 4位encoding:查看對象編碼方式

3> 24位lru:lru記錄的是對象最后一次被命令程序訪問的時間。高16位存儲最后被訪問時間(分鐘級),低8位存儲最近訪問次數。

4> refcount:記錄對象被引用次數。對象創建時?refcount=1,被新程序使用時?+1,不再使用時?-1。當?refcount==0?時,對象占用的內存被回收。

5> ptr:指向具體的數據,比如:set hello worldptr 指向包含字符串 world SDS

2.2 核心作用

  • 多態性:?相同類型的值對象 (type) 可以根據不同條件使用不同的底層數據結構 (encoding)。命令的實現只需關注?type?和?encoding,調用對應的底層操作函數。

  • 內存管理:?refcount?實現引用計數垃圾回收機制。lru?記錄對象訪問信息,支撐 LRU/LFU 內存淘汰策略。

  • 共享對象:?引用計數允許共享對象 (如小整數?0-9999),節省內存。

2.3 類型與編碼映射

2.3.1?字符串 (String)
  • REDIS_ENCODING_INT: 整數值 (直接用?ptr?存儲,ptr?被強制轉換為?long)。

  • REDIS_ENCODING_EMBSTR: 短字符串 (<=44字節,Redis 3.2+),redisObject?和?SDS?分配在連續內存。

  • REDIS_ENCODING_RAW: 長字符串,動態?SDS

2.3.2?列表 (List)
  • REDIS_ENCODING_QUICKLIST: 默認實現 (QuickList)。

  • (歷史)?REDIS_ENCODING_ZIPLIST?/?REDIS_ENCODING_LINKEDLIST

2.3.3?哈希 (Hash)
  • REDIS_ENCODING_LISTPACK: 小哈希 (字段數/值大小未超配置閾值)。

  • REDIS_ENCODING_HT: 大哈希 (字典)。

2.3.4?集合 (Set)
  • REDIS_ENCODING_INTSET: 小整數集合。

  • REDIS_ENCODING_HT: 大集合或包含非整數元素 (字典,值設為 NULL)。

2.3.5?有序集合 (Sorted Set)
  • REDIS_ENCODING_LISTPACK: 小有序集合 (元素數/值大小未超閾值)。

  • REDIS_ENCODING_SKIPLIST: 大有序集合 (跳躍表 + 字典)。字典提供 O(1) 成員到分值的查找,跳躍表提供按分值排序和范圍操作。兩者共享元素和分值。

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

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

相關文章

【項目實訓】【項目博客#07】HarmonySmartCodingSystem系統前端開發技術詳解(5.12-6.15)

【項目實訓】【項目博客#07】HarmonySmartCodingSystem系統前端開發技術詳解&#xff08;5.12-6.15&#xff09; 一、項目概述與目標 HarmonySmartCodingSystem是一個面向HarmonyOS開發者的智能編碼輔助平臺&#xff0c;旨在通過自然語言交互簡化開發流程&#xff0c;提供智能…

系統性能優化-2 CPU

系統性能優化-2 CPU 其實除了 CPU 的頻率&#xff0c;多核架構以及多 CPU 架構對系統運行的性能也是很大影響的&#xff0c;那么該如何充分利用 CPU 呢&#xff1f; CPU 架構 首先介紹一下當前主流的 CPU 架構&#xff0c;現在的系統基本都是多 CPU&#xff0c;一個 CPU 處理…

Docker Pull 相關配置指南

在Docker環境中&#xff0c;docker pull命令用于從Docker鏡像倉庫拉取鏡像。為了確保Docker鏡像能夠快速、穩定地拉取&#xff0c;配置 docker pull相關的設置是非常重要的。本文將詳細介紹如何配置Docker以優化 docker pull操作&#xff0c;涵蓋鏡像源配置、登錄私有倉庫、網絡…

Python的Matplotlib庫:從入門到精通的數據可視化實戰指南

&#x1f49d;&#x1f49d;&#x1f49d;歡迎蒞臨我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 持續學習&#xff0c;不斷…

CentOS查日志

在 CentOS 系統中&#xff0c;查看日志是系統維護和故障排查的重要技能。以下是常用的日志查看方法和工具&#xff1a; 1. 基本日志位置 CentOS 使用systemd管理服務&#xff0c;主要日志存儲在&#xff1a; /var/log/messages&#xff1a;系統主日志/var/log/secure&#x…

Linux運維新人自用筆記(用虛擬機Ubuntu部署lamp環境,搭建WordPress博客)

內容全為個人理解和自查資料梳理&#xff0c;歡迎各位大神指點&#xff01; 每天學習較為零散。 day20 一、./configure 腳本命令 ./configure 是 Unix/Linux 系統中用于配置軟件源代碼的腳本命令&#xff0c;通常用于為后續的 make 和 make install 準備編譯環境。 選項作…

JetBrains 2025 全家桶 包含 IDEA、WebStorm、DataGrip、Pycharm、CLion、GoLand、PhpStorm

JetBrains 2025 全家桶 11合1 包含&#xff1a;IDEA、WebStorm、DataSpell、DataGrip、Pycharm、RustRover、CLion、Rider、PhpStorm、RubyMine、GoLand。 原文地址&#xff1a;JetBrains 2025 全家桶 11合1 含 IDEA、PyCharm、DataGrip、WebStrom、GoLand、CLion、PhpStorm、D…

【一手實測】字節豆包 1.6 + Trae + 火山 MCP + FaaS:AI云原生 Agent 開發部署全流程體驗!

原創 Aitrainee AI進修生 2025年06月13日 16:42 湖南 標題已修改 緣起 —— 火山引擎在 2025 原動力大會上&#xff0c;也端出了自家的豆包大模型&#xff1a;Doubao-Seed-1.6 系列。 這三兄弟都支持文本、圖片、視頻輸入&#xff0c;都帶著 256K 的長上下文。 Doubao-Seed-…

Vulkan學習筆記8—頂點輸入描述與頂點緩沖

一、著色器代碼更新及構建時自動編譯著色器腳本 用內存中的頂點緩沖區替換頂點著色器中硬編碼的頂點數據 之前的頂點著色器&#xff1a; #version 450layout(location 0) out vec3 fragColor;// 頂點數據硬編碼 vec2 positions[3] vec2[](vec2(0.0, -0.5),vec2(0.5, 0.5),…

Day04_數據結構(棧鏈棧循環隊列)

01.棧 main.c #include "stack.h" int main() { stack_p S(stack_p)create_stack(); //1.入棧 …

PyTorch 的 CUDA GPU 支持 · 安裝五條鐵律(最新版 2025 修訂)(適用于所有用戶)

相關參考資料&#xff08;往期博客&#xff09;&#xff1a; 是否需要預先安裝 CUDA Toolkit&#xff1f;——按使用場景分級推薦及進階說明-CSDN博客 太方便&#xff0c;WIN系統CUDA12.4下使用conda便捷管理虛擬環境中的不同版本的CUDA、cuDNN、PyTorch-CSDN博客 好消息&#…

Django構建簡易視頻編輯管理系統

Django構建簡易視頻編輯管理系統 以下是基于Django構建簡易視頻編輯管理系統的可運行代碼框架&#xff0c;包含核心功能模塊和實現邏輯。該系統支持視頻上傳、基本剪輯操作和管理功能。 環境準備 安裝必要依賴包&#xff1a; pip install django pillow moviepy django-cri…

Java求職者面試題詳解:計算機網絡、操作系統、設計模式與數據結構

Java求職者面試題詳解&#xff1a;計算機網絡、操作系統、設計模式與數據結構 第一輪&#xff1a;基礎概念問題 1. 請解釋TCP和UDP的區別。 2. 什么是操作系統&#xff1f;它的主要功能是什么&#xff1f; 3. 請解釋設計模式中的單例模式&#xff0c;并給出一個實際應用的例…

【mysql】docker運行mysql8.0

背景 mariadb10.5.8報錯&#xff1a;Error 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘LIMIT ?’ at line 1 所以更換為mysql8.0.39試試 docker run啟動…

C#實現語音預處理:降噪/靜音檢測/自動增益

無論是在音視頻錄制系統&#xff0c;還是音視頻通話系統、或視頻會議系統中&#xff0c;對從麥克風采集到的說話的聲音數據進行預處理&#xff0c;都是是非常必要的。 語音數據預處理主要包括&#xff1a;??降噪&#xff08;Noise Reduction&#xff09;、靜音檢測&#xff0…

組合模式Composite Pattern

模式定義 又稱整體-部分模式 組合多個對象形成 樹形結構 以表示“整體-部分”的結構層次 組合模式對單個對象&#xff08;即葉子對象&#xff09;和組合對象&#xff08;即容器對象&#xff09;的使用具有一致性對象結構型模式 模式結構 Component&#xff1a;抽象構件Leaf&a…

商代大模型:智能重構下的文明曙光與青銅密碼

引言&#xff1a;技術奇點的歷史想象 在人類文明的長河中&#xff0c;技術的進步始終是推動社會變革的核心動力。從青銅冶煉到文字發明&#xff0c;從農業革命到工業革命&#xff0c;每一次技術飛躍都重塑了人類對世界的認知與生存方式。而如今&#xff0c;人工智能的崛起正以…

【Python】python系列之函數作用域

Python 系列文章學習記錄&#xff1a; Python系列之Windows環境安裝配置_開著拖拉機回家的博客-CSDN博客 Python系列之變量和運算符_開著拖拉機回家的博客-CSDN博客 Python系列之判斷和循環_開著拖拉機回家的博客-CSDN博客 Python系列之字符串和列表_開著拖拉機回家的博客…

Unity UI 核心類解析之Graphic

&#x1f9f1; Unity UI 核心類解析&#xff1a;Graphic 類詳解 一、什么是 Graphic&#xff1f; 在 Unity 的 UI 系統中&#xff0c;Graphic 是一個抽象基類&#xff0c;繼承自 UIBehaviour 并實現了 ICanvasElement 接口。它是所有可以被繪制到屏幕上的 UI 元素的基礎類。 …

【Elasticsearch】文檔遷移(Reindex)

文檔遷移 1.為什么要進行 reindex 操作2.Reindex 操作的本質3.實際案例3.1 同集群索引之間的全量數據遷移3.2 同集群索引之間基于特定條件的數據遷移3.2.1 源索引設置檢索條件3.2.2 基于 script 腳本的索引遷移3.2.3 基于預處理管道的數據遷移 3.3 不同集群之間的索引遷移3.4 查…