基於redis的zset實現排行榜功能

2021-08-08 19:30:23 字數 1620 閱讀 8146

主要需求包括:

1. 使用者可以上傳每次遊戲的分數,系統返回該使用者的最高分和最高分排名(分數相同時,時間優先);

2. 使用者可以查詢排行榜,返回top50,和自己所在的排名

最開始是想使用資料庫來實現,儲存每個使用者最高分的記錄,主要字段【name, score, createtime】

針對需求1,使用者有新的高分產生的話,就更新使用者的最高分,否則返回當前的最高分,獲取排名時,需要查詢兩次資料庫(1:查詢分數大於自己的記錄 數;

2:查詢分數相同,時間小於自己的記錄數)

針對需求2,按照分數倒序,時間正序查詢top50,判斷自己如果不是前50,則查詢自己的記錄,放到列表末尾

這樣對於資料庫的查詢壓力會比較大,而且只是乙個臨時活動,也沒必要專門建立一張表來實現

然後和同事討論可不可以參考hashmap的原理,

使用陣列+鍊錶的形式的來實現,將分數作為陣列下標,每個陣列元素上是鍊錶,按照達到該分數的先後

順序儲存使用者

針對需求1: 使用者上傳新的分數時,在對應索引位置末尾增加使用者,將原先的使用者節點刪除(需要另外維護使用者原先的最大分數),從末尾迴圈每個節點的

鍊錶,獲取排名和最高分

針對需求2:類似於需求1,

從末尾迴圈每個節點的

鍊錶,獲取top50

這樣每次都需要迴圈列表,如果使用者分數很低的話,迴圈會比較消耗效能,而且系統重啟也會丟失資料。

最後都懂得,搜尋引擎,看到

redis 的zset原來是解決排行榜的標配,天生就是來做排行榜的

redis的zset可以給每個object標記乙個分數,然後可以針對這個分數,為object排名,基於hashtable和skiplist執行insert和remove操作,可以通過range方法獲取top50,通過rank方法獲取排名,完美解決排行榜問題,直接上**

獲取top50的邏輯

public listgetrangetop(long userid) 

// 判斷是否在末尾追加自己

string midautumnstr = stringredistemplate.opsforvalue().get(mid_autumn_user + userid);

midautumnview midautumnview = jsonobject.parseobject(midautumnstr, midautumnview.class);

long rank = stringredistemplate.opsforzset().rank(mid_autumn,

convview2itemstr(midautumnview));

if (rank != null && rank > top_num)

return midautumnviews;

}

提交新分數的邏輯
public midautumnview putscore(redisrankitem redisrankitem)  else 

return midautumnview;}}

為了排錯,最後使用者的每次提交都會記錄到mong

基於redis的zSet集合做資料快取實現分頁查詢

最近公司要做手機頁面展示新聞文章資料查詢的優化工作,讓我提個優化方案。現狀是目前手機頁面的資料請求系統後台,系統後台然後呼叫其他系統的介面,返回分頁資料到前台展示,這樣一來,使用者每次下拉到頁面底部載入更多資料都要呼叫其他介面,使用者體驗顯然不是很好,那有沒有更好的方案呢?優化方案 redis正好適...

redis 六 redis的zset(有序集合)

相比於set,zset中會有乙個score屬性,用於set的排名。zadd 向zset中新增元素 sorce value zrem 刪除element zscore 獲取score zincrby 增加score zrange 獲取資料,start到end zrank 通過下標獲取排名 127.0....

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

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