Redis學習筆記(四) 跳躍表與整數集合

(一)跳躍表數組

跳躍表是一種有序的數據結構,它經過每一個節點中維持多個指向其餘節點的指針,從而達到快速訪問節點的目的。數據結構

Redis使用跳躍表做爲有序集合鍵的底層實現之一,若是一個有序集合包含的元素數量比較多,或者有序集合中元素的成員是比較長的字符串時,Redis就會使用跳躍表做爲有序集合鍵的底層實現。學習

Redis中的兩個地方用到了跳躍表,一個是實現有序集合鍵,另外一個是在集羣節點中用做內部數據結構。ui

Redis的跳躍表由zskiplistNode 與 zskiplist 兩個結構定義。其中zskiplistNode 結構用於標識跳躍表節點,zskiplist結構用於保存跳躍表節點的相關信息(表頭、表尾節點、節點數量等)。編碼

 

zskiplistNodespa

typedef struct zskiplistNode{
  //
  struct zskiplistLevel{
    struct zskiplistNode *forward;//前進指針
    unsigned int span;//跨度
  } level[];
  //後退指針
  struct zskiplistNode *backward;
  //分值
  double score;
  //成員對象
  robj *obj;
}

中包含多個元素,每一個元素是指向其餘節點的指針,經過這些層能夠加快訪問其餘節點的速度,層越多,訪問其餘節點的速度越快。沒增長一個跳躍節點,程序根據冪次定律(越大的數出現機率越小)生成1-32之間的值做爲層高。設計

一、每層都有一個指向表尾方向的前進指針,做爲表頭向表尾方向訪問節點。指針

二、層中的跨度用於記錄兩個節點之間的距離。code

三、後退指針則只能一次跨1個節點進行訪問。對象

四、跳躍表的排序是按照全部節點的分值來排序的。

五、節點中的對象則是保存了一個SDS的字符串。

六、同一個跳躍表的對象必須惟一,但分值能夠重複。(相同分數,成員小的靠前排)。

跳躍表zskiplist

typedef struct zskiplist{
    struct skiplistNode *header,*tail;//表頭節點與表尾節點
    unsigned long length;//表中節點的數量
    int level;//表中層數最大的節點的層數(表頭不計算在內)
} zskiplist;

 

(二)整數集合

整數集合是集合鍵的底層實現之一,當一個集合只包含整數值元素,而且集合的元素數量很少時,Redis就會使用整數集合做爲集合鍵的底層實現,而且保證集合中不會出現重複元素。

intset

typedef struct intset{
    uint32_t encoding;//編碼方式
    uint32_t length;//集合包含的元素數量。
    int8_t contents[];//保存元素的數組 
} intset;

contents數組是這個數集合的底層實現:整數集合的每一個元素都是contents數組的一個數組項,各個項的數組中按值的大小從小到大有序地排列,而且數組中不包含任何重複項。

 

升級

當咱們要將一個新元素添加到整數集合裏面時,而且新元素類型比整數集合現有的全部元素類型都長時,整數集合須要先進性升級,而後才能將新的元素添加到整數集合中。

一、根據新元素的類型,擴展整數集合底層數組的空間大小,併爲新元素分配空間。

二、將底層數組現有的全部元素都轉換爲與新元素相同的類型,並將類型轉換後的元素放置到正確位置上,並且在放置元素過程當中,須要繼續維持底層數組的有序性質不變。

三、將新元素添加到底層數組裏面。

四、修改整數集合encoding屬性。

由於每次向整數集合添加新元素都有可能引發升級,而每次升級都須要將底層數組中已有的全部元素進行類型轉換,因此向整數集合中添加新元素的時間複雜度爲O(N);

 

---- end ----

天天學一點,總會有收穫。

說明:尊重做者知識產權,文中內容參考《Redis設計與實現》,僅在此作學習與你們分享。

 

 

相關文章
相關標籤/搜索