redis數據結構介紹二-第二部分 跳錶

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)redis

本文做者: Nicksxs數組

建立時間: 2020年01月04日數據結構

本文連接: redis數據結構介紹二-第二部分 跳錶dom

跳錶 skiplist

跳錶是個在咱們平常的代碼中不太經常使用到的數據結構,相對來說就沒有像數組,鏈表,字典,散列,樹等結構那麼熟悉,因此就從頭開始分析下,首先是鏈表,跳錶跟鏈表都有個表字(太硬扯了我🤦‍♀️),注意這是個有序鏈表

如上圖,在這個鏈表裏若是我要找到 23,是否是我須要從3,5,9開始一直日後找直到找到 23,也就是說時間複雜度是 O(N),N 的一次冪複雜度,那麼咱們來看看第二個

這個結構跟原先有點不同,它給鏈表中偶數位的節點又加了一個指針把它們連接起來,這樣子當咱們要尋找 23 的時候就能夠從原來的一個個往下找變成跳着找,先找到 5,而後是 10,接着是 19,而後是 28,這時候發現 28 比 23 大了,那我在退回到 19,而後從下一層原來的鏈表往前找,

這裏毛估估是否是前面的節點我就少找了一半,有那麼點二分法的意思。
前面的實際上是跳錶的引子,真正的跳錶其實不是這樣,由於上面的其實有個比較大的問題,就是插入一個元素後須要調整每一個元素的指針,在 redis 中的跳錶實際上是作了個隨機層數的優化,由於沿着前面的例子,其實當數據量很大的時候,是否是層數越多,其查詢效率越高,可是隨着層數變多,要保持這種嚴格的層數規則其實也會增大處理複雜度,因此 redis 插入每一個元素的時候都是使用隨機的方式,看一眼代碼優化

/* ZSETs use a specialized version of Skiplists */
typedef struct zskiplistNode {
    sds ele;
    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;

typedef struct zset {
    dict *dict;
    zskiplist *zsl;
} zset;

忘了說了,redis 是把 skiplist 跳錶用在 zset 裏,zset 是個有序的集合,能夠看到 zskiplist 就是個跳錶的結構,裏面用 header 保存跳錶的表頭,tail 保存表尾,還有長度和最大層級,具體的跳錶節點元素使用 zskiplistNode 表示,裏面包含了 sds 類型的元素值,double 類型的分值,用來排序,一個 backward 後向指針和一個 zskiplistLevel 數組,每一個 level 包含了一個前向指針,和一個 span,span 表示的是跳錶前向指針的跨度,這裏再補充一點,前面說了爲了靈活這個跳錶的新增修改,redis 使用了隨機層高的方式插入新節點,可是若是全部節點都隨機到很高的層級或者全部都很低的話,跳錶的效率優點就會減少,因此 redis 使用了個小技巧,貼下代碼spa

#define ZSKIPLIST_P 0.25      /* Skiplist P = 1/4 */
int zslRandomLevel(void) {
    int level = 1;
    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
        level += 1;
    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

當隨機值跟0xFFFF進行與操做小於ZSKIPLIST_P * 0xFFFF時纔會增大 level 的值,所以保持了一個相對遞減的機率
能夠簡單分析下,當 random() 的值小於 0xFFFF 的 1/4,纔會 level + 1,就意味着當有 1 - 1/4也就是3/4的機率是直接跳出,因此一層的機率是3/4,也就是 1-P,二層的機率是 P(1-P),三層的機率是 P² (1-P) 依次遞推。指針

相關文章
相關標籤/搜索