我們的遊戲上個星期經曆了第一個資料合服。簡單說,就是把2個資料庫合并在一個資料庫,讓2個伺服器的玩家一起玩。
過程簡直是驚心動魄,最終還是安全完成任務。
本文就分享下合服的各種技術細節。
需求說明:
--------------------------
要把2個伺服器玩家合并,首先外部對玩家而言是不變的,包括了登陸遊戲的URL,遊戲中的角色等;但是物理上,確是一台伺服器一個資料庫。
簡單的說,一服的玩家用一服入口登陸,玩一服帳號;二服的玩家用二服入口登陸,玩二服帳號;
即使我只有1個帳號,但是不同入口登陸,依然能使用不同遊戲帳號進行遊戲。
資料庫設計
--------------------------
要實現合服,首先表主鍵必須全部使用代碼產生,並用伺服器編碼作為首碼。
例如我的一服表主鍵就是 001GMxxxxxxxxxxxxxxxx。 二服就是002GMxxxxxxxxxxxxxxxx。這樣合服的時候,就不需要對資料進行預先處理了。直接匯入。
其次,使用平台使用者使用一個帳號,登陸不同服,要獲得不同帳號,因此在遊戲的玩家表,要通過伺服器編碼進行區分,例如:
Usr_Profile
:usercode 主鍵
:username 平台帳號
:servercode 伺服器編碼
這樣,根據傳入的username+servercode就知道應該擷取什麼伺服器帳號了。
遊戲中,玩家通過暱稱識別對方,因此合服的時候,必須對暱稱進行修正,防止重複,因此所有暱稱都要添加尾碼。我們最終方案就是添加 .x服 這個尾碼。
有了這3方面保證,合服就變得簡單了。(簡單個屁。。。)
合服流程
--------------------------------
1. 資料庫分析準備
做事前都要先準備。因此首先要對資料庫表結構進行分析,判斷什麼表結構需要合服,什麼可以忽略。
我們遊戲有60多張表,其中僅僅27張表需要合并,其他的都是配置表、日誌表,都不需要合并。
2. 資料備份
這部不用說了,首先要對資料庫全備份,防止操作失誤,導致資料丟失了。一般就在本機MySQL建立一個backup資料庫, 然後使用bult insert進行複製,速度很快。當然,備份的時候,對於體積很大的日誌表,可以跳過了。
3. 資料刪減
這部分很重要,一個網頁遊戲有接近80%的帳號是死號,因此合服的時候必須先過濾掉死號。規則如下:等級小於10級、沒有儲值、最近登入時間大於30天的,全部清除。
然後,就是上文提到的27張表中,與被淘汰帳號相關的資料,也清除。
這個清除量實際上非常大的,我有張資料表接近30W資料,結果一清就清了20W,超級舒服。
4. 資料檢測
這部分也很重要,因為我們第二個伺服器當時配置錯了,沒有使用伺服器編碼作為主鍵,導致與一服資料存在衝突的可能,因此需要對27張表的主鍵進行檢測,判斷首碼是否002,如果不是,就要進行手動修正了。
5. 資料修正
這塊主要針對存在主鍵衝突的資料進行修正,一般用SQL即可,大概耗時30~60分鐘,我就用個SQL,例如 update xxx set pk = concat('001',substring(pk,4)),進行資料修複。
當然,修複前,需要對錶結構進行分析,不能出現遺漏,特別是外部索引鍵關聯。
6. 資料匯出
不要嘗試使用代碼等方式進行合服,速度太慢了。我使用SQLYog,對所有表進行匯出,其中插入配置為Bult Insert,匯入速度非常快。
7. 資料匯入測試
最終匯入的時候,要測試,看看匯出的SQL是否存在問題。
8. 匯入。
這部完成,合服成功了。
貌似非常簡單的步驟,實際上卻問題多多。接下來我將說明實際部署中存在的陷阱。
合服 生存大考驗
------------------------------
1. 合服的表結構不匹配
當時我合服的時候,發現表總是導不進去,提示主鍵重複。不可能的啊。。從一個不重複主鍵的表匯入會提示重複?
檢查了很久發現,服1的主鍵是21位,服2的主鍵是22位,結果匯入的時候22位的主鍵自動省略了最後一位,自然會產生了主鍵重複。。。
2. SQLYog該死的bug
SQLYog改表結構竟然和實際表結構不對應。我明明修改了char(100),可是資料庫一看,還是char(21). 最終只好用命令列修改。。
嗨。關鍵時候,這些工具總是找麻煩。
3. SQLYog匯入出錯竟然沒有提示
也是該死的工具問題,最後我使用navicat配合SQLYog進行操作。
4. 部分動態產生的資料,無法大量匯入
例如競技場排名,不允許出現相同排名。所以這塊資料需要在玩家登陸的時候自動產生。此類型資料都是動態產生的,無法通過批量修正,都需要通過遊戲邏輯進行補全。
因此,合服的時候,這塊資料將不參與合并。
合服曆險記
------------------------------
說了這麼多理論知識,接下來就說說那天我合服的經過。本來在測試機上一切順利的,不到2個小時就合并了。可是真正操作起來, 卻用了8個小時。。。。
開始還順利,3個多小時就做好了資料備份、刪除、修正。可是匯入的時候發現總是提示主鍵衝突,於是不斷找原因,1個小時過去,才發現原來表結構不匹配。暈死。
接下來導完資料,4個小時過去了,開服。一運行,玩家就投訴了,說中文亂碼、丟失裝備、丟失武將。
丟失裝備、武將問題,我又花了1個小時檢查,原來是潛在部分主鍵仍然丟失最後1位,導致找不到。這個時候,我不能停機,因此我對比2個資料庫有差異的表,產生一堆update的SQL,然後手動操作。可是發現SQL多了,SQLYog會卡死,遊戲也會卡死。我只好開了10多個SQLYog,採用並行方法,把SQL拆分成50一組,進行手動操作。。累死了。
對於武將名字亂碼,是當時產生SQL檔案的時候,編碼格式錯誤了。可是武將資料接近有3W條,不可能進行手動更新了,因此我寫了個更新程式,進行後台更新。這塊就花了1小時。
終於遊戲Exception少了,本來可以歇口氣了,結果運營說,玩家儲值失敗!我檢查代碼,原來儲值介面沒有使用servercode去區分玩家帳號,又是疏忽。
第二天,運營又投訴說,商會採集資源失敗,回去檢查,才發現原來漏了對帳號中商會主鍵進行修正,又是疏忽。
小結
----------------------------
本來已經提前預演了2天,沒有問題,可是上到戰場還是錯漏百出。
如果準備過於詳細,會導致發展緩慢。如果準備不充分,又會很多問題。這個是個進退兩難的情況。最終,我偏向了迅速準備,快速修正的方案。
畢竟,預演的時候找不到的問題,給再多的時間也不一定找到。還不如直接上戰場,隨機應變。