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。小公尺 加入了乙個排隊的機制,於是我們可以感知到自己被限流了,但大部分服務,比如最近各大電商的搶茅台活動,並沒有讓我們感知到限流,不管你是手速不夠還是被限流,都會給你返回 很遺憾,已...