(一)跳躍表數組
跳躍表是一種有序的數據結構,它經過每一個節點中維持多個指向其餘節點的指針,從而達到快速訪問節點的目的。數據結構
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設計與實現》,僅在此作學習與你們分享。