移動互聯網實戰--社交游戲的排行榜設計和實現(2)


 

前言:
  游戲領域, 特別是移動端的社交類游戲, 排行榜成為了一種增強體驗交互, 提高用戶粘性的大法寶. 這邊講述在不同用戶規模下, 游戲服務化/游戲平台化趨勢下, 如何去設計和實現游戲排名榜. 本文側重講解Nosql在游戲排名榜中的作用. 小編(mumuxinfei)對這塊認識較淺, 所述觀點不代表主流(工業界)做法, 望能拋磚引玉.

秉承:
  上一篇文章, 詳見: 社交游戲的排行榜設計和實現(1) 

進階篇:
  隨着數據量/並發量的上漲, Mysql集群也呈現了一些疲態.
  (1). 數據庫分庫分表后, 表間的join事實上失去了意義. 要join的表數據在不同的庫中.
  (2). 數據庫的讀寫性能很容易達到上限.
  如何破解:
  我們先回過頭來看些表定義以及使用
  表tb_score使用user_id訪問score得分,其實user_id相當於key, score相當於value. 因此可借助Nosql的持久化key/value系統去實現,redis/mongodb/leveldb/hbase, 這樣無論在讀寫速度上, 還是在應用擴展性上,都獲得了很大的提升.
  表tb_friend借助user_id來獲取friend_id列表, 其本質相當於user_id為key, list<friend_id>為value, 而key對應value列表, 可借助redis(數據結構服務器),也可借助sorted key/value db系統. 這邊我們選用sorted key/value db, 因其數據按key的順序存儲.
  sorted key/value db的特點是:
  (1) 支持key的前綴查找
  (2) 支持批量/范圍查詢
  我們可以如下好友列表的key/value格式

key => user_id:friend_id
value => score

  評注:
  key=>user_id:friend_id表示friend_id為user_id的好友.
  那我們好友列表的查詢, 就演變為前綴為"user_id"的范圍查詢.
  系統演變: 關系型數據庫mysql轉化為Nosql系統.
  

緩存篇:
   分布式緩存, 永遠是互聯網界的狗皮膏葯, 無論什么疼痛, 貼一下總有療效. 緩存的引入也是見血封喉, 效果非常顯著, 不過需要注意數據一致性問題. 不過互聯網能忍受弱事務性/弱數據一致性(C), 而強調可用性和可擴展性(AP). 移動端游戲, 其實也是類似的執行策略(除了和錢相關的業務). 常用的緩存有memcache/redis, 這些都是hash型散列的內存緩存.
  簡單的采用Key/Value, 而不采用redis的key/sort-list的方式.
  value為json格式的列表:

json格式的內容 [{'user_id' : 'score'}, {'user_id' : 'score'}, {...}]

  排名相對靜止, 因此緩存系統能擋掉大部分的數據讀.

  但是引入緩存以后,數據的一致性,如何去保證?
  模擬如下應用場景:
  1). 好友破了新的記錄
  2). 新增/刪除好友關系
  這些情況發生后, 會更新好友的排行榜. 需要更新緩存, 使得緩存和后端服務的持久數據保持一致.
  那么如何去實現?
  這邊談談常見的三種思路
  1). 同步更新: 當好友添加/刪除以后, 主動刪除排行榜緩存. 而用戶的分數創新高后, 主動遍歷好友列表,通知刪除相應的緩存.
  2). 異步更新: 當好友添加/刪除, 或者用戶分數創新高, 其投遞一個事件到一個隊列中, 有隊列消費者做這個耗時的同步操作.
  3). 緩存定期刪除: 設定緩存key的有效期ttl, 不關注好友添加/刪除, 得分更新事件的發生, 允許數據的一致有一定的延遲. 
  這三種方案的優缺點, 可以對比如下:

  實時性 操作代價 擴展性
同步更新 最好 有副作用,嵌入好友添加/刪除代碼邏輯中, 響應變大 不好, 將來的好友添加/刪除邏輯會越發的臃腫
異步更新 一般 影響小 好, 引入隊列, 可以由不同消費端做不同的處理
緩存定期刪除 一般 幾乎無影響 ---

  評注: 通知排行版更新是個重操作,比較耗時, 同步操作會影響響應時間.
  對於游戲而言, 如果排行榜不是實時排名, 采用方案2/3, 都是可接受的. 對於方案3, 這種沒心沒肺的做法, 其實最簡單有效了(個人觀點).

服務/平台化
  當一個社交類App演化為一個平台時, 好友模塊和游戲模塊就自然分開了, 其數據庫/Nosql系統邏輯上不在一塊了,比如微信App, 其內部肯定把各類服務做了拆分, 其數據是彼此隔離的. 在這種服務/平台化的演進下, 好友特定的游戲排行榜, 又該如何破?
  我們假定如下的服務, 其交互流程如下.
  GameService/FriendService模塊
  
  評注:好友更新事件主動觸發Game模塊, 代價也特別大(如之上所述). 同時也需要Friend模塊添加相關的邏輯代碼,這使得模塊之間緊耦合了.
  借助隊列, 采用異步的方式來實現. 這相當於在模塊之間采用了觀察者(Observer)模式, 事件的觸發者只要簡單的投遞事件於(topic模式)隊列中. 然后由需要關注該事件的服務模塊主動去訂閱它. 新模式轉化為如下:
  
  評注: 通過隊列異步化事件, 采用訂閱的方式, 來實現解耦.
  服務平台化后, 這種做法, 在工業界常常被采用.

后記:
  本來只想寫一篇文章, 關於社區游戲排行榜的設計的. 但發現內容有些長, 於是就拆分成了兩篇, 里面的內容簡單的涉及了一些, 並沒有具體展開. 小編(mumuxinfei)對這塊還是入門尚淺, 如果有什么不足, 希望能指正.

 


免責聲明!

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



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