基於redis的排行榜設計和實現


 

前言:
  最近想實現一個網頁闖關游戲的排行榜設計, 相對而言需求比較簡單. 秉承前廠長的訓導: “做一件事之前, 先看看別人是怎么做的”. 於是乎網上搜索並參考了不少排行榜的實現機制, 很多人都推薦了redis的有序集(sorted set). 我覺得十分的贊, 技術方案很難在超越已有的模型了, 就看業務上的需求, 做些小改動. 

相關文章系列:
  記得大概在一年前吧, 寫過兩篇關於排行榜的文章, 不過那是針對游戲平台(類似微信, 手Q等)而言的. 每個用戶都有自己的排行榜, 不是全局性的.
  • 社交游戲的排行榜設計和實現(1)
  • 社交游戲的排行榜設計和實現(2) 

有序集初體驗:
  先來看幾個后續會使用的redis命令語法:

	ZADD key score1 member1 [score2 member2] 
	添加一個或多個成員到有序集合,或者如果它已經存在更新其分數

	ZRANGE key start stop [WITHSCORES] 
	由索引返回一個成員范圍的有序集合。

	ZSCORE key member 
	獲取給定成員相關聯的分數在一個有序集合

	ZRANK key member 
	確定成員的索引中有序集合 

  更詳細和完整的命令, 請點擊該鏈接
  • 案例設計
  輸入5個學生的成績(name, score), 實現top-3的查詢, 修改某個同學的得分, 再次查詢top-3.
  1). 添加成績記錄
  添加 (lucy, 61), (lily 60), (uncle wang, 10), (lilei, 98), (hanmeimei, 99) 這5人的成績, 並假定class_rank 為sorted set的name.
  
  2). 第一次top-3查詢
  
  3). 更新uncle wang的分數
  
  注: zadd命令既可以添加, 也可以更新
  4). 再次top-3查詢
  
  場景的設計, 以及最后輸出的結果與預期符合.看來redis的sorted set滿足需求, 而且特別的方便.

原理淺析:
  有了前文的直觀體驗, 再來研究redis中的有序集合(sorted set), 究竟是何種數據結構, 它能提供什么樣的接口, 以及滿足什么樣的需求呢?
  我們來探究下它支持的功能, 首先當然就是支持按分值排序的功能. 由此可以猜測它底層是按score為key, name為value的tree結構(因為支持范圍查詢, 以及按分值排序). 但是該有序集又支持按name來修改score. 這樣需求下, 又演變成name為key, score為value的map結構了. 單獨的一種數據結構, 無法滿足其需求, 兩個都不可或缺. 那答案究竟是什么?
  redis源碼的定義如下:

typedef struct zset {
    // 字典
    dict *dict;
    // 跳躍表
    zskiplist *zsl;
} zset;

  這樣就比較清晰了, 它采用了復合結構, 字典維護了name=>score的映射表, 而跳躍表則維護了按score排序的列表. 按name和按score的范圍查詢都天然支持.
  具體的解讀,可參考<<redis 設計和實現--有序集>>.同時引用官文文檔的一張示意圖:
  

總結:
  其實我很早就想這篇文章,作為一個游戲編程的愛好者而言,排行榜作為一個基礎服務,必然會接觸到.早做准備必然是好事,后續如果有機會.我想依據實際的項目,來具體闡述一下,畢竟理論和實戰, 還是有所差異.

公眾號&游戲站點:
  個人微信公眾號: 木目的H5游戲世界
  
  個人游戲作品集站點,
 www.mmxfgame.com, 請點擊訪問http://120.26.221.54/. 

 


免責聲明!

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



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