• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 119  文章 - 290  trackbacks - 0

            博客搬家了哦,請移步
            叫我abc

            常用鏈接

            留言簿(12)

            隨筆分類

            我的博客

            搜索

            •  

            積分與排名

            • 積分 - 303672
            • 排名 - 84

            最新評論

            閱讀排行榜

             

            需求

            表面上看,就是服務器崩潰重啟后,還能將關鍵數據恢復到崩潰前的那一刻,達到這種效果,角色的金錢、裝備和道具都能恢復到崩潰前的狀態,不會有嚴重的損失。

            先假定所謂的關鍵數據都有哪些,以及這些數據有什么特性:

            1.         角色基本屬性,比如姓名、年齡、性別、HP、MPmoney什么的。

            屬性數據頻繁修改,讀寫性強。

            2.         角色物品,比如裝備、道具、技能和寵物等。

            物品數據有歸屬性,總是屬于某個角色,或者無主被刪除。這種數據的歸屬性容易轉移,經常需要分配和釋放。

             

            這些關鍵數據的數據結構通常是這樣子的:

            struct Item

            {

            int id;

            int belong;

            int data[32];
            };

             

            struct Cha

            {

              int id;

              int atb[ 128 ];

              Item* item_head;

            };

             

            能滿足易于修改,易于分配和釋放,并能像上面的數據結構那樣組織起來,只有內存能做到。但是,在崩潰重啟后,普通內存屬于不可恢復資源,因此就要考慮共享內存了。

            共享內存

            共享內存其實是文件,所以會有“指針變量改成偏移變量更合適”的這種想法,但是我期望能像操縱普通內存上的數據一樣操縱共享內存上的數據,指針是必須使用的。

            另外,在需求上,角色的屬性數據和角色的物品數據都是數以千計、面臨不斷的分配和釋放的,而在文件上管理和維護離散的小塊的數據空間,不能像對付普通內存那樣直接。

            因此,要想用共享內存實現上述需求,需要一個方案。

            方案

            要靈活的分配和釋放空間,就要打造一個基于共享內存的內存分配器,不僅如此,還必須能在崩潰后從共享內存文件中重建這個分配器。

            1.      MemRecord

            分配器用來記錄一次內存分配的相關信息,其結構如下:

            ----size | type id | data buffer----

            其中sizedata buffer的長度;

            data buffer是應用戶請求分配的內存,其地址作為分配結果的返回值;

            type id則表明了這段內存的用途。

             

            通過MemRecord,一個分配器的基本管理元素就有了。

            每次用戶請求內存,都相應的分配一個MemRecord,包含被請求的內存,和記錄這段內存的大小和用途;

            每次用戶釋放內存,只要對內存指針做一下偏移,就能得到相應的MemRecord,然后把MemRecord放入空閑隊列,留待下次請求分配。

             

            MemRecord里最重要的就是type id,直接關系到是否能從共享內存中恢復分配器的狀態。系統目前保留2id值:

            0-       表示這段內存是主內存,在沒有空閑的MemRecord的情況下,用戶請求的內存都從這里分配出去;

            1-       表示這段內存是已經分配過并被釋放了的,標記為1MemRecord總是放進空閑隊列中。

             

            其他id值,則是留給用戶使用的,用戶必須指明他所請求的內存是什么類型/用途,以便于崩潰以后的數據恢復。

            比如,struct Itemtype id可以是10struct Chatype id可以是11。

             

            通過MemRecordtype id,分配器就可以從共享內存中恢復狀態,并把已分配給用戶的內存交給用戶,由用戶恢復數據的邏輯意義。

            2.      MemChunk

            服務器上的角色和物品數量不少,因此共享內存通常都會一下子分配得比較大,比如200M。但是并沒有必要一開始就把200M的文件映射到進程的內存空間上,我們可以每次只映射一小部分,如20M,這每次20M的部分,就是MemChunk。

            一個MemChunk最初會被初始化成一個type id值為0MemRecord,即主內存,隨后用戶不斷的申請內存的分配和釋放,MemChunk就分成了一連串的MemRecord集合。

             

            一個分配器的重建,其實就是旗下所有MemChunk的重建;而MemChunk的重建,就是區分不同的MemRecord的過程。

            3.      FileHeader

            再次強調共享內存其實是一個文件,既然在文件上有組織的保存數據,最好相應的有一個文件頭描述這種組織。

            在當前方案下,文件頭至少要包含以下幾條,以便于從整個共享內存中重建分配器:

            1.         文件大小

            2.         每個MemChunk的大小

            3.         已經分配出來的MemChunk的數量

             

            因為FileHeader的基址和大小都是固定的,一開始就可以讀取的,因此是保存分配器整體信息的不二選擇。

            實驗程序

            這一篇的表達能力有限,我也看出來自己完全沒法把這個東西講解清楚,所以,代碼才是最好的表述。

            點擊這里下載代碼

            以下的程序按其啟動順序逐個簡述:

            1.         test_daemon,共享內存守護進程。啟動后創建一塊200M的共享內存,然后死循環;

            2.         test_write,啟動后讀取200M的共享內存,然后創建一批角色數據和物品數據,并隨機的刪除這些角色和物品;

            3.         test_read,啟動后讀取200M的共享內存,并從中恢復test_write分配出來的角色和物品。

            test_writetest_read在最后都dump了當前的角色和物品到文件上,比較2個文件就能判斷方案是否正確了。

            遇上的問題

            1.         字節對齊問題

            說來慚愧,計算MemRecord中到最后一個變量m_data前的大小,我居然用sizeof(MemRecord)-1,結果出錯了。

            因為存在字節對齊,所以大小應該是m_data的偏移量才對。

             

            2.         MapViewOfFile的偏移量對齊問題

            如果不是用到multi view,根本不用關心這個問題。每一個view的起始偏移地址,不是隨意的,必須是某個值的整數倍,我這里是65536。具體的值,通過SYSTEM_INFO. dwAllocationGranularity讀取。

             

            posted on 2008-11-12 21:27 LOGOS 閱讀(6265) 評論(8)  編輯 收藏 引用

            FeedBack:
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-12 22:53 肥仔
            反正都是基于文件系統,直接寫文件不行嗎?沒有與其他進程共享內存通訊,為什么要MappingFile呢?難道速度有優勢?  回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 01:19 Fox
            很誘人的功能,先MARK一個,明天好好研究研究:D  回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 08:57 LOGOS
            @肥仔
            你可以試一下寫文件的,呵呵
            我沒試過  回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 12:49 Jeason Zhao
            共享一個文件寫入性能實在很低,而且弄得操作系統的IO頻繁,
            文章提出的方案的確有意思,JAVA有外部的緩沖實現,這個貌似等同的
            不同之處在于共享內存和Socket訪問的區別  回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 12:50 陳梓瀚(vczh)
            mapping file爆快,其中一個優點。  回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 15:22 飯中淹
            可以用保護線程
            把崩潰的信息記錄下來,順便把未保存的數據保存下  回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 19:36 imdavid
            # re: 崩潰后重啟,用共享內存恢復你的數據 2008-11-13 12:50 陳梓瀚(vczh)
            mapping file爆快,其中一個優點。


            哈,我覺得也是.


              回復  更多評論
              
            # re: 崩潰后重啟,用共享內存恢復你的數據 2010-09-26 10:37 true
            共享內存畢竟是一種進程間通訊技術,如果將對內存的操作全部轉為對共享內存的操作,恐怕會有數量級的性能損耗,如果有dbproxy的話,可以縮短持久化數據的時間,也僅僅是將數據通過tcp連接發送給dbproxy,小概率的短時間回檔我覺得可以接受的,當然最好是不崩潰,或者崩潰后不丟失數據。你們線上系統使用共享內存的效果如何?  回復  更多評論
              
            久久亚洲AV成人无码国产| 无码精品久久一区二区三区| 怡红院日本一道日本久久| 91精品国产高清91久久久久久| 99国产欧美久久久精品蜜芽| 久久国产V一级毛多内射| 亚洲日本久久久午夜精品| 漂亮人妻被黑人久久精品| 久久精品国产只有精品66| 国产A级毛片久久久精品毛片| 91精品国产9l久久久久| 香蕉久久久久久狠狠色| 欧美777精品久久久久网| 偷偷做久久久久网站| 久久黄视频| 99久久99久久精品国产片果冻| 国产激情久久久久久熟女老人| 久久精品国产亚洲av瑜伽| 大伊人青草狠狠久久| 久久男人Av资源网站无码软件| 久久久久久无码国产精品中文字幕| 久久精品中文闷骚内射| 久久精品国产2020| 欧美日韩精品久久久免费观看| 7国产欧美日韩综合天堂中文久久久久| 97久久国产露脸精品国产| 久久久久亚洲AV成人网| 成人午夜精品久久久久久久小说| 亚洲午夜久久久影院| 东方aⅴ免费观看久久av | 91精品国产高清久久久久久91| 三级三级久久三级久久| 伊人色综合九久久天天蜜桃| 久久久久无码精品国产app| 久久久久久av无码免费看大片| 99久久亚洲综合精品网站| 青青草国产精品久久| 色综合久久精品中文字幕首页| 久久精品国产一区| 99久久国产综合精品网成人影院 | 婷婷久久综合九色综合98|