Redis 排行榜 相同分數根據時間優先排行


 

 

1. 需求

    Redis 提供了按分數進行排序的有序集合。 比如在游戲里面,比如戰斗力排行,充值排行,用默認的Redis 實現就可以達到需求。

    但是,比如等級排行,大家都是30級,誰先到30級誰第一。Redis 默認實現是,相同分數的成員按字典順序排序(0 ~9 , A ~Z,a ~ z),所以相同分數排序就不能根據時間優先來排序。

    需要設計一個 【分數 = 等級 + 時間】 ,誰分數大誰第一,最后再根據分數能解析出來等級即可。

 

2.設計

    分數 = 等級 + 時間 (當前系統時間戳)

    分數是 64位的長整型 Long (有符號)

 

    1) 設計方式一

         long 分數,二進制用高 32位存 等級,低32位存時間(秒精度),那么數據看起是這樣

         A 玩家, 10 + 1111111111(時間戳)     

         后來 B 玩家也到 10 級, 10 + 2222222222(時間戳)         

         

         這樣排序,最終還是 B 玩家 會排到第一名,不能達到目的。

 

    2) 設計方式二    

         long 整數長度總共有 19位,923XXX.......,時間戳 毫秒精度 是 13位,所以只需 14 ~ 19 位存 等級,其他13位存時間。接下來看怎么存。

         等級偏移: Math.power(10, 14) = 10000000000000000(14位)

         這里有一個最大時間 MAX_TIME = 9999999999999 (13位)

         A 玩家,(10 * 等級偏移) + MAX_TIME - 11111111111111( 時間戳),最終分數 10888888888888888

         B 玩家,(10 * 等級偏移) + MAX_TIME - 22222222222222( 時間戳),最終分數 10777777777777777

         

         最終排序,A 玩家依然是第一。通過分數可以解析出真實 【等級 = 分數 / 等級偏移,取整】

 

3. 劣勢

    1) 如果有三個,四個排序條件怎么辦,這種情況還是推薦使用數據庫,就別考慮 Redis了 。Redis 優勢在於可以做到實時排行

    2) 方式二 14 ~ 19位,那么等級最大數據就只能是 919999,超過這個數就會溢出。可以把時間戳降低到秒級別,可以支持更大數字

 

4. 總結

    以上設計主要還是針對游戲內排行榜,並不能涵蓋所有行業,只能說是借鑒作用,僅供參考。

 

 

// 萬仙陣排名變化
public void updateWanxianzhePoints(final String avatarId, final int points) {
jedisTemplate.execute(new JedisCallback() {
  @Override
  public Object doInJedis(Jedis jedis) {

  long updateTime = System.currentTimeMillis();
  double timeRank = points + 1 - updateTime / Math.pow(10, (int) Math.log10(updateTime) + 1);
  jedis.zadd(FsGameDbConstants.KEY_LIST_WANXIANZHEN_POINTS, timeRank, avatarId);
  LoggerHelper.infoParams("updateWanxianzhePoints avatarId=", avatarId, " points=", points);
  return null;
    }
  });
}

 

取出來轉化成整型

int points = Double.valueOf(rr.getScore()).intValue();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM