Redis 數(shù)據(jù)類型及應(yīng)用場(chǎng)景——zset

今天再來(lái)聊下redis中的有序集合sort set,也是redis里面最高級(jí)別的一種數(shù)據(jù)類型故河,之前有聊到集合(set) ,從名字上來(lái)看這兩種類型很相似巍佑,不過兩者可能在設(shè)計(jì)之初就被賦予了不同的使命吧色洞。顧名思義巫财,有序集合就是集合中的元素是按照一定的順序排列的妄田,是有序的净赴,我們之前說的那個(gè)集合是無(wú)序的绳矩,那接下來(lái)我們來(lái)詳細(xì)的看看redis 有序集合。

1.簡(jiǎn)介

有序集合(sort set)是在集合類型的基礎(chǔ)上為每個(gè)元素關(guān)聯(lián)一個(gè)分?jǐn)?shù)玖翅,那這使得我們不僅可以完成插入翼馆,刪除和判斷元素是否存在等集合操作,還能夠獲得分?jǐn)?shù)最高(或最低)的前N個(gè)元素金度,獲得指定分?jǐn)?shù)范圍內(nèi)的元素等分?jǐn)?shù)有關(guān)的操作应媚。雖然集合中每個(gè)元素都是不相同的,但是分?jǐn)?shù)可以相同猜极;內(nèi)部使用hashMap或者跳躍表來(lái)實(shí)現(xiàn)的中姜。下面給大家畫一張圖:


圖1.png

2. 命令

這里關(guān)于有序集合的命令寫得比較全,小伙伴們可以有選擇的看

  1. 增加元素/刪除元素/獲取元素的分?jǐn)?shù)/獲取集合中的元素?cái)?shù)量
    zadd key score member [score member ...] score(分?jǐn)?shù))跟伏,如果分?jǐn)?shù)是小數(shù)的話可能會(huì)存在精度的問題丢胚,本人覺得比較省事的做法就是把數(shù)據(jù)轉(zhuǎn)換為整數(shù)后再進(jìn)行存放,比如乘以100受扳。
    zrem key member [member] 携龟,返回成功刪除的元素?cái)?shù)量
    zscore key member 返回指定元素的分?jǐn)?shù)
redis> zadd scoreboard 100 xiaoming 89 Tom 95 Peter // 往集合中加入三條記錄
(integer) 3
redis> zrem scoreboard  xiaoming
(integer) 1
redis > zscore  scoreboard   Peter 
"95"
redis > zcard scoreboard  
(integer) 4

如果scoreboard 這個(gè)集合中已經(jīng)存在Tom這位同學(xué),那么執(zhí)行zadd 后會(huì)覆蓋原來(lái)的勘高。

  1. 獲得排名在某個(gè)范圍內(nèi)的元素列表/按照排名范圍刪除元素
    zrange key start stop [withscores]
    zrevrange key start stop [withscores]
    zremrangebyrank key start stop 按照元素分?jǐn)?shù)從小到大的順序刪除處在指定排名范圍內(nèi)的所有元素峡蟋,并返回刪除的元素?cái)?shù)量浮定,注意是包含start和stop位置上的元素
redis > zrange scoreboard 0 -1 //獲取集合中的所有元素,并且按照分?jǐn)?shù)來(lái)從小到大排好序了层亿。
1) "Tom"
2) "Peter"
3) "xiaoming"
redis >zrange scoreboard 0 -1 withscores // 加上withscores參數(shù) 額外再返回分?jǐn)?shù)桦卒。
1) "Tom"
2) "89"
3) "Peter"
4) "95"
5) "xiaoming"
6) "100"
redis > zrevrange   scoreboard 0 -1  //按照分?jǐn)?shù)從高到低排序。
1) "xiaoming"
2) "Peter"
3) "Tom"
redis > zadd testRem 1 a 2 b 3 c 4 d
(integer) 4
redis > zremrangebyrank testRem 0  2
(integer) 3

這里就展示這三個(gè)操作匿又,不過需要注意的是start和end 這兩個(gè)值的選取方灾,集合中的數(shù)據(jù)下標(biāo)是從0開始的,所以第一個(gè)元素標(biāo)號(hào)是0碌更,第二個(gè)元素標(biāo)號(hào)是1裕偿,zrange和zrevrange命令中的start和end返回的元素是包含start和end標(biāo)號(hào)下的元素的。所以我們?nèi)绻幌敕祷氐谝粋€(gè)元素可以這樣寫

