日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Rediszset有序集合(底層原理+圖解)
顧名思義,Redis zset(有序集合)中的成員是有序排列的,它和 set 集合的相同之處在于,集合中的每一個成員都是字符串類型,并且不允許重復;而它們最大區(qū)別是,有序集合是有序的,set 是無序的,這是因為有序集合中每個成員都會關聯(lián)一個 double(雙精度浮點數(shù))類型的 score (分數(shù)值),Redis 正是通過 score 實現(xiàn)了對集合成員的排序。

網(wǎng)站建設哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、小程序開發(fā)、集團企業(yè)網(wǎng)站建設等服務項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了遵化免費建站歡迎大家使用!

zset 是 Redis 常用數(shù)據(jù)類型之一,它適用于排行榜類型的業(yè)務場景,比如 QQ 音樂排行榜、用戶貢獻榜等。在音樂排行榜單中,我們可以將歌曲的點擊次數(shù)作為 score 值,把歌曲的名字作為 value 值,通過對 score 排序就可以得出歌曲“熱度榜單”。

Redis 使用以下命令創(chuàng)建一個有序集合:

127.0.0.1:6379> ZADD key score member [score member ...]  

key:指定一個鍵名;

score:分數(shù)值,用來描述  member,它是實現(xiàn)排序的關鍵;

member:要添加的成員(元素)。

當 key 不存在時,將會創(chuàng)建一個新的有序集合,并把分數(shù)/成員(score/member)添加到有序集合中;當 key 存在時,但 key 并非 zset 類型,此時就不能完成添加成員的操作,同時會返回一個錯誤提示。

注意:在有序集合中,成員是唯一存在的,但是分數(shù)(score)卻可以重復。有序集合的最大的成員數(shù)為 2^32 - 1 (大約 40 多億個)。

認識有序集合

1) 壓縮列表

有序集合(zset)同樣使用了兩種不同的存儲結構,分別是 zipList(壓縮列表)和 skipList(跳躍列表),當 zset 滿足以下條件時使用壓縮列表:

  • 成員的數(shù)量小于128 個;
  • 每個 member (成員)的字符串長度都小于 64 個字節(jié)。

下面對壓縮列表做簡單介紹,它由以下五部分組成,如圖所示:

上述每一部分在內存中都是緊密相鄰的,并承擔著不同的作用,介紹如下:

  • zlbytes 是一個無符號整數(shù),表示當前 ziplist 占用的總字節(jié)數(shù);
  • zltail 指的是壓縮列表尾部元素相對于壓縮列表起始元素的偏移量。
  • zllen 指 ziplist 中 entry 的數(shù)量。當 zllen 比2^16 - 2大時,需要完全遍歷 entry 列表來獲取 entry 的總數(shù)目。
  • entry 用來存放具體的數(shù)據(jù)項(score和member),長度不定,可以是字節(jié)數(shù)組或整數(shù),entry 會根據(jù)成員的數(shù)量自動擴容。
  • zlend 是一個單字節(jié)的特殊值,等于 255,起到標識 ziplist 內存結束點的作用。

下面執(zhí)行
ZADD命令添加兩個成員:xh(小紅) 的工資是 3500.0;xm(小明) 的工資是 3200.0。

ZADD salary 3500.0 xh 3200.0 xm

上述成員在壓縮列表中的布局,如下所示:

當 zset 使用壓縮列表保存數(shù)據(jù)時,entry 的第一個節(jié)點保存 member,第二個節(jié)點保存 score。依次類推,集合中的所有成員最終會按照 score 從小到大排列。

2) 跳躍列表

當有序結合不滿足使用壓縮列表的條件時,就會使用 skipList 結構來存儲數(shù)據(jù)。

跳躍列表(skipList)又稱“跳表”是一種基于鏈表實現(xiàn)的隨機化數(shù)據(jù)結構,其插入、刪除、查找的時間復雜度均為 O(logN)。從名字可以看出“跳躍列表”,并不同于一般的普通鏈表,它的結構較為復雜,本節(jié)只對它做淺顯的介紹,如有興趣可自行研究。

在 Redis 中一個 skipList 節(jié)點最高可以達到 64 層,一個“跳表”中最多可以存儲 2^64 個元素,每個節(jié)點都是一個 skiplistNode(跳表節(jié)點)。skipList 的結構體定義如下:

typedf struct zskiplist{
    //頭節(jié)點
    struct zskiplistNode *header;
    //尾節(jié)點
    struct zskiplistNode *tail;
    // 跳表中的元素個數(shù)
    unsigned long length;
    //表內節(jié)點的最大層數(shù)
    int level;
}zskiplist;
  • header:指向 skiplist 的頭節(jié)點指針,通過它可以直接找到跳表的頭節(jié)點,時間復雜度為 O(1);
  • tail:指向 skiplist 的尾節(jié)點指針,通過它可以直接找到跳表的尾節(jié)點,時間復雜度為 O(1);
  • length:記錄 skiplist 的長度,也就跳表中有多少個元素,但不包括頭節(jié)點;
  • level:記錄當前跳表內所有節(jié)點中的最大層數(shù)(level);

跳躍列表的每一層都是一個有序的鏈表,鏈表中每個節(jié)點都包含兩個指針,一個指向同一層的下了一個節(jié)點,另一個指向下一層的同一個節(jié)點。最低層的鏈表將包含 zset 中的所有元素。如果說一個元素出現(xiàn)在了某一層,那么低于該層的所有層都將包含這個元素,也就說高層是底層的子集。 

