上篇介紹了 SDS、雙向鏈表、字典。本文續講 Redis 另外三大核心結構:跳躍表(有序集合)、整數集合(小整數集合)、壓縮列表(列表/哈希底層),幫助你在選擇資料型別時做出正確決策。
跳躍表是一種有序、隨機化的多層鏈表,查找/插入/刪除皆為 O(log N) 期望時間,實現遠比平衡樹簡單。Redis 僅在兩處使用:有序集合鍵與叢集節點內部結構。
zskiplistNodetypedef struct zskiplistNode {
struct zskiplistLevel { // 層
struct zskiplistNode *forward; // 前進指標
unsigned int span; // 跨度(節點間距離)
} level[];
struct zskiplistNode *backward; // 後退指標
double score; // 分值(排序依據)
robj *obj; // 成員物件(SDS 字串)
} zskiplistNode;
ZRANK)。zskiplisttypedef struct zskiplist {
struct zskiplistNode *header, *tail; // 表頭/表尾
unsigned long length; // 節點總數
int level; // 最大層數
} zskiplist;
當集合只含整數且元素數量較少時,Redis 使用 intset 作為集合鍵底層實現。
typedef struct intset {
uint32_t encoding; // 編碼方式:INT16/INT32/INT64
uint32_t length; // 元素數量
int8_t contents[]; // 實際儲存陣列(型別由 encoding 決定)
} intset;
新增元素超出當前編碼範圍時,自動升級:
優點:提升靈活性、節省記憶體(小整數用 INT16)。只升不降,避免頻繁轉換開銷。
列表鍵或哈希鍵元素較少、且值為小整數或短字串時使用,極度節省記憶體。
+--------+--------+--------+--------+--------+--------+------+
| zlbytes| zltail | zllen | entry1 | entry2 | ... | zlend|
+--------+--------+--------+--------+--------+--------+------+
zlbytes:總佔用位元組數zltail:尾節點偏移量(O(1) 尾部操作)zllen:節點數entryX:節點內容(字串或整數,緊湊編碼)zlend:結束標記 0xFF插入/刪除節點可能導致後續節點zltail、zlbytes 需調整,極端情況觸發連鎖更新(O(N²)),但實際觸發機率極低。
| 結構 | 用途 | 特點 |
|---|---|---|
| 跳躍表 | 有序集合、叢集節點 | 有序、O(log N)、多層索引、支援排名/範圍查詢 |
| 整數集合 | 小整數集合 | 緊湊陣列、自動升級、只升不降、節省記憶體 |
| 壓縮列表 | 列表/哈希(小數據) | 連續記憶體、緊湊編碼、O(1) 尾部操作、可能連鎖更新 |
理解底層結構,才能根據數據特徵選擇最佳 Redis 資料型別,避免記憶體浪費與效能瓶頸。