• <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

            博客搬家了哦,請(qǐng)移步
            叫我abc

            常用鏈接

            留言簿(12)

            隨筆分類

            我的博客

            搜索

            •  

            積分與排名

            • 積分 - 305322
            • 排名 - 84

            最新評(píng)論

            閱讀排行榜

             

            需求

            表面上看,就是服務(wù)器崩潰重啟后,還能將關(guān)鍵數(shù)據(jù)恢復(fù)到崩潰前的那一刻,達(dá)到這種效果,角色的金錢、裝備和道具都能恢復(fù)到崩潰前的狀態(tài),不會(huì)有嚴(yán)重的損失。

            先假定所謂的關(guān)鍵數(shù)據(jù)都有哪些,以及這些數(shù)據(jù)有什么特性:

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

            屬性數(shù)據(jù)頻繁修改,讀寫性強(qiáng)。

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

            物品數(shù)據(jù)有歸屬性,總是屬于某個(gè)角色,或者無(wú)主被刪除。這種數(shù)據(jù)的歸屬性容易轉(zhuǎn)移,經(jīng)常需要分配和釋放。

             

            這些關(guān)鍵數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)通常是這樣子的:

            struct Item

            {

            int id;

            int belong;

            int data[32];
            };

             

            struct Cha

            {

              int id;

              int atb[ 128 ];

              Item* item_head;

            };

             

            能滿足易于修改,易于分配和釋放,并能像上面的數(shù)據(jù)結(jié)構(gòu)那樣組織起來(lái),只有內(nèi)存能做到。但是,在崩潰重啟后,普通內(nèi)存屬于不可恢復(fù)資源,因此就要考慮共享內(nèi)存了。

            共享內(nèi)存

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

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

            因此,要想用共享內(nèi)存實(shí)現(xiàn)上述需求,需要一個(gè)方案。

            方案

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

            1.      MemRecord

            分配器用來(lái)記錄一次內(nèi)存分配的相關(guān)信息,其結(jié)構(gòu)如下:

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

            其中sizedata buffer的長(zhǎng)度;

            data buffer是應(yīng)用戶請(qǐng)求分配的內(nèi)存,其地址作為分配結(jié)果的返回值;

            type id則表明了這段內(nèi)存的用途。

             

            通過(guò)MemRecord,一個(gè)分配器的基本管理元素就有了。

            每次用戶請(qǐng)求內(nèi)存,都相應(yīng)的分配一個(gè)MemRecord,包含被請(qǐng)求的內(nèi)存,和記錄這段內(nèi)存的大小和用途;

            每次用戶釋放內(nèi)存,只要對(duì)內(nèi)存指針做一下偏移,就能得到相應(yīng)的MemRecord,然后把MemRecord放入空閑隊(duì)列,留待下次請(qǐng)求分配。

             

            MemRecord里最重要的就是type id,直接關(guān)系到是否能從共享內(nèi)存中恢復(fù)分配器的狀態(tài)。系統(tǒng)目前保留2個(gè)id值:

            0-       表示這段內(nèi)存是主內(nèi)存,在沒(méi)有空閑的MemRecord的情況下,用戶請(qǐng)求的內(nèi)存都從這里分配出去;

            1-       表示這段內(nèi)存是已經(jīng)分配過(guò)并被釋放了的,標(biāo)記為1MemRecord總是放進(jìn)空閑隊(duì)列中。

             

            其他id值,則是留給用戶使用的,用戶必須指明他所請(qǐng)求的內(nèi)存是什么類型/用途,以便于崩潰以后的數(shù)據(jù)恢復(fù)。

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

             

            通過(guò)MemRecordtype id,分配器就可以從共享內(nèi)存中恢復(fù)狀態(tài),并把已分配給用戶的內(nèi)存交給用戶,由用戶恢復(fù)數(shù)據(jù)的邏輯意義。

            2.      MemChunk

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

            一個(gè)MemChunk最初會(huì)被初始化成一個(gè)type id值為0MemRecord,即主內(nèi)存,隨后用戶不斷的申請(qǐng)內(nèi)存的分配和釋放,MemChunk就分成了一連串的MemRecord集合。

             

            一個(gè)分配器的重建,其實(shí)就是旗下所有MemChunk的重建;而MemChunk的重建,就是區(qū)分不同的MemRecord的過(guò)程。

            3.      FileHeader

            再次強(qiáng)調(diào)共享內(nèi)存其實(shí)是一個(gè)文件,既然在文件上有組織的保存數(shù)據(jù),最好相應(yīng)的有一個(gè)文件頭描述這種組織。

            在當(dāng)前方案下,文件頭至少要包含以下幾條,以便于從整個(gè)共享內(nèi)存中重建分配器:

            1.         文件大小

            2.         每個(gè)MemChunk的大小

            3.         已經(jīng)分配出來(lái)的MemChunk的數(shù)量

             

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

            實(shí)驗(yàn)程序

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

            點(diǎn)擊這里下載代碼

            以下的程序按其啟動(dòng)順序逐個(gè)簡(jiǎn)述:

            1.         test_daemon,共享內(nèi)存守護(hù)進(jìn)程。啟動(dòng)后創(chuàng)建一塊200M的共享內(nèi)存,然后死循環(huán);

            2.         test_write,啟動(dòng)后讀取200M的共享內(nèi)存,然后創(chuàng)建一批角色數(shù)據(jù)和物品數(shù)據(jù),并隨機(jī)的刪除這些角色和物品;

            3.         test_read,啟動(dòng)后讀取200M的共享內(nèi)存,并從中恢復(fù)test_write分配出來(lái)的角色和物品。

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

            遇上的問(wèn)題

            1.         字節(jié)對(duì)齊問(wèn)題

            說(shuō)來(lái)慚愧,計(jì)算MemRecord中到最后一個(gè)變量m_data前的大小,我居然用sizeof(MemRecord)-1,結(jié)果出錯(cuò)了。

            因?yàn)榇嬖谧止?jié)對(duì)齊,所以大小應(yīng)該是m_data的偏移量才對(duì)。

             

            2.         MapViewOfFile的偏移量對(duì)齊問(wèn)題

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

             

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

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


            哈,我覺(jué)得也是.


              回復(fù)  更多評(píng)論
              
            # re: 崩潰后重啟,用共享內(nèi)存恢復(fù)你的數(shù)據(jù) 2010-09-26 10:37 true
            共享內(nèi)存畢竟是一種進(jìn)程間通訊技術(shù),如果將對(duì)內(nèi)存的操作全部轉(zhuǎn)為對(duì)共享內(nèi)存的操作,恐怕會(huì)有數(shù)量級(jí)的性能損耗,如果有dbproxy的話,可以縮短持久化數(shù)據(jù)的時(shí)間,也僅僅是將數(shù)據(jù)通過(guò)tcp連接發(fā)送給dbproxy,小概率的短時(shí)間回檔我覺(jué)得可以接受的,當(dāng)然最好是不崩潰,或者崩潰后不丟失數(shù)據(jù)。你們線上系統(tǒng)使用共享內(nèi)存的效果如何?  回復(fù)  更多評(píng)論
              

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久精品www人人爽人人| 精品久久久久久久久中文字幕| 国产精品久久成人影院| 亚洲午夜久久久久妓女影院| 亚洲а∨天堂久久精品| 久久天天日天天操综合伊人av| 国产精品伊人久久伊人电影| 国产午夜福利精品久久| 久久综合丁香激情久久| 色综合久久久久| 国产成人综合久久精品尤物| 中文字幕亚洲综合久久2| 久久99精品久久久久久9蜜桃| 久久精品18| 综合人妻久久一区二区精品| 日韩av无码久久精品免费| 精品久久久久久| 久久国产精品偷99| 国产精品久久久久久久app| 一本色道久久88—综合亚洲精品 | 丰满少妇人妻久久久久久| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 午夜人妻久久久久久久久| 久久这里只精品国产99热| 久久精品国产91久久综合麻豆自制| 国产精品九九久久免费视频| 久久艹国产| 久久综合给合综合久久| 久久伊人精品青青草原高清| 国产精品久久一区二区三区| 久久久久亚洲AV无码麻豆| 狠狠综合久久综合88亚洲| 伊人久久成人成综合网222| 久久夜色撩人精品国产| 国产午夜精品理论片久久| 91精品国产91久久久久久青草 | 成人午夜精品久久久久久久小说| 久久精品无码专区免费东京热| 色欲久久久天天天综合网精品| 亚洲精品乱码久久久久久自慰| 伊人久久大香线蕉综合Av|