原網(wǎng)址: 我們的游戲上個星期經(jīng)歷了第一個數(shù)據(jù)合服。簡單說,就是把2個數(shù)據(jù)庫合并在一個數(shù)據(jù)庫,讓2個服務(wù)器的玩家一起玩。 過程簡直是驚心動魄,最終還是安全完成任務(wù)。 本文就分享下合服的各種技術(shù)細(xì)節(jié)。 需求說明: -------------------------- 要把2個服
原網(wǎng)址:
我們的游戲上個星期經(jīng)歷了第一個數(shù)據(jù)合服。簡單說,香港空間,就是把2個數(shù)據(jù)庫合并在一個數(shù)據(jù)庫,讓2個服務(wù)器的玩家一起玩。
過程簡直是驚心動魄,最終還是安全完成任務(wù)。
本文就分享下合服的各種技術(shù)細(xì)節(jié)。
需求說明:
--------------------------
要把2個服務(wù)器玩家合并,首先外部對玩家而言是不變的,包括了登陸游戲的URL,游戲中的角色等;但是物理上,確是一臺服務(wù)器一個數(shù)據(jù)庫。
簡單的說,一服的玩家用一服入口登陸,玩一服賬號;二服的玩家用二服入口登陸,玩二服賬號;
即使我只有1個賬號,但是不同入口登陸,依然能使用不同游戲賬號進(jìn)行游戲。
數(shù)據(jù)庫設(shè)計
--------------------------
要實現(xiàn)合服,首先表主鍵必須全部使用代碼生成,并用服務(wù)器編碼作為前綴。
例如我的一服表主鍵就是 001GMxxxxxxxxxxxxxxxx。 二服就是002GMxxxxxxxxxxxxxxxx。這樣合服的時候,就不需要對數(shù)據(jù)進(jìn)行預(yù)處理了。直接導(dǎo)入。
其次,使用平臺用戶使用一個賬號,登陸不同服,要獲得不同賬號,因此在游戲的玩家表,要通過服務(wù)器編碼進(jìn)行區(qū)分,例如:
Usr_Profile
:usercode 主鍵
:username 平臺賬號
:servercode 服務(wù)器編碼
這樣,根據(jù)傳入的username+servercode就知道應(yīng)該獲取什么服務(wù)器賬號了。
游戲中,玩家通過昵稱識別對方,因此合服的時候,必須對昵稱進(jìn)行修正,防止重復(fù),因此所有昵稱都要添加后綴。我們最終方案就是添加 .x服 這個后綴。
有了這3方面保證,合服就變得簡單了。(簡單個屁。。)
合服流程
--------------------------------
1. 數(shù)據(jù)庫分析準(zhǔn)備
做事前都要先準(zhǔn)備。因此首先要對數(shù)據(jù)庫表結(jié)構(gòu)進(jìn)行分析,判斷什么表結(jié)構(gòu)需要合服,什么可以忽略。
我們游戲有60多張表,其中僅僅27張表需要合并,其他的都是配置表、日志表,都不需要合并。
2. 數(shù)據(jù)備份
這部不用說了,首先要對數(shù)據(jù)庫全備份,防止操作失誤,導(dǎo)致數(shù)據(jù)丟失了。一般就在本機(jī)MySQL新建一個backup數(shù)據(jù)庫, 然后使用bult insert進(jìn)行復(fù)制,速度很快。當(dāng)然,備份的時候,對于體積很大的日志表,可以跳過了。
3. 數(shù)據(jù)刪減
這部分很重要,一個網(wǎng)頁游戲有接近80%的賬號是死號,因此合服的時候必須先過濾掉死號。規(guī)則如下:等級小于10級、沒有充值、最近登錄時間大于30天的,全部清除。
然后,就是上文提到的27張表中,與被淘汰賬號相關(guān)的數(shù)據(jù),也清除。
這個清除量實際上非常大的,我有張數(shù)據(jù)表接近30W數(shù)據(jù),結(jié)果一清就清了20W,超級舒服。
4. 數(shù)據(jù)檢測
這部分也很重要,因為我們第二個服務(wù)器當(dāng)時配置錯了,沒有使用服務(wù)器編碼作為主鍵,導(dǎo)致與一服數(shù)據(jù)存在沖突的可能,因此需要對27張表的主鍵進(jìn)行檢測,判斷前綴是否002,如果不是,就要進(jìn)行手動修正了。
5. 數(shù)據(jù)修正
這塊主要針對存在主鍵沖突的數(shù)據(jù)進(jìn)行修正,一般用SQL即可,大概耗時30~60分鐘,我就用個SQL,例如 update xxx set pk = concat('001',substring(pk,4)),進(jìn)行數(shù)據(jù)修復(fù)。
當(dāng)然,修復(fù)前,需要對表結(jié)構(gòu)進(jìn)行分析,不能出現(xiàn)遺漏,香港服務(wù)器,特別是外鍵關(guān)聯(lián)。
6. 數(shù)據(jù)導(dǎo)出
不要嘗試使用代碼等方式進(jìn)行合服,速度太慢了。我使用SQLYog,對所有表進(jìn)行導(dǎo)出,其中插入配置為Bult Insert,導(dǎo)入速度非???。
7. 數(shù)據(jù)導(dǎo)入測試
最終導(dǎo)入的時候,要測試,看看導(dǎo)出的SQL是否存在問題。
8. 導(dǎo)入。
這部完成,合服成功了。
貌似非常簡單的步驟,實際上卻問題多多。接下來我將說明實際部署中存在的陷阱。
合服 生存大考驗
------------------------------
1. 合服的表結(jié)構(gòu)不匹配
當(dāng)時我合服的時候,發(fā)現(xiàn)表總是導(dǎo)不進(jìn)去,提示主鍵重復(fù)。不可能的啊。從一個不重復(fù)主鍵的表導(dǎo)入會提示重復(fù)?
檢查了很久發(fā)現(xiàn),服1的主鍵是21位,服2的主鍵是22位,結(jié)果導(dǎo)入的時候22位的主鍵自動省略了最后一位,自然會產(chǎn)生了主鍵重復(fù)。。
2. SQLYog該死的bug
SQLYog改表結(jié)構(gòu)竟然和實際表結(jié)構(gòu)不對應(yīng)。我明明修改了char(100),可是數(shù)據(jù)庫一看,還是char(21). 最終只好用命令行修改。
嗨。關(guān)鍵時候,這些工具總是找麻煩。
3. SQLYog導(dǎo)入出錯竟然沒有提示
也是該死的工具問題,最后我使用navicat配合SQLYog進(jìn)行操作。
4. 部分動態(tài)生成的數(shù)據(jù),無法批量導(dǎo)入
例如競技場排名,不允許出現(xiàn)相同排名。所以這塊數(shù)據(jù)需要在玩家登陸的時候自動生成。此類型數(shù)據(jù)都是動態(tài)生成的,無法通過批量修正,都需要通過游戲邏輯進(jìn)行補全。
因此,合服的時候,這塊數(shù)據(jù)將不參與合并。
合服歷險記
------------------------------
說了這么多理論知識,接下來就說說那天我合服的經(jīng)過。本來在測試機(jī)上一切順利的,不到2個小時就合并了??墒钦嬲僮髌饋?, 卻用了8個小時。。
開始還順利,3個多小時就做好了數(shù)據(jù)備份、刪除、修正??墒菍?dǎo)入的時候發(fā)現(xiàn)總是提示主鍵沖突,于是不斷找原因,1個小時過去,才發(fā)現(xiàn)原來表結(jié)構(gòu)不匹配。暈死。
接下來導(dǎo)完數(shù)據(jù),4個小時過去了,開服。一運行,玩家就投訴了,說中文亂碼、丟失裝備、丟失武將。
丟失裝備、武將問題,我又花了1個小時檢查,原來是潛在部分主鍵仍然丟失最后1位,導(dǎo)致找不到。這個時候,我不能停機(jī),因此我對比2個數(shù)據(jù)庫有差異的表,生成一堆update的SQL,然后手動操作。可是發(fā)現(xiàn)SQL多了,SQLYog會卡死,游戲也會卡死。我只好開了10多個SQLYog,采用并行方法,把SQL拆分成50一組,進(jìn)行手動操作。累死了。
對于武將名字亂碼,是當(dāng)時生成SQL文件的時候,編碼格式錯誤了??墒俏鋵?shù)據(jù)接近有3W條,不可能進(jìn)行手動更新了,因此我寫了個更新程序,進(jìn)行后臺更新。這塊就花了1小時。
終于游戲Exception少了,本來可以歇口氣了,結(jié)果運營說,玩家充值失??!我檢查代碼,原來充值接口沒有使用servercode去區(qū)分玩家賬號,又是疏忽。
第二天,運營又投訴說,商會采集資源失敗,回去檢查,才發(fā)現(xiàn)原來漏了對賬號中商會主鍵進(jìn)行修正,又是疏忽。
小結(jié)
----------------------------
本來已經(jīng)提前預(yù)演了2天,沒有問題,可是上到戰(zhàn)場還是錯漏百出。
如果準(zhǔn)備過于詳細(xì),會導(dǎo)致發(fā)展緩慢。如果準(zhǔn)備不充分,又會很多問題。這個是個進(jìn)退兩難的情況。最終,我偏向了迅速準(zhǔn)備,快速修正的方案。
畢竟,預(yù)演的時候找不到的問題,網(wǎng)站空間,給再多的時間也不一定找到。還不如直接上戰(zhàn)場,隨機(jī)應(yīng)變。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com