redis> zrange scoreboard  0 0
1) "Tom"

還有一個(gè)需要注意的就是如果兩個(gè)元素的分?jǐn)?shù)相同痛单,Redis會(huì)按照字典順序(也就是 "0" < "9"<"A"<"Z"<"a"<"z" 這樣的順手來(lái)排列)來(lái)進(jìn)行排序嘿棘,但如果是中文則取決于中文的編碼方式,具體的沒做深入的研究旭绒,這里就不具體說了鸟妙。
不過貌似沒有只獲取所有元素分?jǐn)?shù)的命令

  1. 獲取指定分?jǐn)?shù)范圍內(nèi)的元素/獲取指定分?jǐn)?shù)范圍內(nèi)的元素個(gè)數(shù)/按照分?jǐn)?shù)范圍刪除元素
    zrangebyscore key min max [WITHSCORES] [LIMIT offset count] //從小到大
    zrevrangebyscore key min max [WITHSCORES] [LIMIT offset count] //從大到小
    zcount key min max
    zremrangebyscore key min max
redis > zrangebyscore scoreboard 80 100 WITHSCORES
1) "Tom"
2) "89"
3) "Peter"
4) "95"
5) "xiaoming"
6) "100"
redis > zcount scoreboard   80 90
(integer) 1

注意:包含min和max。 如果希望不要返回端點(diǎn)的數(shù)據(jù)可以使用"(" 符號(hào)挥吵。例如:

redis > zrangebyscore scoreboard 80 (100 WITHSCORES
1) "Tom"
2) "89"
3) "Peter"
4) "95"
redis >

如果需要返回大于某個(gè)值或者小于某個(gè)值的所有元素可以使用+inf和-inf 重父,分別表示正無(wú)窮大和負(fù)無(wú)窮大,比如希望返回高于89分忽匈,但是不包含89分的所有元素房午,但是你不知道最高分是多少,這個(gè)時(shí)候就可以這樣寫:

redis> zrangebyscore scoreboard (89  +inf  WITHSCORES
1) "Peter"
2) "95"
3) "xiaoming"
4) "100"

zrangebyscore 這個(gè)命令還向我們提供了limit offset count 丹允,這個(gè)類型于我們經(jīng)常使用的sq語(yǔ)句里面的limit offset count郭厌,就是從offset這個(gè)文位置開始獲取count個(gè)元素

  1. 獲得元素的排名
    zrank key member
    zrevrank key member
redis > zrank scoreboard Peter
(integer) 2
redis > zrevrank scoreboard Peter
(integer) 1

注意:排名是從0開始計(jì)數(shù)的。

  1. 增加或者減少某個(gè)元素的分?jǐn)?shù)
    zincrby key increment member 雕蔽,其中increment既可以為正數(shù)(表示增加)也可以為負(fù)數(shù)(表示減少),這個(gè)increment就好為整數(shù)折柠,不然也是會(huì)出現(xiàn)精度問題,導(dǎo)致數(shù)據(jù)不太對(duì)萎羔。
redis > zincrby  scoreboard  -1 Peter
"94"

6)計(jì)算有序集合的交集
ZINTERSTORE destination numkeys key [key ...] 液走,該命令用來(lái)計(jì)算多個(gè)有序集合的交集并將結(jié)果存放在destination鍵中(同樣以有序集合類型存儲(chǔ)),返回值為destination鍵中的元素個(gè)數(shù)贾陷。destination鍵中的元素分?jǐn)?shù)是有aggregate參數(shù)決定的缘眶。
(1) 當(dāng)aggregate是sum時(shí)(也就是默認(rèn)值),destination 鍵中的元素的分?jǐn)?shù)是每個(gè)參與計(jì)算的集合中的改元素分?jǐn)?shù)的和髓废。

redis > zadd sortedSets3 1 a 2 b
(integer) 2
redis > zadd sortedSets4 2 b 3 c
(integer) 2
redis > ZINTERSTORE sortedSetsResult1 2 sortedSets3 sortedSets4
(integer) 1
redis > zrange sortedSetsResult1 0 -1 WITHSCORES
1) "b"
2) "4"

