1. 程式人生 > >db伺服器在遊戲伺服器組中的作用

db伺服器在遊戲伺服器組中的作用

db(一般是mysql,或是類似的,比如mariadb)在遊戲伺服器中,啟動了資料落地的作用。遊戲伺服器可以直接和db建立訪問連線操作資料,或者通過一箇中間人(DbServer)來完成這個工作。本文,我們以獨立DbServer來分析帶來的好處,以及遇到的問題。

下文提到的一些優勢,如果不單獨封裝一個db伺服器(通過一個儲存模組的方式來實現)也可能可以做到。但如果有一個獨立的db伺服器時,更容易把這一點實現的比較純粹。

適配儲存過程,隱藏儲存細節

db伺服器可以做到,快取資料儲存到redis,超時資料mysql落地,而外層資料完全無感。同樣的,當底層進行儲存切換,或是升級時,只需要改動db伺服器的程式碼。舉一個例子,我們的伺服器支援部分機器人玩家進入遊戲,但是機器人玩家的資料我們不希望會改變,從而方便我們重複做一些效能測試。於是,我們再dbserver上做了差異化,機器人的資料載入後,不再接受資料回寫,感覺上是這些資料是隻讀的。

db伺服器可以額外做一層邏輯業務有關的cache。比如玩家登出後30分鐘,他的資料實際還在db伺服器上,再次登入不需要從mysql走一套。

外圍伺服器(這裡稱除了db伺服器,都是外圍伺服器)不再需要連結db相關的庫

外圍伺服器需要發起儲存,只能通過網路訊息等方式發起,而無法直接訪問資料庫。

隱藏儲存方案的細節

我們知道,每次mysql的訪問都需要建立一條單獨的mysql連線。而通過是同步的mysql訪問會獨佔當前執行緒一定的cpu時間。由此,我們自然可以推出,dbserver需要有一個執行緒池和一個連線池,這樣可以最大化mysql的儲存吞吐量。

如果這樣的連線池和執行緒池實現在所有的遊戲程序中(假設我們是一個多程序的伺服器組)。如果濫用,mysql的總連線數已經系統的匯流排程數容易暴漲;而如果非常謹慎開支,又無法最大化IO。而如果單獨放置在DBServer上來排程,就比較容易控制和排程這些資源,做到兼顧效能和資源浪費問題了。

隔離邏輯型別

在我們的方案中,大部分資料在db中都是以blob的形式儲存的。那麼,在dbServer中,我們需要有一個從物件轉換為byte[]的過程。而我們系統中只有註冊的儲存型別才能夠正常序列化。這就要求,邏輯伺服器中使用的資料結構和最終儲存的資料結構是一個數據結構(比如邏輯運算使用PackItem,儲存使用DbPackItem)。

這麼做的好處

型別功能清晰,歸屬明確。

儲存的資料欄位,不會因為邏輯的臨時需要,多儲存一些無用資料。也就是雙方(邏輯和儲存)不用互相遷就。

壞處也比較明顯,可能需要多一次物件建立和記憶體拷貝。

不足

載入週期變得更長,因為跨程序的緣故,如果是串聯讀取多個數據,需要進行非同步等待,程式碼複雜度和時間消耗都會增加。

增加了伺服器啟動和關閉的流程複雜性。比如邏輯伺服器因為需要取一些系統上次快取的資料來恢復遊戲,但必須等db伺服器啟動完成,才能這麼做。

儲存的資料結構增多時,需要定義大量的資料同步協議,相比於多執行緒可以限制性的直接操作(如果多執行緒情況下使用訊息傳遞資料的情況,和我們遇到的問題應該差不多),要繁瑣和難以維護一些。

伺服器組複雜度上升後的問題。比如如果db伺服器和邏輯伺服器的socket連線斷了,資料該怎麼辦。