新聞中心

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了遵化免費(fèi)建站歡迎大家使用!
zset 是 Redis 常用數(shù)據(jù)類型之一,它適用于排行榜類型的業(yè)務(wù)場景,比如 QQ 音樂排行榜、用戶貢獻(xiàn)榜等。在音樂排行榜單中,我們可以將歌曲的點(diǎn)擊次數(shù)作為 score 值,把歌曲的名字作為 value 值,通過對(duì) score 排序就可以得出歌曲“熱度榜單”。
Redis 使用以下命令創(chuàng)建一個(gè)有序集合:
127.0.0.1:6379> ZADD key score member [score member ...]
key:指定一個(gè)鍵名;
score:分?jǐn)?shù)值,用來描述 member,它是實(shí)現(xiàn)排序的關(guān)鍵;
member:要添加的成員(元素)。
當(dāng) key 不存在時(shí),將會(huì)創(chuàng)建一個(gè)新的有序集合,并把分?jǐn)?shù)/成員(score/member)添加到有序集合中;當(dāng) key 存在時(shí),但 key 并非 zset 類型,此時(shí)就不能完成添加成員的操作,同時(shí)會(huì)返回一個(gè)錯(cuò)誤提示。
注意:在有序集合中,成員是唯一存在的,但是分?jǐn)?shù)(score)卻可以重復(fù)。有序集合的最大的成員數(shù)為 2^32 - 1 (大約 40 多億個(gè))。
認(rèn)識(shí)有序集合
1) 壓縮列表
有序集合(zset)同樣使用了兩種不同的存儲(chǔ)結(jié)構(gòu),分別是 zipList(壓縮列表)和 skipList(跳躍列表),當(dāng) zset 滿足以下條件時(shí)使用壓縮列表:
- 成員的數(shù)量小于128 個(gè);
- 每個(gè) member (成員)的字符串長度都小于 64 個(gè)字節(jié)。
下面對(duì)壓縮列表做簡單介紹,它由以下五部分組成,如圖所示:
上述每一部分在內(nèi)存中都是緊密相鄰的,并承擔(dān)著不同的作用,介紹如下:
- zlbytes 是一個(gè)無符號(hào)整數(shù),表示當(dāng)前 ziplist 占用的總字節(jié)數(shù);
- zltail 指的是壓縮列表尾部元素相對(duì)于壓縮列表起始元素的偏移量。
- zllen 指 ziplist 中 entry 的數(shù)量。當(dāng) zllen 比
2^16 - 2大時(shí),需要完全遍歷 entry 列表來獲取 entry 的總數(shù)目。 - entry 用來存放具體的數(shù)據(jù)項(xiàng)(score和member),長度不定,可以是字節(jié)數(shù)組或整數(shù),entry 會(huì)根據(jù)成員的數(shù)量自動(dòng)擴(kuò)容。
- zlend 是一個(gè)單字節(jié)的特殊值,等于 255,起到標(biāo)識(shí) ziplist 內(nèi)存結(jié)束點(diǎn)的作用。
下面執(zhí)行
ZADD命令添加兩個(gè)成員:xh(小紅) 的工資是 3500.0;xm(小明) 的工資是 3200.0。
ZADD salary 3500.0 xh 3200.0 xm
上述成員在壓縮列表中的布局,如下所示:
當(dāng) zset 使用壓縮列表保存數(shù)據(jù)時(shí),entry 的第一個(gè)節(jié)點(diǎn)保存 member,第二個(gè)節(jié)點(diǎn)保存 score。依次類推,集合中的所有成員最終會(huì)按照 score 從小到大排列。
2) 跳躍列表
當(dāng)有序結(jié)合不滿足使用壓縮列表的條件時(shí),就會(huì)使用 skipList 結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù)。
跳躍列表(skipList)又稱“跳表”是一種基于鏈表實(shí)現(xiàn)的隨機(jī)化數(shù)據(jù)結(jié)構(gòu),其插入、刪除、查找的時(shí)間復(fù)雜度均為 O(logN)。從名字可以看出“跳躍列表”,并不同于一般的普通鏈表,它的結(jié)構(gòu)較為復(fù)雜,本節(jié)只對(duì)它做淺顯的介紹,如有興趣可自行研究。
在 Redis 中一個(gè) skipList 節(jié)點(diǎn)最高可以達(dá)到 64 層,一個(gè)“跳表”中最多可以存儲(chǔ) 2^64 個(gè)元素,每個(gè)節(jié)點(diǎn)都是一個(gè) skiplistNode(跳表節(jié)點(diǎn))。skipList 的結(jié)構(gòu)體定義如下:
typedf struct zskiplist{
//頭節(jié)點(diǎn)
struct zskiplistNode *header;
//尾節(jié)點(diǎn)
struct zskiplistNode *tail;
// 跳表中的元素個(gè)數(shù)
unsigned long length;
//表內(nèi)節(jié)點(diǎn)的最大層數(shù)
int level;
}zskiplist;
- header:指向 skiplist 的頭節(jié)點(diǎn)指針,通過它可以直接找到跳表的頭節(jié)點(diǎn),時(shí)間復(fù)雜度為 O(1);
- tail:指向 skiplist 的尾節(jié)點(diǎn)指針,通過它可以直接找到跳表的尾節(jié)點(diǎn),時(shí)間復(fù)雜度為 O(1);
- length:記錄 skiplist 的長度,也就跳表中有多少個(gè)元素,但不包括頭節(jié)點(diǎn);
- level:記錄當(dāng)前跳表內(nèi)所有節(jié)點(diǎn)中的最大層數(shù)(level);
跳躍列表的每一層都是一個(gè)有序的鏈表,鏈表中每個(gè)節(jié)點(diǎn)都包含兩個(gè)指針,一個(gè)指向同一層的下了一個(gè)節(jié)點(diǎn),另一個(gè)指向下一層的同一個(gè)節(jié)點(diǎn)。最低層的鏈表將包含 zset 中的所有元素。如果說一個(gè)元素出現(xiàn)在了某一層,那么低于該層的所有層都將包含這個(gè)元素,也就說高層是底層的子集。
通過以下示意圖進(jìn)一步認(rèn)識(shí) skiplist 結(jié)構(gòu)。下圖是一個(gè)上下共四層的跳躍列表結(jié)構(gòu):
圖1:跳躍列表示意圖
跳躍列表中的每個(gè)節(jié)點(diǎn)都存儲(chǔ)著 S:V(即 score/value),示意圖顯示了使用跳躍列表查找 S:V 節(jié)點(diǎn)的過程。跳躍列表的層數(shù)由高到低依次排列,最低層是 L0 層,最高層是 L3 層,共有 4 層。
圖 1 所示,首先從最高層開始遍歷找到第一個(gè)
S:V節(jié)點(diǎn),然后從此節(jié)點(diǎn)開始,逐層下降,通過遍歷的方式找出每一層的 S:V 節(jié)點(diǎn),直至降至最底層(L0)才停止。在這個(gè)過程中找到所有 S:V 節(jié)點(diǎn)被稱為期望的節(jié)點(diǎn)。跳躍列表把上述搜索一系列期望節(jié)點(diǎn)的過程稱為“搜索路徑”,這個(gè)“搜索路徑”由搜索到的每一層的期望節(jié)點(diǎn)組成,其本質(zhì)是一個(gè)列表。
常用命令匯總
| 命令 | 說明 |
|---|---|
| ZADD key score1 member1 [score2 member2] | 用于將一個(gè)或多個(gè)成員添加到有序集合中,或者更新已存在成員的 score 值 |
| ZCARD key | 獲取有序集合中成員的數(shù)量 |
| ZCOUNT key min max | 用于統(tǒng)計(jì)有序集合中指定 score 值范圍內(nèi)的元素個(gè)數(shù)。 |
| ZINCRBY key increment member | 用于增加有序集合中成員的分值。 |
| ZINTERSTORE destination numkeys key [key ...] | 求兩個(gè)或者多個(gè)有序集合的交集,并將所得結(jié)果存儲(chǔ)在新的 key 中。 |
| ZLEXCOUNT key min max | 當(dāng)成員分?jǐn)?shù)相同時(shí),計(jì)算有序集合中在指定詞典范圍內(nèi)的成員的數(shù)量。 |
| ZRANGE key start stop [WITHSCORES] | 返回有序集合中指定索引區(qū)間內(nèi)的成員數(shù)量。 |
| ZRANGEBYLEX key min max [LIMIT offset count] | 返回有序集中指定字典區(qū)間內(nèi)的成員數(shù)量。 |
| ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] | 返回有序集合中指定分?jǐn)?shù)區(qū)間內(nèi)的成員。 |
| ZRANK key member | 返回有序集合中指定成員的排名。 |
| ZREM key member [member ...] | 移除有序集合中的一個(gè)或多個(gè)成員。 |
| ZREMRANGEBYLEX key min max | 移除有序集合中指定字典區(qū)間的所有成員。 |
| ZREMRANGEBYRANK key start stop | 移除有序集合中指定排名區(qū)間內(nèi)的所有成員。 |
| ZREMRANGEBYSCORE key min max | 移除有序集合中指定分?jǐn)?shù)區(qū)間內(nèi)的所有成員。 |
| ZREVRANGE key start stop [WITHSCORES] | 返回有序集中指定區(qū)間內(nèi)的成員,通過索引,分?jǐn)?shù)從高到低。 |
| ZREVRANGEBYSCORE key max min [WITHSCORES] | 返回有序集中指定分?jǐn)?shù)區(qū)間內(nèi)的成員,分?jǐn)?shù)從高到低排序。 |
| ZREVRANK key member | 返回有序集合中指定成員的排名,有序集成員按分?jǐn)?shù)值遞減(從大到小)排序。 |
| ZSCORE key member | 返回有序集中,指定成員的分?jǐn)?shù)值。 |
| ZUNIONSTORE destination numkeys key [key ...] | 求兩個(gè)或多個(gè)有序集合的并集,并將返回結(jié)果存儲(chǔ)在新的 key 中。 |
| ZSCAN key cursor [MATCH pattern] [COUNT count] | 迭代有序集合中的元素(包括元素成員和元素分值)。 |
基本命令演示
下面通過一組命令,讓我們熟悉如何操作 zset 數(shù)據(jù)類型。以下示例是一個(gè)保存了員工薪水的有序集合:
#在有序集合中添加一個(gè)成員 127.0.0.1:6379> ZADD salary 4000 lucy (integer) 1 #同時(shí)添加多個(gè)成員 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)計(jì)指定工資范圍內(nèi)的元素個(gè)數(shù)3000<=score<=5000 127.0.0.1:6379> ZCOUNT salary 3000 5000 (integer) 3 #表示3000ZCOUNT salary (3000 (5000 (integer) 1 #返回指定工資范圍內(nèi)的score和成員,限制條件是跳過1個(gè)元素,返回2個(gè)元素。 127.0.0.1:6379> ZRANGEBYSCORE salary 3000 6000 WITHSCORES LIMIT 1 2 1) "lucy" 2) "4000" 3) "tom" 4) "5000" #查看有序集合在指定字典區(qū)間內(nèi)的成員的數(shù) #其中 - 表示最小值,而 + 則表示最大值 127.0.0.1:6379> ZLEXCOUNT salary - + (integer) 5
在線練習(xí)工具:https://try.redis.io/
查看更多命令:https://redis.io/commands
分享題目:Rediszset有序集合(底層原理+圖解)
標(biāo)題鏈接:http://www.dlmjj.cn/article/coghhep.html


咨詢
建站咨詢
