redis資料結構---跳躍表
阿新 • • 發佈:2021-12-20
跳躍表(skiplist)是一種有序資料結構, 它通過在每個節點中維持多個指向其他節點的指標, 從而達到快速訪問節點的目的。
跳躍表支援平均O(\log N)最壞O(N)複雜度的節點查詢, 還可以通過順序性操作來批量處理節點。
跳躍表的實現
redis 的跳躍表由 zskiplistNode 和 zskiplist 兩個結構定義,zskiplistNode 結構用於表示跳躍表節點,zskiplist 結構則用於儲存跳躍表節點的相關資訊
跳躍表節點
typedef struct zskiplistNode { // 後退指標 struct zskiplistNode *backward;
// 分值 double score; // 成員物件 robj *obj; // 層 struct zskiplistLevel { // 前進指標 struct zskiplistNode *forward; // 跨度 unsigned int span; } level[]; } zskiplistNode;
- 層:跳躍表節點的 level 陣列可以包含多個元素, 每個元素都包含一個指向其他節點的指標, 程式可以通過這些層來加快訪問其他節點的速度, 一般來說, 層的數量越多, 訪問其他節點的速度就越快。每次建立一個新跳躍表節點的時候, 程式會隨機生成一個介於 1 和 32 之間的值作為 level 陣列的大小, 這個大小就是層的“高度”。
- 前進指標:用於從表頭向表尾方向訪問節點
- 跨度:用於記錄兩個節點之間的距離,兩個節點之間的跨度越大, 它們相距得就越遠。指向 NULL 的所有前進指標的跨度都為 0, 因為它們沒有連向任何節點。
- 後退指標:用於從表尾向表頭方向訪問節點:,跟可以一次跳過多個節點的前進指標不同, 因為每個節點只有一個後退指標, 所以每次只能後退至前一個節點。
- 分值:是一個 double 型別的浮點數, 跳躍表中的所有節點都按分值從小到大來排序。
- 成員:是一個指標, 它指向一個字串物件, 而字串物件則儲存著一個 SDS 值。
zskiplist結構
雖然僅靠多個跳躍表節點就可以組成一個跳躍表,但通過使用一個zskiplist結構來持有這些節點, 程式可以更方便地對整個跳躍表進行處理, 比如快速訪問跳躍表的表頭節點和表尾節點, 又或者快速地獲取跳躍表節點的數量(也即是跳躍表的長度)等資訊。
typedef struct zskiplist { // 表頭節點和表尾節點 struct zskiplistNode *header, *tail; // 表中節點的數量 unsigned long length; // 表中層數最大的節點的層數 int level; } zskiplist;
跳錶建立過程
跳錶查詢過程
本文參考《Redis設計與實現》(感覺書上的圖不太好理解,自己從網上找的圖)