(2) 當(dāng)aggregate是min或者max時(shí)巷懈,destination鍵中的元素的分?jǐn)?shù)是每個(gè)參與計(jì)算的集合中改元素分?jǐn)?shù)的最小值或者最小值。

redis > ZINTERSTORE sortedSetsResult2 2 sortedSets3 sortedSets4 AGGREGATE min
(integer) 1
redis > zrange sortedSetsResult2 0 -1 WITHSCORES
1) "b"
2) "2"

ZINTERSTORE 命令還能夠通過設(shè)置WEIGHTS參數(shù)設(shè)置每個(gè)集合的權(quán)重慌洪,每個(gè)集合在參與計(jì)算時(shí)元素的分?jǐn)?shù)會(huì)被乘上改集合的權(quán)重顶燕。

redis > ZINTERSTORE sortedSetsResult3 2 sortedSets3 sortedSets4  WEIGHTS 1  10
(integer) 1
redis > zrange sortedSetsResult3 0 -1 WITHSCORES
1) "b"
2) "22"

另外還有一個(gè)與ZINTERSTORE命令的用法相同的命令-zunionstore凑保,它的作用是計(jì)算集合間的并集,這里就不具體展示了涌攻。下面我們看下有序集合的相關(guān)應(yīng)用場(chǎng)景

3. 實(shí)踐

1. 實(shí)現(xiàn)按點(diǎn)擊量排序
以文章的ID作為鍵欧引,文章的點(diǎn)擊量作為分?jǐn)?shù),如果將鍵名命名為posts:page.view恳谎,每次訪問某篇文章的時(shí)候就zincrby posts:page.view 1 文章ID 來(lái)更新點(diǎn)擊量芝此,需要按照點(diǎn)擊量來(lái)顯示文章的時(shí)候 zrevrange posts:page.view start end 來(lái)獲取文章的某一范圍內(nèi)的文章id。
2. 按照文章的發(fā)布時(shí)間來(lái)排序
如果文章的發(fā)布時(shí)間是可以修改的因痛,我們可以使用有序集合來(lái)實(shí)現(xiàn)婚苹,元素是文章的id,元素的分?jǐn)?shù)是發(fā)布時(shí)間鸵膏,通過修改元素的對(duì)應(yīng)的分?jǐn)?shù)就可以達(dá)到更改時(shí)間的目的膊升。
3. 排行榜
比如要取得某個(gè)班級(jí)的前十名的學(xué)生名單,使用 zadd scoreboard <score> <username>將學(xué)生的分?jǐn)?shù)保存谭企,那么取得前十名的同學(xué)名單是很容易的廓译,zrevrange scoreboard 0 9
4. 可以做帶權(quán)重的隊(duì)列,比如普通消息的score為1赞咙,重要消息的score為2责循,然后工作線程可以選擇score的倒序來(lái)獲取工作任務(wù)糟港。讓重要的任務(wù)優(yōu)先執(zhí)行攀操。

4. 有序集合和集合的區(qū)別

首先他們都是集合,都支持添加秸抚,刪除速和,獲取元素。但是它們應(yīng)用的場(chǎng)景是不一樣的剥汤,

  1. Set(集合) 這種類型對(duì)于不同集間求交集颠放,并集,差集是很方便的吭敢,因此它非常適合用在一些社交的場(chǎng)景碰凶,比如某兩個(gè)人共同關(guān)注的人。
  2. Zset(有序集合)鹿驼,它更多的應(yīng)用于一些需要按照某種方式排序的情況下欲低,操作是很方便的,例如:求集合中分?jǐn)?shù)最高的幾個(gè)人的名單畜晰,使用zrevrange key 0 5

5. 有序集合和列表的區(qū)別

