1. 程式人生 > 其它 >跳躍表 -《Redis設計與實現》讀書筆記

跳躍表 -《Redis設計與實現》讀書筆記

使用場景

  1. 當有序集合包含的元素數量比較多 或者 有序集合中元素的成員是比較長的字串時,使用跳躍表實現有序集合
  2. 叢集節點中用作內部資料結構

定義

// 跳躍表節點
typedef struct zskiplistNode {
    // 成員物件:一個SDS值
    // 在同一個跳躍表中,各個節點儲存的成員物件必須是唯一的,但是多個節點儲存的分值卻可以是相同的
    // 分值相同的節點將按照成員物件在字典序中的大小來進行排序,成員物件較小的節點會排在前面(靠近表頭的方向),而成員物件較大的節點則會排在後面(靠近表尾的方向)
    sds ele;

    // 分值
    // 跳躍表中的所有節點都按分值從小到大排序
    double score;

    // 後退指標:用於從表尾向表頭方向訪問節點
    // 每次只能後退至前一個節點
    struct zskiplistNode *backward;

    // 層陣列可以包含多個元素,每個元素都包含一個指向其他節點的指標
    // 層可以加快訪問其他節點的速度,一般來說,層的數量越多,訪問其他節點的資料越快
    // 每次建立一個新跳躍表節點的時候,根據冪次定律(越大的數出現的概率越小)隨機生成一個介於1和32之間的值作為level陣列的大小
    struct zskiplistLevel {
        // 前進指標:用於從表頭向表尾方向訪問節點
        struct zskiplistNode *forward;

        // 跨度:記錄前進指標所指向節點和當前節點的距離
        // 兩個節點之間的跨度越大,相距得就越遠
        // 由於指向null的所有前進指標沒有連向任何節點,所以跨度都為0
        // 跨度用來計算排位(rank)
        unsigned long span;
    } level[];

} zskiplistNode;

// 跳躍表
typedef struct zskiplist {
    // 指向跳躍表的表頭節點:表頭節點的後退指標、分值和成員物件屬性都不會被用到,僅用到層屬性
    // 指向跳躍表的表尾節點
    struct zskiplistNode *header, *tail;

    // 跳躍表內節點的數量
    unsigned long length;

    // 跳躍表內層數最大的那個節點的層數(表頭節點的層數不算)
    int level;

} zskiplist;

原始碼閱讀

  1. 檔案:src/server.h、src/t_zset.c、src/sort.c
隻言片語任我說,提筆句句無需忖。落筆不知寄何人,唯有邀友共斟酌。