Redis系列 六 SortedSets設計技巧

2021-09-30 13:50:06 字數 2860 閱讀 7815

閱讀目錄:介紹

score佔位

更多位資訊

總結redis sorted sets是類似redis sets資料結構,不允許重複項的string集合。不同的是sorted sets中的每個成員都分配了乙個分數值(score),它用於在sorted sets中進行成員排序,從最小值到最大值。sorted sets中所有的成員都是唯一的,其分數(score)是可以重複的,即是說乙個分數可能會對應多個值。

用sorted sets可以非常快的進行新增、刪除、或更新成員,其複雜度是o(m*log(n)),m是新增或查詢的成員數量。因為成員是按照順序新增的,所以可以非常快的通過score或者索引進行範圍查詢。訪問sorted sets中間的元素也是非常快的,因此可以用sort sets作為乙個不重複的小型有序列表。 通過sorted sets可以快速操作任何你想做的事情:排序的成員,判斷成員是否在集合中,快速訪問集合中間的成員。

如果多次新增相同的值到sorted sets上,redis會以最後一次的值分數為準。

總的來說,在其他資料庫比較難完成的任務,用sorted sets可以更快更優效能的完成。

更多sorted sets的用法可以檢視官方文件。

sorted sets中的score是個64位整數型別,其範圍在-9007199254740992到9007199254740992之間,這是乙個非常有用的關鍵點。

我們通常可以用它進行簡單的範圍查詢,比如把年齡當分數,通過zrangebyscore查詢某個年齡段的所有使用者。

查詢18-35年齡的使用者:

zrangebyscore user 18

35

如果有更複雜的需求,比如通過日期,使用者型別等來查詢,就比較困難了。 如果用其他資料結構的話,想查詢多條時就要多次往返操作,有效能上的損耗。 這裡可以用score整數型別的長度特性,來儲存查詢的條件資訊。

比如有些資料需要通過日期範圍查詢,這是個很常見的場景。

使用sorted sets當儲存的資料結構,新增key時把日期進行簡單的轉碼。

一年有365天,在score中預留三位來儲存天份,通過dayofyear計算出一年第多少天:

var time1=datetime.now.dayofyear
因為第100天前的資料不滿三位,需要進行用0補全,寫個方法:

string autocompletion(int length, int

num)

return

sb.tostring();

}

因為資料的日期可能跨年,在天位前預留2位,儲存年份。現在長度是5位,如15200表示的是15年19號(第200天)。 

通過年份+天數計算出當前資料項score的值。

var score= long.parse(datetime.year.tostring().substring(2, 2) + autocompletion(3, datetime.dayofyear));
把實際值和分數值儲存到redis裡面:

zadd test socre value
查詢時把需要查詢的日期範圍轉換到分數,這裡查詢前10天的資料:

int time1 =datetime.now.dayofyear;

var score1 = autocompletion(time1, 2) + autocompletion(datetime.now.dayofyear, 3

);

int time2 =datetime.now.dayofyear;

var score2 = autocompletion(time1, 2) + autocompletion(datetime.now.adddays(-10).tolocaltime().dayofyear, 3);

在redis中查詢:

zrangebyscore user score1 score2
查詢當天(分數)下的資訊:

zrangebyscore user score2 score2
r64位整數型別有16個位置,意味著還可以儲存更多維度資訊。這裡以日期為主,在增加個型別維度,日期位置左移4位,預留4位來儲存型別維度。

如152003456,其3456四位是儲存型別的,可以根據型別種類的多少可以增加位或減少位占用。

如果單純以日期來查詢時,型別不用傳,後面4位在查詢時補千位最小值和最大值即可。

查詢前10天的資料:

zrangebyscore user 151900000

152009999

查詢15年19號3578型別的資料:

zrangebyscore user 152003578

152003578

查詢15年19號1000-4000型別的資料:

zrangebyscore user 152001000

152004000

abcd 1000

dcda

1001

以此類推...

在新增時或查詢時注意轉換。

需要注意的是score是整數型別按從小到大排序儲存的,按照上面的設計是不能在指定型別的情況下,進行日期範圍查詢的,因為我們定義日期作為主維度。

通常在資料庫中有很多層級關係的表,比如大分類、子分類、小分類等一級一級遞減。 使用sorted sets我們可以模擬這種關係去設計score值,主維度->次維度->低維度,這樣就可以更快的進行範圍分類資訊的查詢,有個前提是64位整數的位置夠用。

如果沒有類似的需求,可以使用時間戳作為值的分數值,這樣就不需要額外的轉換了。

簡單分享了sorted sets儲存設計的經驗,希望對大家有所幫助。

Redis系列六 Redis事務

在redis事務中可以一次執行多個命令,本質是一組命令的集合。乙個事務中的所有命令都會序列化,按順序地序列化執行而不會被其它命令插入,不許加塞。乙個佇列中,一次性 順序性 排他性的執行一系列命令。case1 正常執行 執行exec全部成功 case2 放棄事務 執行discard case3 全體連...

Redis系列 六 SortedSets設計技巧

閱讀目錄 介紹score佔位 更多位資訊 總結redis sorted sets是類似redis sets資料結構,不允許重複項的string集合。不同的是sorted sets中的每個成員都分配了乙個分數值 score 它用於在sorted sets中進行成員排序,從最小值到最大值。sorted ...

Redis系列 字串 String (六)

redis 字串資料型別的相關命令用於管理 redis 字串值,基本語法如下 redis 127.0 0.1 6379 command key nameredis 127.0 0.1 6379 set runoobkey redis okredis 127.0 0.1 6379 get runoob...