我們先來(lái)看下相同的地方:

  1. 兩者都是有序的砾莱,注意list的順序是按照插入的順序,而有序集合是按照分?jǐn)?shù)來(lái)排序的凄鼻,不是添加時(shí)候的順序腊瑟。
  2. 兩者都可以獲得某一范圍內(nèi)的元素聚假,說的具體一點(diǎn),就是list獲取某一范圍內(nèi)的元素是根據(jù)元素的位置來(lái)的闰非,有序集合可以獲取排名在某一范圍內(nèi)的元素膘格,也可以獲取分?jǐn)?shù)在某一范圍內(nèi)的元素。
    下面來(lái)說下二者的區(qū)別
  3. list取鏈表的中間元素是相對(duì)沒有取兩端的數(shù)據(jù)塊财松,但是有序集合使用散列表或者跳躍表來(lái)作為底層實(shí)現(xiàn)闯袒,即使取中間的元素的速度也是很快的。
  4. 列表是不能簡(jiǎn)單的調(diào)整某個(gè)元素的位置的游岳,但是有序集合可以政敢,改變?cè)氐姆謹(jǐn)?shù)即可。我們知道list雖說是可以存儲(chǔ)各種列表胚迫,但是如果需要排序的話喷户,就可能比較麻煩
  5. 有序集合要比列表類型更消耗內(nèi)存。

關(guān)于有序集合就先寫到這吧访锻,如果有小伙伴需要補(bǔ)充的褪尝,歡迎在下面和我留言哦,看到會(huì)及時(shí)回復(fù)的期犬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末河哑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子龟虎,更是在濱河造成了極大的恐慌璃谨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲤妥,死亡現(xiàn)場(chǎng)離奇詭異佳吞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)棉安,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門底扳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人贡耽,你說我怎么就攤上這事衷模。” “怎么了蒲赂?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵阱冶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我凳宙,道長(zhǎng)熙揍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任氏涩,我火速辦了婚禮届囚,結(jié)果婚禮上有梆,老公的妹妹穿的比我還像新娘。我一直安慰自己意系,他們只是感情好泥耀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛔添,像睡著了一般痰催。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迎瞧,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天夸溶,我揣著相機(jī)與錄音,去河邊找鬼凶硅。 笑死缝裁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的足绅。 我是一名探鬼主播捷绑,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼氢妈!你這毒婦竟也來(lái)了粹污?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤首量,失蹤者是張志新(化名)和其女友劉穎壮吩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蕾总,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粥航,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了生百。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柄延,死狀恐怖蚀浆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搜吧,我是刑警寧澤市俊,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站滤奈,受9級(jí)特大地震影響摆昧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜒程,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一绅你、第九天 我趴在偏房一處隱蔽的房頂上張望伺帘。 院中可真熱鬧,春花似錦忌锯、人聲如沸伪嫁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)张咳。三九已至,卻和暖如春似舵,著一層夾襖步出監(jiān)牢的瞬間脚猾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工砚哗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留婚陪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓频祝,卻偏偏與公主長(zhǎng)得像泌参,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子常空,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 五種基本類型及其用法 STRING類型 獲得符合規(guī)則的鍵名列表 KEYS pattern pattern可以以gl...
    nailding閱讀 892評(píng)論 0 49
  • 1 Redis介紹1.1 什么是NoSql為了解決高并發(fā)漓糙、高可擴(kuò)展铣缠、高可用、大數(shù)據(jù)存儲(chǔ)問題而產(chǎn)生的數(shù)據(jù)庫(kù)解決方...
    克魯?shù)吕?/span>閱讀 5,295評(píng)論 0 36
  • Redis數(shù)據(jù)類型 1. Set 集合類型 集合類型:無(wú)序昆禽、不可重復(fù) 列表類型:有序蝗蛙、可重復(fù) 1.1 命令 1.1...
    彈鋼琴的崽崽閱讀 484評(píng)論 0 2
  • redis是一個(gè)以key-value存儲(chǔ)的非關(guān)系型數(shù)據(jù)庫(kù)。有五種數(shù)據(jù)類型醉鳖,string捡硅、hashes、list盗棵、s...
    林ze宏閱讀 996評(píng)論 0 0
  • 有序集合 有序集合相對(duì)于哈希纹因、列表喷屋、集合來(lái)說會(huì)有一點(diǎn)點(diǎn)陌生,但既然叫有序集合瞭恰,那么它和集合必然有著聯(lián)系屯曹,它保留了集...
    linuxzw閱讀 1,016評(píng)論 0 5