2017-01-09 74 views
0

我正在開發基於MySQL的多人遊戲匹配系統。我有三個表:對接,遊戲GameScores實現SQL匹配

當玩家做一個牽線搭橋的要求,我們嘗試從對接會求n對手,然後我們創建一個遊戲遊戲GameScore行與引用播放器和遊戲 N個。

  1. 選擇對接會 LEFT JOIN GameScores ON 對接會 .player = GameScores .player和GameScores .player IS NULL ...(玩家不GameScore
  2. INSERT 遊戲
  3. INSERT GameScore
  4. 當比賽結束後,GameScores被刪除這樣的球員是在步驟1中找到再次

GameScore是玩家唯一的。當系統得到高頻率的請求時,這會導致很多錯誤,因爲其他人已經將此播放器添加到GameScore

所以第1步是由多個客戶端同時進行的,他們試圖在第3步

我試圖做牽線搭橋之前鎖定表添加相同的玩家不同的遊戲,但是這導致服務器速度變慢太多了。

對接是一個臨時表,包含對玩家數據和上次ping時間的引用。也許這個數據應該在MySQL之外以獲得更好的性能?

有沒有其他方法可以做得更好?可能memcached或類似的共享內存多個進程和/或服務器?

服務器運行在多個內核(NodeJS)上,未來甚至可能是多個服務器。

+2

請閱讀[我可以問什麼主題](http://stackoverflow.com/help/on-topic) 和[如何提出一個好問題](http://stackoverflow.com/help/how - 問) 和[完美的問題](http://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) 以及如何創建[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve) – RiggsFolly

+0

最終,我認爲這樣做的正確方法是擺脫Matchmaking表併爲匹配請求使用適當的消息隊列。然後,您可以使用消息代理(如RabbitMQ)將匹配處理正確分發到多個核心。 –

回答

0

下面是使用SQL表跨內核分配工作任務的技術:

  1. 分配一個唯一的ID給每個核心
  2. 列ProcessingByCore添加到婚介
  3. 修改你的第一個SQL查詢看起來更像這樣:

    UPDATE dbo.Matchmaking 
    SET ProcessingByCore = @coreId 
    FROM Matchmaking m 
    LEFT JOIN GameScores gs 
    ON m.player = gs.player 
    WHERE gs.player IS NULL 
    AND m.ProcessingByCore IS NULL 
    
  4. 您現在可以通過ProcessingCoreId進行選擇。

這是可行的,因爲UPDATE是原子的,所以本質上它只是鎖定表,儘管它的範圍較小。

當然,這種方法的主要問題是當核心在沒有釋放Matchmaking行的情況下死亡時會發生什麼。這些球員將永遠留在比賽隊列中。您可以添加另一個進程,該進程至少驗證所有ProcessingByCore ID是否都有關聯且運行正常的核心。

就像我在評論中所說的那樣,使用SQL表來分發工作對於工作來說是錯誤的工具。你需要一個消息隊列。

+0

FROM必須是拉取一行(限制1)的子查詢,然後在主鍵上匹配,否則將更新整個表而不是單個行,除非更新所有匹配的行是您的願望。 –

+0

從我對這個問題的理解中提取所有匹配的行是期望的行爲,儘管這看起來似乎是矯枉過正。我認爲人們只想在一場比賽中儘可能多地吸引球員。如果涉及MMR,問題會變得更加複雜,但這些細節都不包含在問題中。 –