基於redis的排行榜設計和實現
http://www.cnblogs.com/mumuxinfei/p/5013357.html
前言:
最近想實現一個網頁闖關遊戲的排行榜設計, 相對而言需求比較簡單. 秉承前廠長的訓導: “做一件事之前, 先看看別人是怎麼做的”. 於是乎網上搜索並參考了不少排行榜的實現機制, 很多人都推薦了redis的有序集(sorted set). 我覺得十分的贊, 技術方案很難在超越已有的模型了, 就看業務上的需求, 做些小改動.
相關文章系列:
記得大概在一年前吧, 寫過兩篇關於排行榜的文章, 不過那是針對遊戲平臺(類似微信, 手Q等)而言的. 每個使用者都有自己的排行榜, 不是全域性性的.
•
• 社交遊戲的排行榜設計和實現(2)
有序集初體驗:
先來看幾個後續會使用的redis命令語法:
1 2 3 4 5 6 7 8 9 10 11 |
|
更詳細和完整的命令, 請點選該連結.
• 案例設計
輸入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原始碼的定義如下:
1 2 3 4 5 6 |
|
這樣就比較清晰了, 它採用了複合結構, 字典維護了name=>score的對映表, 而跳躍表則維護了按score排序的列表. 按name和按score的範圍查詢都天然支援.
具體的解讀,可參考<<redis 設計和實現--有序集>>.同時引用官文文件的一張示意圖:
總結:
其實我很早就想這篇文章,作為一個遊戲程式設計的愛好者而言,排行榜作為一個基礎服務,必然會接觸到.早做準備必然是好事,後續如果有機會.我想依據實際的專案,來具體闡述一下,畢竟理論和實戰, 還是有所差異.