redis java根据value排序_Redis高级特性——排序
排序
對(duì)于排序的場(chǎng)景,在業(yè)務(wù)中會(huì)大量使用到,對(duì)于Redis,如果使用了有序集合,那么排序問題很容易解決,并且得分可以根據(jù)實(shí)際的業(yè)務(wù),由時(shí)間、點(diǎn)贊、費(fèi)用、排行等等進(jìn)行轉(zhuǎn)化,支持的業(yè)務(wù)范圍也比較廣泛。
除了有序集合的排序外,Redis另外提供了排序的指令SORT。SORT指令可以針對(duì)列表類型、集合類型、有序集合類型的鍵進(jìn)行排序,同時(shí)借助BY指令,Redis的SORT...BY指令可以完成一部分類似MYSQL中的關(guān)系查詢排序效果。
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern...]] [ASC|DESC] [ALPHA] [STORE destinion]
SORT排序比較簡(jiǎn)單,排序之后立即將結(jié)果返回,以列表的形式返回。假定有一個(gè)資源ID列表,資源ID使用MYSQL的自增主鍵,從1開始累增。如果將這些ID放置到了集合中,那么在使用按入庫(kù)時(shí)間降序排列時(shí),使用集合是無(wú)法做到的,此時(shí)可以使用SORT。使用列表效果也一致。參考下面的例子。
# 結(jié)合
SADD resourceids 2 3 1 5 4
# (integer) 5
SORT resourceids # 默認(rèn)為ASC
# 1) "1"
# 2) "2"
# 3) "3"
# 4) "4"
# 5) "5"
SORT resourceids DESC
# 1) "5"
# 2) "4"
# 3) "3"
# 4) "2"
# 5) "1"
# 列表
LPUSH lst 2 3 1 5 4
# (integer) 5
SORT lst DESC
# 1) "5"
# 2) "4"
# 3) "3"
# 4) "2"
# 5) "1"
從上列中看出,使用SORT指令時(shí),列表、集合或者是有序集合,指令功能基本是一致的。而對(duì)有序集合使用SORT進(jìn)行排序時(shí),將會(huì)忽略SCORE,只對(duì)元素字面值進(jìn)行排序,此時(shí)效果和集合或列表使用方式及表現(xiàn)是一致的。
ZADD zlst 123 2 125 3 120 1 125 5 124 4
# (integer) 5
SORT zlst DESC
# 1) "5"
# 2) "4"
# 3) "3"
# 4) "2"
# 5) "1"
一般情況下資源類的ID都是數(shù)字,使用SORT進(jìn)行排序能完成快速排序的目的,但有時(shí)候也會(huì)有字符串類的ID集合,Redis命令也可以通過指定ALPHA屬性實(shí)現(xiàn)字符串排序。這個(gè)時(shí)候只是按非數(shù)字字符串本身進(jìn)行排序,會(huì)丟掉數(shù)據(jù)庫(kù)自增的順序?qū)傩浴H绻鸖ORT沒有攜帶ALPHA參數(shù),那么SORT仍然會(huì)使用數(shù)字類型排序,如果是非數(shù)字字符串集合,那么將會(huì)返回錯(cuò)誤信息。
LPUSH alphaLst hello world lua redis c# java JAVA
# (integer) 7
SORT alphaLst ALPHA
# 1) "c#"
# 2) "hello"
# 3) "java"
# 4) "JAVA"
# 5) "lua"
# 6) "redis"
# 7) "world"
當(dāng)結(jié)果較多時(shí),排序時(shí),可以使用LIMIT參數(shù)進(jìn)行限制返回的數(shù)據(jù)數(shù)量,可以實(shí)現(xiàn)分頁(yè)效果,該參數(shù)的使用方式同MySQL的LIMIT基本一致。offset從0開始
SORT lst DESC
# 1) "5"
# 2) "4"
# 3) "3"
# 4) "2"
# 5) "1"
SORT lst LIMIT 0 2 DESC
# 1) "5"
# 2) "4"
SORT lst LIMIT 2 2 DESC
# 3) "3"
# 4) "2"
如果資源ID已經(jīng)存儲(chǔ)到了列表中,如上例中的[1,2,3,4,5]五個(gè)資源,同時(shí)使用散列數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)了這些資源的詳情,同時(shí)詳情中包含了一個(gè)點(diǎn)擊得分的字段score,該字段為數(shù)字類型。如果有需求要實(shí)現(xiàn)按用戶的點(diǎn)擊得分進(jìn)行排序,此時(shí)需要借助BY參數(shù)實(shí)現(xiàn)。
# 資源詳情散列數(shù)據(jù)結(jié)構(gòu)及數(shù)據(jù)如下,散列的key為`resource:id`,散列的field為字段名,這里只有title和score
[
"resource:5" : {
title: "efg",
score: 125
} ,
"resource:4" : {
title: "bcd",
score: 230
} ,
"resource:3" : {
title: "ddd"
score: 125
} ,
"resource:2" : {
title: "ggg",
score: 100
} ,
"resource:1" : {
title: "fff",
score: 156
}
]
要實(shí)現(xiàn)資源點(diǎn)擊得分倒序排列,采用如下的指令。當(dāng)排序中參考字段某幾個(gè)元素相同時(shí),如本例中5、3得分都是125,那么在排序時(shí),遇到相同的,會(huì)再次參考元素本身進(jìn)行排序
SORT lst BY resource:*->score DESC
# 1) "4"
# 2) "1"
# 3) "5"
# 4) "3"
# 5) "2"
BY的使用方法為:BY pattern,pattern為要進(jìn)行排序的參考的鍵。該字段的標(biāo)識(shí)方法為:鍵名->字段名,可以是散列類型,也可以是字符串類型。當(dāng)出現(xiàn)BY參數(shù)時(shí),Redis會(huì)使用列表中元素,去替換BY后面字段中的*,并根據(jù)實(shí)際的字段獲取值,參與到排序中,如上述示例中,將分別獲取resource:1、resource:2、resource:3、resource:4、resource:5等散列中的score字段的值,并參與到排序中。如果參考字段時(shí)散列類型那么對(duì)于通配符*只能存在于->之前。如果使用字符串作為參考字段時(shí),ID列表不需要變更,只要將score存儲(chǔ)到字符串中,其數(shù)據(jù)如下:
[
"strscore:5": 125,
"strscore:4": 230,
"strscore:3": 125,
"strscore:2": 100,
"strscore:1": 156,
]
排序指令如下,得到和散列結(jié)構(gòu)詳情一樣的結(jié)果。
SORT lst BY strscore:* DESC
# 1) "4"
# 2) "1"
# 3) "5"
# 4) "3"
# 5) "2"
當(dāng)參考鍵中不包含*時(shí),常量鍵值,此時(shí)SORT將不會(huì)進(jìn)行排序。
SORT lst BY a DESC
# 1) "2"
# 2) "3"
# 3) "1"
# 4) "5"
# 5) "4"
如果參考字段中某個(gè)值不存在時(shí),會(huì)以默認(rèn)值0進(jìn)行替代,上例中抹去resource:1字段,在進(jìn)行排序
DEL strscore:1
# (integer) 1
SORT lst BY strscore:* DESC
# 1) "4"
# 2) "5"
# 3) "3"
# 4) "2"
# 5) "1"
GET參數(shù)可以應(yīng)用于SORT BY結(jié)構(gòu)中,用于指定返回的信息。這個(gè)功能在做列表時(shí)非常有用,如果有需求要顯示點(diǎn)擊排行列表,那么一方面需要按點(diǎn)擊排序,另外一方面需要返回資源名稱以及資源ID;如果可以在SORT指令中一并返回,就不需要業(yè)務(wù)先做排序,拿到排序后的ID集合,在根據(jù)ID獲取資源信息,取出title信息。
SORT指令的GET實(shí)現(xiàn)了這個(gè)功能,根據(jù)字符串或散列對(duì)象分別獲取,其規(guī)則為
# 散列
GET key:*->field
get resource:*->title
# 字符串
GET key:*
# 獲取列表中的ID
GET #
根據(jù)之前的數(shù)據(jù)結(jié)構(gòu),從散列表中resource:*和集合resourceids中按評(píng)分進(jìn)行排序,并獲取id、title和評(píng)分的列表。
SORT resourceids BY resource:*->score DESC GET resource:*->title GET resource:*->score GET # LIMIT 0 2
# 1) "bcd"
# 2) "230"
# 3) "4"
# 4) "efg"
# 5) "125"
# 6) "5"
如果有幾個(gè)GET,如上面例子中有三個(gè)GET,那么返回結(jié)果列表中,每一個(gè)結(jié)果就有幾條顯示,(3條,title、score、id)。
一般情況下,SORT主要用于對(duì)列表進(jìn)行排序,獲取部分結(jié)果,如排行榜之類的。這時(shí)顯示的一般是列表,不需要返回跟多的詳情信息,并且有時(shí)間要求(排行榜每一小時(shí)更新一次)。這種情況不需要業(yè)務(wù)系統(tǒng)每次都排序,獲取字段組裝數(shù)據(jù),SORT指令提供給了最后一個(gè)參數(shù)STORE,該參數(shù)可以將結(jié)果存儲(chǔ)到指定的鍵中,同時(shí)設(shè)置有效期后,將可以滿足上述的業(yè)務(wù)需求。其參數(shù)使用方式為:... STORE key,加了該參數(shù)后,其返回結(jié)果將不在是列表,而是存儲(chǔ)的結(jié)果數(shù)量,以列表數(shù)據(jù)存儲(chǔ)。
SORT resourceids BY resource:*->score DESC GET resource:*->title GET resource:*->score GET # LIMIT 0 2 STORE my_top
# (integer) 6
LRANGE my_top 0 -1
# 1) "bcd"
# 2) "230"
# 3) "4"
# 4) "efg"
# 5) "125"
# 6) "5"
SORT指令是目前為止使用到的最復(fù)雜的指令,且提供了類似MySQL一樣的關(guān)聯(lián)查詢操作。在某些操作的時(shí)候,可能會(huì)導(dǎo)致查詢緩慢,由于Redis時(shí)單線程,也可能一個(gè)指令導(dǎo)致Redis的阻塞。
SORT指令的時(shí)間負(fù)責(zé)度:O(n+mlogm),n為要排序的列表數(shù)量,m為要SORT返回的元素?cái)?shù)量(LIMIT),隨著n的增大,該指令的效率降低。同時(shí)排序時(shí),Redis也會(huì)建立一個(gè)長(zhǎng)度為n的臨時(shí)列表存儲(chǔ)這些元素,從這方面看數(shù)據(jù)越大,性能就越慢。
為了提高性能,只能從這兩方面入手:降低n的數(shù)量,或者降低m的數(shù)量(LIMIT可解決);數(shù)量較大時(shí),使用STORE參數(shù)將結(jié)果緩存,在一定程度上可以減少STORE的調(diào)用次數(shù)。
總結(jié)
以上是生活随笔為你收集整理的redis java根据value排序_Redis高级特性——排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python的按钮控件_python实现
- 下一篇: Intel 56核心至强超频5.5GHz