聽上去共享記憶體和遊戲不太沾邊,但在遊戲伺服器上利用共享記憶體這個技術已經不是乙個新鮮的事了,暢遊和畫素早在天龍八部和尋仙就實現了這一應用(但不一定都像下面提到的這麼用)。
較早之前和同事討論過如何在現有框架裡利用共享記憶體這種程序間訪問統一資料的特點,最理想的應用方案是切合目前以場景為單位的邏輯程序分割方式,能訪問同乙個記憶體資料就意味著場景間的物體進出程序間完全可以不用傳遞資料就能完成,怪物跟著玩家跑到另乙個場景也成為很自然的事情,由於程序間使用的物件資料始終只有乙份,無縫大世界裡的冗餘單位的管理問題也就不存在了(atlas的解決方案是用中心抉擇伺服器來抉擇大世界重疊邏輯區里冗餘單位的資料歸哪乙個程序管理)。另乙個應用是資料和邏輯分離的方案,這意味著玩家資料從資料庫載入上來就放乙個地方,服務程序誰取誰用,比如聊天伺服器需要玩家名字時去共享記憶體取,拍賣伺服器需要操作金錢了去共享記憶體取,郵件伺服器要處理乙個郵件物品的提取了還是訪問的共享記憶體。功能程序之間的處理不會因為冗餘的資料而產生髒資訊,乙個功能邏輯需要幾個程序間協調時也顯得相對容易些,再來可以實現乙個程序來維護這個共享記憶體比如定時存檔,定時或延時改變某個資料。
這兩個方案聽上去很吸引人但都沒成型,原因很簡單:共享記憶體是一台機器上能訪問的,而之前設計的多程序處理不同邏輯的目的就是為了讓更多的機器能夠分擔運算,如果想用到共享記憶體意味著多個程序都必須放一台機器上,但樣一來程序的優勢就完全比不上執行緒了,執行緒間簡單的記憶體鎖訪問就能解決的問題幹嘛還非得動用到程序間的共享記憶體。
最近新加入個原暢遊的程式介紹他們天龍的共享記憶體才發現其實還有另一種簡單但確實已用於實戰的方案:玩家資料備份。在處理程序崩潰時可能產生的玩家資料回檔上,通用的就是採取n分鐘自動存檔一次的方法,但這個方法一來不可能把頻率提得很高,二來即便提高頻率了也不能保證玩家重要的資訊不在存檔前產生。百多號人的程式團隊很難保證程式在後期新功能上線時的能夠快速穩定,這時候保證玩家的資訊不被頻繁回檔成為優先解決問題。共享記憶體正好在很大程度上能解決這個問題,只需要乙個維護程序負責在邏輯程序崩潰的時候保留這塊共享記憶體(共享記憶體需要超過1的程序引用才能保證不被系統**),能保證在下次啟動邏輯程序前處理完存檔就行。天龍的共享記憶體策略核心是利用資料冗餘資料來保證備份,可以把共享記憶體的應用簡單理解成是程序專屬的小型資料庫,實際在邏輯程序裡依然有乙份玩家資料的本地記憶體資訊,在邏輯中需要修改玩家資訊時在更改本程序記憶體的同時更新共享記憶體的資料,另外乙個維護程序則負責資料載入和定時往資料庫存檔的工作,維護程序和邏輯程序間由於要操作同乙個物件的資訊所以訪問共享記憶體時都需要加解鎖操作(網上也能搜到這套方案的設計文件,呵呵) 這套策略確實簡單好用。
基於備份玩家資料這一目的,適合目前專案的方案也清晰了:維護程序就只管進入共享記憶體不訪問任何資料,邏輯程序啟動的時候負責遍歷已有的共享記憶體區域,如果裡面存在資料則判斷資料完整性後存檔,存檔結束以後釋放共享區域。這樣一來訪問共享記憶體也不用加鎖解鎖,維護程序只要啟動之後就一直pause住就行了也不必擔心會不會有什麼操作能導致它的崩潰;再來由於訪問沒有互斥也不需要另外操作乙份本地的記憶體來保證速度,直接操作共享記憶體裡的資料就行(目前的測試結果表明操作共享記憶體和操作本地記憶體效率一樣,1kw次下同為16ms),而且恢復也不用特殊寫,邏輯程序本身就有存檔邏輯。幸運的是現有邏輯程序裡用的屬性系統和這套方案對接起來也很容易,原有的設計目標就是把任何乙個場景物件能用到的可以被關心的資料(這類資料只包括策劃案裡提到的物件屬性而不包括程式執行時產生的那些,這些也正好是需要存檔的)統一放一塊連續記憶體中管理,按屬性註冊的型別和索引去訪問和修改。由於不是所有物件都需要共享記憶體的備份,能用到的只有和玩家相關的物件,比如玩家,buff,物品,公會等等這一類的,在屬性系統裡分配記憶體時需要提供2種allocator;一種基於本地記憶體池,一種基於共享的記憶體池。更加幸運的是這些allocatorace
按這種方案實現的版本目前執行良好,不過有個意外比較糾結,如果有2個不同的工程生成的exe要操作這塊記憶體會出現讀寫錯誤。。。比如維護程序和邏輯程序都訪問這塊記憶體,後訪問的就會有問題。但有同乙個工程生成的比如多個邏輯程序要訪問這塊記憶體卻沒這個問題。 這2個工程設定和記憶體對齊模式也都一樣的。。。好在目前看來維護程序的是用不到訪問這塊記憶體的。
利用binlog來恢復資料庫
開發庫和線上表結構有很多不一樣,分表個數也不同,我需要重新整理保持開發庫和線上一致,之前已經告知開發資料是否允許丟失,開發說資料可以不要了,直接丟掉,等我搞好之後開發告訴我部分資料 ring 是不能刪除的,我暈,只好想辦法來恢復資料了,沒有備份,不過還好有全部的binlog。1.根據binlog解析...
MySQL利用binlog來恢復資料庫
1.根據binlog解析出所有ring資料庫的所有sql mysql localhost mysqlbinlog no defaults database ring start datetime 2005 04 20 9 55 00 stop datetim 2009 04 08 08 05 00 ...
Oracle資料庫利用日誌挖掘來恢復誤刪除的資料
在資料庫操作中,當我們誤刪除了表 資料或者是檢視等,可以利用日誌挖掘oracle不完全恢復進行恢復,本文主要就介紹了利用日誌挖掘oracle不完全恢復來恢復資料的方法,接下來我們就開始介紹這一過程。實施該方法需要滿足兩個條件 1.db工作在歸檔模式下 2.有冷準備份的資料檔案。接下來我們介紹恢復過程...