使用redis中的zset實現實時排行榜

2021-10-10 01:29:33 字數 4009 閱讀 6863

redis在業務開發中會被頻繁使用,zset是其中一種特殊用法,zset具排行榜的天然特性,我前幾個月在一次開發中使用到了zset,就是因為涉及到要實現乙個排行榜,那是我第一次用到zset,雖然之前都看過redis幾種資料型別的資料結構及其使用方法,但是真正用起來的時候,還是有一些細節的東西要處理的。

使用者在某條賽道上的跑步資料排行榜,以使用者完成賽道的最佳成績(最快圈速)為排序,做出排行榜。

作為公司的新手菜鳥自然不敢自己做技術選型,我當時接到這個需求就想到了zset可能是可以實現這個功能的,後來跟我們的技術老大說了我的想法,她也支援使用zset,於是乎,開了技術評審後,我使用了zset來實現。

zset 和 set 很像,都是字串的集合,都不允許重複的成員出現在乙個 set 中。

他們的區別在於有序集合中每乙個成員都有乙個分數(score)與之關聯,redis 正是通過分數來對集合裡的成員進行從小到大的排序。儘管有序集合中的成員必須是惟一的,但是分數(score)卻可以重複。

* 新增或者更新資料

** @param sortedsetkey key(用於區分不同的排行榜)

* @param member 排行榜物件

* @param score 排行依據(值)

* 如果在key中,不存在該member,則新增,如果存在,則更新

*/public void addorupdate(string sortedsetkey, int member, double score)

/*** 獲取排行榜指定範圍的內容

** @param sortedsetkey key(用於區分不同的排行榜)

* @param startindex 起始值(從0開始)

* @param endindex 結束值

* @return

*/public setreverserange(string sortedsetkey, int startindex, int endindex)

/*** 獲取排行榜指定範圍的內容,反序

** @param sortedsetkey key(用於區分不同的排行榜)

* @param startindex 起始值(從0開始)

* @param endindex 結束值

* @return

*/public setrange(string sortedsetkey, int startindex, int endindex)

/*** 獲取排行榜前n的資料

** @param sortedsetkey key(用於區分不同的排行榜)

* @param number

* @return

*/public settop(string sortedsetkey, long number)

/*** 獲取排行榜start到end的value以及他的score

** @param sortedsetkey key(用於區分不同的排行榜)

* @param start 從0開始算起

* @param end

* @return

*/public set> rangewithscore(string sortedsetkey, int start, int end)

/*** 獲取排名

** @param sortedsetkey key(用於區分不同的排行榜)

* @param member 排行榜物件

* @return

*/public long getranknum(string sortedsetkey, int member)

/*** 獲取score

** @param sortedsetkey

* @param member

* @return

*/public double getscore(string sortedsetkey, object member)

/*** 批量新增/更新資料

** @param sortedsetkey key(用於區分不同的排行榜)

* @param tuples set> tuples = new hashset<>();

* long start = system.currenttimemillis();

* for (int i = 0; i < 100000; i++)

* 注:這個方法,我沒測過

*/public long addorupdateset(string sortedsetkey, set> tuples)

return 0l;

}/**

* 刪除資料

** @param sortedsetkey (用於區分不同的排行榜)

* @param member 排行榜物件

* @return

*/public long remove(string sortedsetkey, object member)

/*** 查詢,範圍內的資料

** @param sortedsetkey key(用於區分不同的排行榜)

* @param startindex 起始值(從0開始)

* @param endindex 結束值

* @return

*/public string getrangedata(string sortedsetkey, long startindex, long endindex)

/*** 增量新增score

** @param sortedsetkey key(用於區分不同的排行榜)

* @param member 排行榜物件

* @param addscore 新增的分數

*/public void incrementscore(string sortedsetkey, string member, double addscore)

/*** 獲取當前redis中排名的資料的總個數

** @param sortedsetkey

* @return

*/public long getsize(string sortedsetkey)

/*** 獲取排行榜所有的資料

** @param sortedsetkey key(用於區分不同的排行榜)

* @return 注意:數量多,容易卡死,不建議使用

*/public setgetall(string sortedsetkey)

return collections.emptyset();

}相信看了上面我列出來的文件裡面的幾個api和上面的工具類,大家對用法也清楚了,其實就是取的時候用rangebyscore,存的時候用zadd,zadd之後zset會自己在內部自動排序,拿出來的結果就是排好序的,不過有個需要注意的地方就是,當score分數一樣時,zset會按照unicode編碼的自然順序來排序(這個我就被坑過),以我之前那個需求為例子的話,當score分數一樣,要以使用者上傳跑步資料的時間作公升序來排的,就是說如果分數一樣,就看誰先完成,誰先完成就排前面,我當時是用分數拼接時間戳的方法。

double timerank = double.parsedouble(vo.getfastspeed() + "." + vo.getlastuploadtime().gettime());
取出來的時候可以直接用int來接收,就直接去掉了後面的小數點了。如果業務需求是時間越大排越前面,就需要用乙個最大時間戳99999999減去業務時間戳,再拼接。

關於redis中Zset元素的使用

zset在set基礎上增加了乙個排序 權值 需手動指定,分數越小,越排前面 zadd zadd name 序號 value 序號2 value2 依據序號的重要程度排序 zrange zrange name start end 查詢zset中的元素,預設從小到大排序,若要從大到小,使用zrevran...

使用redis的zset實現簡單的延時佇列

一 需求切入點 在公司做的乙個系統業務需要有個定時提醒的功能 資料在mysql中 要求提醒的時間差精準到分鐘 解決方案有 使用定時器,每分鐘執行一次,查符合提醒的資料,發起提醒 資料庫連線與系統的負載都承受不住的!將待提醒資料提前查出存進redis中,根據提醒時間設定過期時間,做redis的過期監聽...

用Redis中的zset實現乙個限流器

我還記得14年搶紅公尺的時候,下面這個圖是我最煩的乙個圖 搶了兩個星期,才終於買到了我的第一台小公尺手機 紅公尺1s。小公尺 加入了乙個排隊的機制,於是我們可以感知到自己被限流了,但大部分服務,比如最近各大電商的搶茅台活動,並沒有讓我們感知到限流,不管你是手速不夠還是被限流,都會給你返回 很遺憾,已...