通過以下示意圖進一步認識 skiplist 結構。下圖是一個上下共四層的跳躍列表結構:



圖1:跳躍列表示意圖

 

跳躍列表中的每個節(jié)點都存儲著 S:V(即 score/value),示意圖顯示了使用跳躍列表查找 S:V 節(jié)點的過程。跳躍列表的層數(shù)由高到低依次排列,最低層是 L0 層,最高層是 L3 層,共有 4 層。

圖 1 所示,首先從最高層開始遍歷找到第一個
S:V節(jié)點,然后從此節(jié)點開始,逐層下降,通過遍歷的方式找出每一層的 S:V 節(jié)點,直至降至最底層(L0)才停止。在這個過程中找到所有 S:V 節(jié)點被稱為期望的節(jié)點。跳躍列表把上述搜索一系列期望節(jié)點的過程稱為“搜索路徑”,這個“搜索路徑”由搜索到的每一層的期望節(jié)點組成,其本質是一個列表。

常用命令匯總

有序集合常用命令
命令 說明
ZADD key score1 member1 [score2 member2] 用于將一個或多個成員添加到有序集合中,或者更新已存在成員的 score 值
ZCARD key 獲取有序集合中成員的數(shù)量
ZCOUNT key min max 用于統(tǒng)計有序集合中指定 score 值范圍內的元素個數(shù)。
ZINCRBY key increment member 用于增加有序集合中成員的分值。
ZINTERSTORE destination numkeys key [key ...] 求兩個或者多個有序集合的交集,并將所得結果存儲在新的 key 中。
ZLEXCOUNT key min max 當成員分數(shù)相同時,計算有序集合中在指定詞典范圍內的成員的數(shù)量。
ZRANGE key start stop [WITHSCORES] 返回有序集合中指定索引區(qū)間內的成員數(shù)量。
ZRANGEBYLEX key min max [LIMIT offset count] 返回有序集中指定字典區(qū)間內的成員數(shù)量。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 返回有序集合中指定分數(shù)區(qū)間內的成員。
ZRANK key member 返回有序集合中指定成員的排名。
ZREM key member [member ...] 移除有序集合中的一個或多個成員。
ZREMRANGEBYLEX key min max 移除有序集合中指定字典區(qū)間的所有成員。
ZREMRANGEBYRANK key start stop 移除有序集合中指定排名區(qū)間內的所有成員。
ZREMRANGEBYSCORE key min max 移除有序集合中指定分數(shù)區(qū)間內的所有成員。
ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定區(qū)間內的成員,通過索引,分數(shù)從高到低。
ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分數(shù)區(qū)間內的成員,分數(shù)從高到低排序。
ZREVRANK key member 返回有序集合中指定成員的排名,有序集成員按分數(shù)值遞減(從大到小)排序。
ZSCORE key member 返回有序集中,指定成員的分數(shù)值。
ZUNIONSTORE destination numkeys key [key ...] 求兩個或多個有序集合的并集,并將返回結果存儲在新的 key 中。
ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成員和元素分值)。

基本命令演示

下面通過一組命令,讓我們熟悉如何操作 zset 數(shù)據(jù)類型。以下示例是一個保存了員工薪水的有序集合:

#在有序集合中添加一個成員
127.0.0.1:6379> ZADD salary 4000 lucy
(integer) 1
#同時添加多個成員
127.0.0.1:6379> ZADD salary 5000 tom 6000 Helen 6500.50 Jack 3000 Smith
(integer) 4
#查詢指定區(qū)間上的元素
127.0.0.1:6379> ZRANGE salary 0 4
1) "Smith"
2) "lucy"
3) "tom"
4) "Helen"
5) "Jack"
#降序查看指定區(qū)間上的元素
127.0.0.1:6379> ZREVRANGE salary 0 4
1) "Jack"
2) "Helen"
3) "tom"
4) "lucy"
5) "Smith"
#查看指定元素的分值
127.0.0.1:6379> ZSCORE salary lucy
"4000"
#查看所有元素和分值
127.0.0.1:6379> ZRANGE salary 0 4 WITHSCORES
1) "Smith"
2) "3000"
3) "lucy"
4) "4000"
5) "tom"
6) "5000"
7) "Helen"
8) "6000"
9) "Jack"
10) "6500.5"
#統(tǒng)計指定工資范圍內的元素個數(shù)3000<=score<=5000
127.0.0.1:6379> ZCOUNT salary 3000 5000
(integer) 3
#表示3000 ZCOUNT salary (3000 (5000
(integer) 1
#返回指定工資范圍內的score和成員,限制條件是跳過1個元素,返回2個元素。
127.0.0.1:6379> ZRANGEBYSCORE salary 3000 6000 WITHSCORES LIMIT 1 2
1) "lucy"
2) "4000"
3) "tom"
4) "5000"
#查看有序集合在指定字典區(qū)間內的成員的數(shù)
#其中 - 表示最小值,而 + 則表示最大值
127.0.0.1:6379> ZLEXCOUNT salary - +
(integer) 5

在線練習工具:https://try.redis.io/

查看更多命令:https://redis.io/commands


文章題目:Rediszset有序集合(底層原理+圖解)
轉載源于:http://www.5511xx.com/article/coghhep.html