redis的zset數據結構底層淺析

最近在看老錢的《redis深度歷險》,裏面最後的章節介紹了zset的底層的數據結構,跳躍表。感覺這個跳躍表的設計非常好,在此記錄一下。有理解錯誤的地方,還請路過的大神不吝賜教
其實,Redis的zset結構使用的是hash加上跳躍表的設計
hash結構用來存儲value和score的關係
但是,zset可以根據score的範圍獲取value的列表,這個實現就要用到跳躍表的設計
跳躍表大概長下面這個樣子
以下圖片均借鑑自:https://www.cnblogs.com/thrillerz/p/4505550.html
在這裏插入圖片描述
跳躍表的底層其實也就是一個雙向的list結構。最下面一層是level1,然後往上是level2.如下圖
在這裏插入圖片描述

跳躍表的查詢操作
跳躍表其實是由雙向鏈表衍生出來的。我們先初始化一個有序的鏈表
在這裏插入圖片描述
如果我們想要找到[23,43,59]這三個元素。需要的比較次數分別是[2,4,6]。23這個元素需要經過2次比較。
1 .和14比較,大於14
2 .和23比較,等於23。找到了
43和59元素的查找順序同上
這樣的話,總的查找次數爲:2+4+6=12次。此時的複雜度爲:O(n)。
好了,跳躍表閃亮登場
我們可以在鏈表的個別元素上增加一層,作爲索引。
如下圖所示,我們將14、34、50、72提取出來作爲索引使用
在這裏插入圖片描述
此時我們再次查找23,43,59這三個元素
找23這個元素
1 .和14比較,大於14
2 .和34比較,比34小。從14的下一層開始找,和23比較,等於23.找到
比較次數:2次
找43這個元素
1 .和14比較,大於14
2 .和34比較,大於34
3 .和50比較,小於50,。從34的下一層開始找,比較43.等於43,找到了
比較次數:4次
找59這個元素
1 .和14比較,大於14
2 .和34比較,大於34
3 .和50比較,大於50。
4 .和72比較,小於72,。從50的下一層元素開始找。和59比較,等於59.找到
比較次數:5次。比單層鏈表的比較次數少了1次。性能提高了。
元素少了,不足以顯示跳躍表的優勢。redis的最高層有64層,大數據量時優勢非常明顯

跳躍表的新增操作

先得到一個隨機的層數,這個隨機的層數是純隨機。redis官方的zset結構,50%概率被分到第一層。
然後越往上,概率減半。所以redis的zset結構,相對來說,更加的扁平化。需要遍歷的次數比較多
我們得到隨機層數之後,在每一層都插入該元素。如果該層數高於最高層,就更新一下跳躍表的最高層數

跳躍表的刪除操作

先查詢到元素的位置,然後使用標準的鏈表刪除操作刪除元素。同時注意更新一下最高層數

跳躍表的更新操作

如果value值存在,此時只是更新一下score值即可。如果更新的score值並不會帶來排序上的變化,此時只更新一下score值即可。score是用來對跳躍表進行排序的依據。這裏說明一下,redis中對於value值的更新操作不是這麼做的,它是先刪除,然後再添加,中間一共經歷過2次查詢操作。所以,這個地方,應該是有優化的空間的。

我猜測,score值在跳躍表中的作用。就是用來做比較用的。我們插入一個元素,就要插入一個score值。然後根據score值決定元素的位置。
查找元素時,根據score值定位元素的位置,然後取得元素即可
每一個元素都會存儲一個跨度span值,代表當前節點到目標節點的跨度。這個跨度也就是RANK值
如果多個元素的score值相同,此時會再次比較value值的字節大小,根據value值的 字節大小進行排序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章