redis有序集合資料結構

2021-10-19 08:58:33 字數 2508 閱讀 1796

zset資料結構類似於set結構,只是zset結構中,每個元素都會有乙個分值,然後所有元素按照分值的大小進行排列,相當於是乙個進行了排序的鍊錶。

如果zset是乙個鍊錶,而且內部元素是有序的,在進行元素插入和刪除,以及查詢的時候,就必須要遍歷鍊錶才行,時間複雜度就達到了o(n),這個在以單執行緒處理的redis中是不能接受的。所以zset採用了一種跳躍表的實現。這個實現有點類似於kafka儲存訊息是使用的稀疏索引,kafka這個相對較簡單,可以用來介紹模擬學習。

如果熟悉kafka,就知道kafka在進行持久化的時候,生成了兩個檔案,乙個是******x.log,乙個是******x.index,這其中log檔案中以鍊錶的形式儲存著訊息的詳細資訊,而index檔案中,則是儲存著這些訊息的索引,或者說偏移量,但又不是每一條訊息的索引都在index檔案中存在,而是稀疏的,比如log檔案中的訊息的索引從0-10000,那麼index檔案中儲存的索引可能是100, 500, 700, 1000, 5000, 6500,每乙個索引中都儲存著對應的log檔案中的訊息的具體位置,如圖:

當要訪問偏移量為899的這條訊息時,先去index檔案中查詢,找到了700和1000這個區間,根據700這個索引中的資訊,找到log檔案中700這條訊息的具體位置,然後順序往下查詢,直到找到索引為899的這條訊息為止。從這個實現中我們可以看到,kafka並沒有進行log檔案的整個遍歷,而是通過index中的稀疏索引,找到訊息在log中的大概位置,然後順序遍歷找到訊息,這樣就大大提高了查詢的效率,如圖:

redis的跳躍表和上面類似,只是更加複雜一些,kafka的稀疏索引只有一層,而redis的索引被提取為多層。如圖:

所有的元素都會在l0層的鍊錶中,根據分數進行排序,同時會有一部分節點有機會被抽取到l1層中,作為乙個稀疏索引,同樣l1層中的索引也有一定機會被抽取到l2層中,組成乙個更稀疏的索引列表。

下面用圖來演示一下在對快速鍊錶進行插入、刪除、查詢時,是如何定位到l0層中的具體位置的。

首先,假定有這麼乙個鍊錶,注意這裡只展示分數,而不展示具體的值了:

如果要查詢分數為66的元素,首先在l2層的索引找。很明顯,66位於25和85中間,這時就縮小了查詢區間:

然後根據獲得的區間,去l1對應的區間中查詢,得到乙個更精確的區間:

最終,根據這個更精確的區間,去l0層順序遍歷,即可得到要查詢的元素:

上述即是對redis的跳躍表的原理的乙個簡述。

這種跳躍表的實現,其實和二分查詢的思路有點接近,只是一方面因為二分查詢只能適用於陣列,而無法適用於鍊錶,所以為了讓鍊錶有二分查詢類似的效率,就以空間換時間來達到目的。

跳躍表因為是乙個根據分數權重進行排序的列表,可以再很多場景中進行應用,比如排行榜,搜尋排序等等。

新增元素,zadd zsetname score1 value1 score2 value2 score3 value3 .....

檢視所有元素,zrange zsetname 0 -1

檢視所有元素,按score逆序排列, zrevrange zsetname 0 -1

元素數量,zcard zsetname

獲取指定value的分數, zscore zsetname value

獲取指定value的排名,zrank zsetname value(從0開始)

獲取指定分值區間中的元素, zrangebyscore zsetname scorestart scoreend(包含上下區間)(注意inf表示無窮大,-inf表示服務券大)

獲取指定分值區間中的元素,並且返回分數, zrangebyscore zsetname scorestart scoreend withscores

刪除元素,zrem zsetname value

redis資料結構之有序集合

有序集合與集合大致差不多,不同的是有序集合中的元素可以排序,但與列表使用下標實現排序不一樣,有序集合利用分數作為依據排序。有序集合不能重複,但分數可以重複。對部落格 發布的文章做排行榜,榜單的維度可能是按時間 按照獲得讚數。比如使用讚數對使用者每天發布文章的排行榜,並實現以下功能 1 新增使用者讚數...

Redis 資料結構之有序集合(sort set)

有序集合 sortset的元素包括 score 分數,int float value 成員,string int float rank等三個屬性,1 實際上是score 和 value的對映 2 value 在有序集合中必須是唯一的,score可以重複 3 rank 從0 開始,score越大,ra...

Redis資料結構之有序集合sortedset

有序集合 sorted set 用於儲存多個字串元素,它是在集合 set 的基礎上給每個元素增加了乙個用於排序的字段 score 元素同樣不可重複,可以根據分數索引獲取元素,此外,提供了根據score獲取指定範圍以及排序功能 zadd 新增資料,返回元素個數 zadd key score1 memb...