棋牌遊戲定時器模塊設計

棋牌遊戲定時器模塊設計

最近在研究棋牌遊戲,想在今年上半年出一款本地麻將。github上down了幾個麻將的模塊走讀了下,基本上可以做麻將的AI,算聽,記番功能,用JNA調用了下,很nice。
算法搞定以後就是後臺了,之前也接觸過幾個開源的遊戲後臺,這些開源後臺其實就是搭個架子,裏面的模塊都沒有,還需要自己壘。
我列了下棋牌後臺的兩個最重要的模塊:
1.定時服務器
棋牌遊戲裏有太多的定時任務了,特別是出牌倒計時,有1000個桌子就要有1000個定時任務併發。

2.網絡連接管理
上線了,掉線了,離線了,換終端了,需要重連,這些都需要專門的模塊管理

當然還有數據庫、異步調度、消息隊列、線程池、序列化等等這些基礎模塊

今天只說定時器模塊
現在一臺服務器併發個幾萬桌遊戲都很正常,定時任務的併發至少在幾萬以上。 我們廣電少點吧,好歹也要準備個幾千個併發能力。
很明顯單純的多線程肯定是不行的。
搜了下,都不合適,總覺得不夠優化,那隻能自己設計了

特點分析
1.併發高(這是肯定要concurrent並行容器了)
2.任務執行有先後次序(有點像隊列)
3.只執行現在時刻的到期任務(貌似讀區間和寫區間是分開的,不用鎖了?)
4.我理想的定時器要能記錄任何時間點的任務

解析
開始想用hashmap,但是在讀的時候,需要對任務執行時刻排序,爲什麼不能在寫任務的時候就排好呢?數據結構肯定是隊列無疑。
程序應該是這樣的,a一條任務隊列,很多遊戲線程會往隊列裏按時間順序插入任務。b定時服務主線程1ms輪詢一次隊列中第一個任務,如果到期,取出執行。
用什麼數據結構呢ConcurrentSkipList ,插入擁有O(logN)複雜度,刪除複雜度是O(1)可以說相當快了。

優化
1.時間軸分段?棋牌大多數倒計時都是在當前時刻15秒時(看你的遊戲規則),插入時間點過於集中。
2.10條或者100條list做負載均衡? 複雜度-1和-2 。但是主線程輪詢的時候需要對10個或100個數據進行排序,反而更差。

3.既然棋牌大多數都是1分鐘以內的定時,我在1分鐘以內的定時用輪盤實現,數量爲6000,每個時間片是10ms。每個時間片使用ConcurrentHashMap實現並行插入,插入複雜度是O(1),讀取複雜度也是O(1)。 當然一分鐘以外的定時任務,我們可以用ConcurrentSkipList記錄,並額外需要一個線程,不斷把SkipList中的定時任務轉移到1分鐘輪盤中。
雖然多了一個線程,但是無論是空間還是時間都是非常優化的。nice!!

4.“特點3”讀區間和寫區間是分開的,ConcurrentSkipList第一個元素的讀取複雜度是O(1)
5.(2019/02/19)優化“3”,需要多一條線程,細想還是不對,第一條線程在讀取時間輪盤以後,再讀取一下 ConcurrentSkipList的任務就好了,沒必要兩個線程。真實優化無止境啊 ,fuck!!!

總結
1 一分鐘以內的定時,用6000個ConcurrentHashMap組成一個時間輪盤,每個ConcurrentHashMap存儲10ms時間段的定時任務。
2 一分鐘之外的定時,用ConcurrentSkipList統一存儲。
3 thread1 定時輪詢當前時間片的ConcurrentHashMap,併發送具體任務給對應的worker執行。然後再讀取ConcurrentSkipList,併發送具體任務給對應的worker執行。
4 thread1 千萬不要阻塞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章