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

            從需求角度看NOSQL發(fā)展

             

            早先當(dāng)640kb就足夠使用的觀點(diǎn)流行的時(shí)候,數(shù)據(jù)處理規(guī)模很小,需求也不多,于是簡(jiǎn)單的文件存儲(chǔ)即可滿足需求,發(fā)展一段時(shí)間之后ISAM之類(lèi)的簡(jiǎn)單存儲(chǔ)就可滿足需求,再之后sql流行,當(dāng)sql為了適應(yīng)各種需求變得越來(lái)越龐大的時(shí)候,效率也止步不前,在將緩存和多線程性能榨取完了之后,sql各項(xiàng)性能還只停留在滿足常規(guī)應(yīng)用的地步,難于處理1秒萬(wàn)次以上的讀寫(xiě)操作,也難于解決萬(wàn)個(gè)以上的并發(fā)連接,一般的企業(yè)不可能動(dòng)不動(dòng)就上硬件,所以nosql發(fā)展是時(shí)代的需要是需求的推動(dòng)。當(dāng)然一般sql對(duì)傳統(tǒng)企業(yè)還是足夠滿足的,所以我們?cè)?/span>nosql的發(fā)展上沒(méi)看到傳統(tǒng)企業(yè)的身影,只看到當(dāng)前發(fā)展最快的SNS公司積極推動(dòng)nosql不斷發(fā)展,著名的如:Facebook 推動(dòng)Cassandra發(fā)展,Linkedin推動(dòng)Voldemort發(fā)展,這都是最大的一類(lèi)sns網(wǎng)站,這些網(wǎng)站都有幾千萬(wàn)以上的用戶(hù),巨量數(shù)據(jù)讀寫(xiě),所以這些數(shù)據(jù)庫(kù)都是極其強(qiáng)調(diào)分布式應(yīng)用的,并不單純的強(qiáng)調(diào)每個(gè)點(diǎn)的讀寫(xiě)性能。再看小一點(diǎn)的mixi推動(dòng)的Tokyo CabinetTokoy Tyrantgreen.jp推動(dòng)Flare的發(fā)展,這些數(shù)據(jù)庫(kù)都滿足于幾千萬(wàn)條數(shù)據(jù)的高速訪問(wèn),也沒(méi)看到特別的強(qiáng)調(diào)并發(fā)性,只強(qiáng)調(diào)他們的速度,當(dāng)然幾千萬(wàn)條數(shù)據(jù)還是有可能全放在內(nèi)存里面的,就算放不下全部數(shù)據(jù)也至少可完全放下全部索引,這樣讀寫(xiě)當(dāng)然快了,據(jù)說(shuō)tt到億條之后寫(xiě)性能急劇下降,大概就是這個(gè)原因吧。純內(nèi)存式數(shù)據(jù)庫(kù)也必須要提一下,典型的如LiveJournal開(kāi)發(fā)的memcached以及另一個(gè)新秀Redis等,前面提到的tt也支持memcached的協(xié)議,雖然這類(lèi)數(shù)據(jù)庫(kù)有很多局限,但在某些場(chǎng)合的確又很適合,memcahced其實(shí)連持續(xù)存儲(chǔ)都不支持,為了解決持續(xù)存儲(chǔ)問(wèn)題,又有人發(fā)展了一些,如tt其實(shí)就是一個(gè)支持存儲(chǔ)的memcached,國(guó)內(nèi)新浪團(tuán)隊(duì)也給memcached加上berkeleydb支持持續(xù)存儲(chǔ)。

            上面說(shuō)了這么多,無(wú)非想說(shuō)一句話,需求推動(dòng)技術(shù)進(jìn)步,每一個(gè)技術(shù)進(jìn)步其實(shí)都是為了滿足某種需求的結(jié)果,就如google的三大基石bigtablegfsmap/reduce都是為了解決它的巨量數(shù)據(jù)而折騰出來(lái)的東西,google也正是靠這幾個(gè)核心技術(shù)把持了互聯(lián)網(wǎng)近十年的風(fēng)光。同理我們可以想見(jiàn),雖然百度沒(méi)有大力的宣傳他們的底層技術(shù),但我們很容易想到,他們一定也是需要這些技術(shù)的,而且他們內(nèi)部就算沒(méi)有這些技術(shù),但一定有類(lèi)似的接替代產(chǎn)品,否則支撐不了他們那么巨量的數(shù)據(jù),雖然替代產(chǎn)品未必有google的產(chǎn)品那么好,但大概是略差一點(diǎn)或相當(dāng)?shù)乃桨伞?guó)內(nèi)互聯(lián)網(wǎng)巨頭騰訊支持了國(guó)內(nèi)最大的im應(yīng)用 10億級(jí),最大的棋牌游戲近億在線,加上他們布局網(wǎng)絡(luò)門(mén)戶(hù),布局qzone等,都是巨量用戶(hù),可以想見(jiàn)他們一定有類(lèi)似的方案,早先聽(tīng)說(shuō)他們棋牌游戲是通過(guò)很多mysql + proxy來(lái)完成的,雖然這個(gè)方式現(xiàn)在看起來(lái)也不是很完美,但至少是一個(gè)可行的解決方案,臆測(cè)下可以這樣使用,proxy有個(gè)巨大的hash表,每個(gè)qqid計(jì)算一下就知道在哪個(gè)區(qū)段,重定向到哪個(gè)區(qū)段讀寫(xiě)數(shù)據(jù)即可,說(shuō)起來(lái)容易做起來(lái)難啊,就算我玩種菜都不知道遇到多少次他們數(shù)據(jù)出故障了,說(shuō)明他們的系統(tǒng)面對(duì)巨大數(shù)據(jù)壓力的時(shí)候還是碰到了很多問(wèn)題。國(guó)內(nèi)還有個(gè)公司不得不提,阿里巴巴淘寶,馬云團(tuán)隊(duì)發(fā)跡很快,淘寶每年不知道要成交多少筆,但他們的數(shù)據(jù)也是一個(gè)天量,看了下他們dba團(tuán)隊(duì)的主頁(yè),牛一點(diǎn)的dba都籠絡(luò)了不少,就是自己開(kāi)發(fā)能力稍弱了一點(diǎn),縱觀國(guó)內(nèi)對(duì)巨量數(shù)據(jù)需求最迫切的也就這幾家公司了,雖然之后的51、開(kāi)心網(wǎng)、盛大等也有類(lèi)似需求,但數(shù)據(jù)量總歸還是沒(méi)有超過(guò)前面幾家公司。

            在需求的推動(dòng)下,國(guó)內(nèi)的nosqlkey-value應(yīng)用也慢慢發(fā)展了一些,如張宴在新浪搞的memcachedb,到金山之后搞的dbcached,豆瓣開(kāi)發(fā)的beansdb等,還有一些沒(méi)開(kāi)源沒(méi)介紹不大為外界知道的應(yīng)該也有一些,但總的來(lái)看水平還是比較低,有點(diǎn)不成氣候的樣子,靠的大多是1-2個(gè)牛人支撐,離開(kāi)了這么幾個(gè)人就不行了,東西也沒(méi)人維護(hù),的確,離開(kāi)了巨量數(shù)據(jù)的需求一般的企業(yè)用sql就能滿足也不會(huì)去研究這些東西,少數(shù)小一點(diǎn)的互聯(lián)網(wǎng)企業(yè)有這個(gè)需求又沒(méi)有相應(yīng)的人才有能力去研究,年輕一點(diǎn)的開(kāi)發(fā)人員都在玩概念想做也做不出這些東西,畢竟做這些東西沒(méi)有很深厚的數(shù)據(jù)結(jié)構(gòu)知識(shí),沒(méi)有3-5年的深入編程磨練是不可能真正做好一個(gè)像樣?xùn)|西的,矛盾啊。

            最后說(shuō)下我最近在做的一個(gè)東西,分布式md5計(jì)算,這個(gè)東西網(wǎng)上隨便查一下就知道做的人不少,提供網(wǎng)站服務(wù)的都不少,但搜了幾篇文章,看了幾個(gè)網(wǎng)站www.cmd5.com www.md5.com.cn就知道,水平之低下超出了我的想象,基本上還是停留在用sql數(shù)據(jù)庫(kù)的層次上,根據(jù)這些網(wǎng)站寫(xiě)的時(shí)間節(jié)點(diǎn)感覺(jué)他們大多數(shù)時(shí)間就是在制造數(shù)據(jù),速度大概是幾個(gè)月制造幾十億條數(shù)據(jù),都號(hào)稱(chēng)有幾萬(wàn)億條數(shù)據(jù),但事實(shí)上提供公開(kāi)查詢(xún)的數(shù)據(jù)只有區(qū)區(qū)幾億條,其他都要收費(fèi)才能查詢(xún),天知道到底有沒(méi)有那幾萬(wàn)億條記錄,看上很吸引人,其實(shí)用處不算很大,用我最近整的md5數(shù)據(jù)制造方法1秒制造100w條數(shù)據(jù),1億條數(shù)據(jù)也就在2分鐘內(nèi)搞定,幾億條數(shù)據(jù)也不過(guò)10分鐘左右就生成好了,1億條記錄耗費(fèi)空間1.5G左右,不過(guò)10G左右空間即可,技術(shù)含量可見(jiàn)并不是很高。 其實(shí)我做這個(gè)項(xiàng)目并不是想做個(gè)類(lèi)似的網(wǎng)站,主要是覺(jué)得這個(gè)東西玩技術(shù)很有意思,可大可小,一臺(tái)機(jī)器也可玩,1T硬盤(pán)放600億數(shù)據(jù)沒(méi)問(wèn)題,1萬(wàn)臺(tái)機(jī)器也不多,全字母遍歷到10位就算是上1w臺(tái)機(jī)器也不夠用,分布式存儲(chǔ)分布式計(jì)算典型云計(jì)算概念,clientp2p可不p2p,很多技術(shù)元素都可參與其中,很有玩性的一個(gè)程序,所以就較上勁了,也好,正好練練技術(shù),玩玩nosql的概念。

            各種新興技術(shù)出來(lái)都看到國(guó)內(nèi)有深入分析,就說(shuō)nosql系列的吧,深入分析memcached,深入分析tt,深入分析Cassandra的文章不計(jì)其數(shù),到底也沒(méi)看到有幾個(gè)國(guó)人能寫(xiě)類(lèi)似的東西,分析得頭頭是道,做的時(shí)候白癡一樣,就算是使用都難用好,更別說(shuō)自己動(dòng)手做個(gè)這方面的好產(chǎn)品了,國(guó)情如此,略感欣慰的是國(guó)內(nèi)現(xiàn)在也有一些公司和一些高水平的人真正參與其中,未來(lái)還是有可能有所突破的,正入本文所說(shuō),需求會(huì)推動(dòng)技術(shù)發(fā)展,但短期肯定還是國(guó)外為主,國(guó)內(nèi)的產(chǎn)品最多是一絲點(diǎn)綴。

            posted @ 2010-10-03 14:18 袁斌 閱讀(409) | 評(píng)論 (0)編輯 收藏

            Jsonajax領(lǐng)域很流行,記得當(dāng)時(shí)看過(guò)它的介紹后很興奮,網(wǎng)上找了一些解析jsonc

             

            c++代碼,不過(guò)沒(méi)有找到特別好的,有的寫(xiě)得不錯(cuò)不過(guò)要依賴(lài)于boost,有的用c寫(xiě)的不大好用,好在json語(yǔ)法簡(jiǎn)單,參考了一些c/c++json解析代碼做了一個(gè)json類(lèi),最近又把去年寫(xiě)的json類(lèi)修改為unicode下使用,增了一些功能,現(xiàn)在CJsonw可以解析const char *型輸入,也可解析const wchar_t *型輸入,可解析ansi編碼、unicode編碼、utf8編碼的json文件。看看我的CJsonw定義:

             

                    JsonwType type;                     //Json類(lèi)型, true false null直接由類(lèi)型表示了

                    DWORD tag;                            //tag,用戶(hù)自用值,默認(rèn)為0

                    union

                    {

                            struct{

                                    wchar_t *cstring;//字符串型值

                                    int clen;            //cstring按照字符計(jì)算的分配個(gè)數(shù),包括可能的0

                            };

                            double dvalue;          //double

                            struct

                            {

                                    int ivalue;         //int

                                    DWORD dwhigh;       //高部

                            };

                            __int64 i64value;        //int64

                            OBJS *objs;                     //對(duì)象型值

                            ARRAYS *arrays;             //數(shù)組型值

                    };

            Sizeof(CJsonw) == 16

            OBJS類(lèi)型描述無(wú)序的key-value型數(shù)據(jù),ARRAYS描述 array型有序數(shù)據(jù),定義如下:

                    typedef CHashiW<CJsonw *, CJsonw *> OBJS;

                    typedef std::vector<CJsonw *> ARRAYS;

            支持以下構(gòu)造函數(shù):

                    CJsonw(JsonwType t=json_null);

                    CJsonw(int value);

                    CJsonw(__int64 value);

                    CJsonw(float value);

                    CJsonw(double value);

                    CJsonw(const wchar_t *value);

                    //數(shù)組型構(gòu)造函數(shù)

                    CJsonw(int *numbers, int count);

                    CJsonw(__int64 *numbers, int count);

                    CJsonw(float *numbers, int count);

                    CJsonw(double *numbers, int count);

                    CJsonw(const wchar_t **strings, int count);

            支持以下賦值函數(shù):

                    bool setnull();

                    bool set(bool value);

                    bool set(int value);

                    bool set(__int64 value);

                    bool set(float value);

                    bool set(double value);

                    bool set(const wchar_t *value);

                    bool set(int *numbers, int count);

                    bool set(__int64 *numbers, int count);

                    bool set(float *numbers, int count);

                    bool set(double *numbers, int count);

                    bool set(const wchar_t **strings, int count);

                   

                    //修改常規(guī)值,就是true, false, int, real, string

                    bool setbystring(const wchar_t *value);

             

            支持以下輸入:

                    bool parse(const char *string);

                    bool parse(const wchar_t *string);

                    bool parsefile(FILE *fp);

                    bool parsefile(LPCTSTR filename);

            文件可以ansi編碼、unicode編碼、或者utf8編碼

             

            支持以下wchar_t型輸出:

                    //dump,默認(rèn)為unicode編碼

                    //uunicode表示字符串中的unicode字符是否按照\uxxxx格式輸出

                    //bDisptrue按照友好格式顯示,會(huì)輸出\t換行等方便閱讀

                    //bDispfalse按照緊湊模式顯示,沒(méi)有多余字符,方便網(wǎng)絡(luò)傳輸?shù)葓?chǎng)合

                    bool dump(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=false, bool bDisp=true);

                    //跟上面的dump一樣,但如果成功會(huì)在buf里面插入一個(gè)'\0'字符

                    bool dump0(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=false, bool bDisp=true);

                    bool save(LPCTSTR filename);

                    bool save(FILE *fp);

            保存到文件默認(rèn)為UNICODE格式

             

            支持以下ANSI型輸出:

                    //a系列dumpansi編碼輸出

                    //bDisptrue按照友好格式顯示,會(huì)輸出\t換行等方便閱讀

                    //bDispfalse按照緊湊模式顯示,沒(méi)有多余字符,方便網(wǎng)絡(luò)傳輸?shù)葓?chǎng)合

                    bool dumpa(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=true, bool bDisp=true);

                    //跟上面的dump一樣,但如果成功會(huì)在buf里面插入一個(gè)'\0'字符

                    bool dumpa0(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=true, bool bDisp=true);

            ANSI型輸出主要用在節(jié)省網(wǎng)絡(luò)帶寬或者和其他系統(tǒng)交換數(shù)據(jù)的情況下。

             

            支持以下類(lèi)型判別函數(shù):

                    //類(lèi)型判別函數(shù)

                    bool IsArray() const { return type==json_array; }

                    bool IsObject() const { return type==json_object; }

                    bool IsInt() const { return type==json_int; }

                    bool IsReal() const { return type==json_real; }

                    bool IsNumber() const { return IsInt()||IsReal(); }

                    bool IsNull() const { return type==json_null; }

                    bool IsTrue() const { return type==json_true; }

                    bool IsFalse() const { return type==json_false; }

                    bool IsString() const { return type==json_string; }

             

            支持以下一些直接取值函數(shù):

                    const wchar_t *getordef(const wchar_t *strdef)

                    int getordef(int idef)

                    __int64 getordef(__int64 idef)

                    double getordef(double ddef)

                    bool getordef(bool bdef)

                    //array的元素

                    CJsonw *get(int n)

                    CJsonw *operator[](int n) const

                    //obj的元素

                    CJsonw *get(const wchar_t *name)

                    CJsonw *operator[](const wchar_t *name) const

             

            支持以下取array型子元素?cái)?shù)據(jù)的函數(shù):

                    const wchar_t *getordef(int n, const wchar_t *strdef)

                    int getordef(int n, int idef)

                    __int64 getordef(int n, __int64 idef)

                    double getordef(int n, double ddef)

                    bool getordef(int n, bool bdef)

             

            支持以下取obj型子元素?cái)?shù)據(jù)的函數(shù):

                    const wchar_t *getordef(const wchar_t *name, const wchar_t *strdef)

                    int getordef(const wchar_t *name, int idef)

                    __int64 getordef(const wchar_t *name, __int64 idef)

                    double getordef(const wchar_t *name, double ddef)

                    bool getordef(const wchar_t *name, bool bdef)

             

            支持以下obj遍歷函數(shù):

                    //遍歷函數(shù),最常見(jiàn)寫(xiě)法:

                    //for(CJsonw::OBJIT *p=xxx.FirstObj(); p; p=p->next())...

                    OBJIT *firstobj()

             

                    //arrayobject元素個(gè)數(shù),string類(lèi)型返回分配的字符個(gè)數(shù)(包括可能的),其他類(lèi)型都返回

                    int size() const

             

            另外支持一些增加array子元素函數(shù):

                    bool add(CJsonw *pnode)

                    bool del(int n, bool bfree=true)

                    bool addnull(){ return add(new CJsonw(json_null)); }

                    bool addtrue(){ return add(new CJsonw(json_true)); }

                    bool addfalse(){ return add(new CJsonw(json_false)); }

                    bool add(int value){ return add(new CJsonw(value)); }

                    bool add(__int64 value){ return add(new CJsonw(value)); }

                    bool add(float value){ return add(new CJsonw(value)); }

                    bool add(double value){ return add(new CJsonw(value)); }

                    bool add(const wchar_t *value){ return add(new CJsonw(value)); }

             

            也支持obj增加刪除子對(duì)象函數(shù):

                    bool addobj(const wchar_t *name, CJsonw *pnode)

                    bool delobj(const wchar_t *name, bool bfree=true)

                    bool addobjnull(const wchar_t *name){ return addobj(name, new CJsonw(json_null)); }

                    bool addobjtrue(const wchar_t *name){ return addobj(name, new CJsonw(json_true)); }

                    bool addobjfalse(const wchar_t *name){ return addobj(name, new CJsonw(json_false)); }

                    bool addobj(const wchar_t *name, int value){ return addobj(name, new CJsonw(value)); }

                    bool addobj(const wchar_t *name, __int64 value){ return addobj(name, new CJsonw(value)); }

                    bool addobj(const wchar_t *name, float value){ return addobj(name, new CJsonw(value)); }

                    bool addobj(const wchar_t *name, double value){ return addobj(name, new CJsonw(value)); }

                    bool addobj(const wchar_t *name, const wchar_t *value){ return addobj(name, new CJsonw(value)); }

             

            還有一些特殊函數(shù):

                    //計(jì)算整個(gè)樹(shù)的crc

                    DWORD calccrc();

                    //計(jì)算整個(gè)樹(shù)的md5,要求md5不少于個(gè)字節(jié)

                    byte *calcmd5(byte *md5);

                    //計(jì)算hex表示的md5,不寫(xiě)尾部,要求md5hex不少于個(gè)字符

                    char *calcmd5hex(char *md5hex, const byte x='x');

                    //計(jì)算hex表示的md5,寫(xiě)尾部,要求md5hex不少于個(gè)字符

                    char *calcmd5hex0(char *md5hex, const byte x='x');

             

             

            json類(lèi)上花了較多時(shí)間,主要是覺(jué)得這個(gè)類(lèi)很有用,可以描述任意對(duì)象,易保存易傳輸易構(gòu)造,對(duì)速度要求不苛刻的應(yīng)用程序用json作為基本數(shù)據(jù)結(jié)構(gòu)很合適,配合json里面的data自定義字段理論上支持描述任意對(duì)象,配合使用一些cache可擴(kuò)大json類(lèi)的使用范圍,用它取代ini xml等配置簡(jiǎn)直是大材小用,用json類(lèi)來(lái)做stringtable簡(jiǎn)直就是小菜一碟,而且還是hash級(jí)高效率,絲毫不比手工做一個(gè)hash_map<,>表差。

            在實(shí)際應(yīng)用中,去年有一個(gè)網(wǎng)絡(luò)驗(yàn)證的項(xiàng)目就大量使用了這個(gè)類(lèi),配置、幫助都是json格式,應(yīng)用中管理大量對(duì)象的內(nèi)存數(shù)據(jù)庫(kù)也是用了json類(lèi),編碼后直接網(wǎng)上傳輸,server內(nèi)部也是一個(gè)json對(duì)象直接管理了大量用戶(hù)的信息,非常方便,可以說(shuō)用json類(lèi)使得這個(gè)程序少寫(xiě)了大量代碼,也使得整個(gè)項(xiàng)目只用了1個(gè)月時(shí)間就做出來(lái)了,還部署成master – master- slave(N)模式穩(wěn)定運(yùn)行了將近1年時(shí)間。

            在另一些網(wǎng)絡(luò)應(yīng)用中,俺將json格式數(shù)據(jù)作為變長(zhǎng)包使用,前面俺寫(xiě)過(guò)一篇短文介紹了變長(zhǎng)包最常見(jiàn)的幾種格式,分別是:

            1、 key\0value\0…

            2、 json格式

            3、 xml格式

            使用json格式作為變長(zhǎng)包現(xiàn)在很流行,這也是大量ajax所采用所依賴(lài)的技術(shù),qq種菜,google搜索預(yù)列表都是采用json格式的。

            posted @ 2010-10-03 14:17 袁斌 閱讀(923) | 評(píng)論 (0)編輯 收藏

            HashCrack程序規(guī)劃

             

            最近幾天在思考如何遍歷md5找出原碼字符串,但九十多個(gè)可見(jiàn)字符,96^6 782757789696,就算只遍歷6位組合也是非常驚人的巨量數(shù)據(jù),單機(jī)根本無(wú)法完成,根據(jù)常用密碼合成規(guī)律,我們可以采用分而治之的方法解決,方法大致如下:

            1、 使用很多機(jī)器,機(jī)器越多覆蓋的范圍越大。

            2、 優(yōu)先覆蓋最常用的范圍,如全數(shù)字組合,小寫(xiě)字母組合,小寫(xiě)數(shù)字混合組合,大寫(xiě)字母組合,夾雜一個(gè)非字母數(shù)字字符的組合,之后覆蓋非常見(jiàn)組合,如所有可見(jiàn)字符的N個(gè)全排列。

            3、 采用c/s結(jié)構(gòu),中心機(jī)管理區(qū)段分配策略,優(yōu)先覆蓋常用區(qū)段,所有slavemaster一起構(gòu)成一個(gè)覆蓋網(wǎng)。

            4、 不僅支持md5,也支持sha等其他類(lèi)似算法。

            5、 Masterslave也支持添加字典,為了覆蓋盡可能多的組合,可添加任何合適的字典組合。

             

            實(shí)現(xiàn)難點(diǎn):

            1、 數(shù)據(jù)組織。

            方案一、考慮過(guò)磁盤(pán)存儲(chǔ)方案,研究了sqlite,寫(xiě)效率大概10w/s,加了索引大概5w/ssqlite存儲(chǔ)效率也不是很高,比berkeley存儲(chǔ)浪費(fèi)很多空間,加了索引后空間放大了一倍。也嘗試過(guò)berkeley方案,寫(xiě)效率大概只有4.5w/s,存儲(chǔ)相對(duì)sqlite緊湊一些。但由于寫(xiě)效率太低,都難于實(shí)現(xiàn)我所希望的一個(gè)slave一下分配1億數(shù)據(jù)量的模式(1億數(shù)據(jù)大概要占磁盤(pán)5-10G,最經(jīng)濟(jì)模式大概也要占2.xG)。由于對(duì)btree+不太熟悉,暫時(shí)還沒(méi)有找到高效的存儲(chǔ)方案。

             

            方案二、其實(shí)首先是考慮了內(nèi)存方案,用內(nèi)存相比磁盤(pán)其實(shí)要簡(jiǎn)單一些,不過(guò)受機(jī)器可用內(nèi)存的限制以及客戶(hù)接受程度的限制,難于讓一臺(tái)slave處理1億以上的數(shù)據(jù)量,默認(rèn)大概只能分配2000w-5000w左右的數(shù)據(jù)量(大概占用內(nèi)存400M-1.2G)。

             

            以上兩種方案其實(shí)選擇方案一更合適一點(diǎn),因?yàn)橐话愕臋C(jī)器擠2G左右的磁盤(pán)基本都沒(méi)有問(wèn)題,甚至20G-200G可能都問(wèn)題不大,但要持久占用1G內(nèi)存可能不大好,畢竟大多數(shù)用戶(hù)比容易接受。第一版暫時(shí)用了方案二,待高速寫(xiě)存儲(chǔ)方案做好后替換一個(gè)dll即可(該dll已經(jīng)留好了接口可直接替換)。

             

            2、 區(qū)段劃分

            單純的劃分某一個(gè)區(qū)段也是比較容易的,如10個(gè)數(shù)字的8個(gè)組合,可用如下方法表示

            Digits = “0123456789”

            Range(Digits, 8, 0, 20000000) 表示digits 8個(gè)字母的排列 [0,20000000]

            但將一些常用區(qū)段單獨(dú)出來(lái)之后涉及到和更大范圍字母全排列的重合情況就不大好扣出來(lái),暫時(shí)沒(méi)有找到較好的表示方法,好在小范圍排列被冗余也問(wèn)題不是很大,此表示方法待繼續(xù)研究,暫時(shí)采用冗余方案。

             

            3、 Master 發(fā)現(xiàn)機(jī)制

            其實(shí)這是一個(gè)經(jīng)典的問(wèn)題,可考慮得很復(fù)雜,也可考慮得很簡(jiǎn)單,由于我名下幾個(gè)域名都被禁止解析了,所以這個(gè)問(wèn)題變得不是那么方便,不過(guò)暫時(shí)還是用個(gè)域名部署一下最為簡(jiǎn)單,存儲(chǔ)空間也是個(gè)問(wèn)題,待我聯(lián)系幾個(gè)朋友看看能不能找到一個(gè)合適的存儲(chǔ)地點(diǎn),待找到后第一版就這么部署出去吧。

             

             

            實(shí)現(xiàn)方法:

            由于要有一個(gè)中心提供調(diào)度方案,因此該系統(tǒng)肯定有一個(gè)中心(不管是一個(gè)點(diǎn)還是N個(gè)點(diǎn)),所以考慮采用c/s模式,第一版采用一個(gè)masterN個(gè)slave的方案。

            master主要實(shí)現(xiàn)以下功能:

            1、 覆蓋最常用區(qū)段排列,籍此提供最基本的查詢(xún)服務(wù)。

            2、 支持大量slave接入(暫采用iocp模式接入)。

            3、 提供區(qū)段劃分功能,slave接入斷開(kāi)自動(dòng)分配區(qū)段,優(yōu)先分配常用區(qū)段,其次分配非常用區(qū)段。

            4、 查詢(xún)轉(zhuǎn)發(fā)功能,接收slave的查詢(xún)請(qǐng)求,轉(zhuǎn)發(fā)給其他slave

             

            slave實(shí)現(xiàn)以下功能:

            1、 master交互,接收分配的區(qū)段,處理區(qū)段內(nèi)的數(shù)據(jù)并提供該區(qū)段數(shù)據(jù)查詢(xún)服務(wù)(此功能由一個(gè)接口dll實(shí)現(xiàn),可輕易替換)。

            2、 支持查詢(xún)功能。

            3、 在客戶(hù)端還計(jì)劃支持apislaveapiproxyapi通過(guò)消息向slave發(fā)送查詢(xún)請(qǐng)求,slave通過(guò)給master發(fā)送查詢(xún)請(qǐng)求,在整個(gè)群落里面提供查詢(xún)服務(wù),此功能為該體系的一大亮點(diǎn),暫時(shí)沒(méi)考慮做什么限制,主要為吸引用戶(hù)提供很主動(dòng)的編程功能,第一版通過(guò)一個(gè)cdll提供api調(diào)用功能,在此api基礎(chǔ)上用戶(hù)應(yīng)該可以很容易包裝出其他語(yǔ)言的調(diào)用接口,如luapython的接口等。

             

             

            進(jìn)度說(shuō)明:

            由于該項(xiàng)目只是一個(gè)即興性項(xiàng)目,沒(méi)打算耗費(fèi)很多時(shí)間,計(jì)劃在一周內(nèi)完成,已經(jīng)過(guò)去了3天,所以在細(xì)節(jié)上暫時(shí)無(wú)法抽出很多時(shí)間仔細(xì)研究,待整體功能成型后看情況再斟酌算法,易改變部分暫時(shí)都用接口dll實(shí)現(xiàn),該項(xiàng)目代碼部分大概完成了一半左右,未來(lái)2-3天左右大概可以做完第一版。

            posted @ 2010-10-03 14:17 袁斌 閱讀(199) | 評(píng)論 (0)編輯 收藏

            簡(jiǎn)單總結(jié)下asp.net狀態(tài)維持方法如下:

            client端狀態(tài)
            1、ViewState
            2、ControlState
            3、Hidden Field (post 模式)
            4、Cookie
            5、QueryString (get 模式)

            server端狀態(tài)
            1、Application (全局)
            2、Cache (全局)
            3、Session (current session,配合后臺(tái)驅(qū)動(dòng)可將session持續(xù)化到很多地方,如xml,
            或者db、或者memcached 等地方)
            4、配置文件(asp.net有一個(gè)sqlprofileProvider類(lèi)使您可將配置文件數(shù)據(jù)保存到sql數(shù)據(jù)庫(kù)中)
            5、db

            對(duì)保持連接的c/s程序來(lái)說(shuō),client端狀態(tài)我們不是特別關(guān)心,除了cookie也有一些參考意義,其他幾種方法很難直接在普通cs程序里面對(duì)應(yīng),對(duì)server端程序開(kāi)發(fā)來(lái)說(shuō),asp.net的server端數(shù)據(jù)持續(xù)方法對(duì)我們很有參考價(jià)值,對(duì)一般的游戲程序來(lái)說(shuō),db是必然會(huì)用的,配置文件型的也可參考使用,session型的很多程序都在使用,application型的緩存估計(jì)也有很多程序在用,更有價(jià)值的是cache型,我們一般的s程序基本都沒(méi)有實(shí)現(xiàn)時(shí)效性cache和文件觸發(fā)性cache,asp.net的cache對(duì)我們很有參考價(jià)值。當(dāng)然我們不必生搬硬套的照搬web上的概念,只要學(xué)到精髓就可以了,總之,還是我堅(jiān)持的那句話,俠義地說(shuō)是從web架構(gòu)學(xué)習(xí)server端程序設(shè)計(jì),更廣義地說(shuō)是從web架構(gòu)學(xué)習(xí)一般網(wǎng)絡(luò)應(yīng)用程序設(shè)計(jì)。

            posted @ 2010-10-03 14:16 袁斌 閱讀(176) | 評(píng)論 (0)編輯 收藏

            寫(xiě)了tmpool之后又發(fā)現(xiàn)居然有tcmalloc,而且比牛逼的ptmalloc好很多,真感嘆啊,世界上好東西很多,但需要智慧的眼光去發(fā)現(xiàn)。在linux下簡(jiǎn)單比較了一下malloc和tcmalloc,快的真不是一點(diǎn)點(diǎn)啊,看到好多人用tcmalloc去重編譯mysql, squid,nginx等。簡(jiǎn)單看了下tcmalloc的原理,比我寫(xiě)的tmpool要多一些整理的功能,大概tmpool就是tcmalloc在win下的子集,俺的tmpool區(qū)區(qū)800行代碼自然是不能去跟tcmalloc比的,不過(guò)對(duì)付一般的server端程序還是夠用的,經(jīng)過(guò)一段時(shí)間的使用效果也還可以,待有時(shí)間對(duì)比下俺的tmpool和tcmalloc。

            posted @ 2010-10-03 14:16 袁斌 閱讀(1108) | 評(píng)論 (0)編輯 收藏

            常見(jiàn)cs程序自定義數(shù)據(jù)包描述

             

            常見(jiàn)cs程序自定義包可分為塊型包、非塊型包,非塊型包如http協(xié)議的,用\r\n\r\n結(jié)束,我們這里重點(diǎn)討論塊型包,塊型包常見(jiàn)頭部如下:

            Struct PKHEAD

            {

                    Union

            {

                            DWORD type;

                            Struct

            {

                    WORD mtype;

                    WORD stype;

            };

                    };

                    DWORD len;

                    Char buf[0];

            };

            內(nèi)容buf部分常見(jiàn)組織方式莫過(guò)于定長(zhǎng)、變長(zhǎng)兩種。定長(zhǎng)的很簡(jiǎn)單,如struct item{…};作為內(nèi)容部分,如果不涉及到高低序問(wèn)題很好辦,涉及到序的時(shí)候轉(zhuǎn)換一下。變長(zhǎng)部分常見(jiàn)組織方式有這么一些經(jīng)典方法:

            1、 Content1 \0 content2 \0 content3 \0 …

            2、 json描述。

            3、 xml描述。

            方法1是效率很高的,對(duì)ansi型字符串或者utf8型字符串都沒(méi)有問(wèn)題,對(duì)utf16型字符串不行。解析這類(lèi)變長(zhǎng)部分的時(shí)候特別要注意包尾部的0,或者在緩沖區(qū)外部總保證存在一個(gè)0,或者保證包內(nèi)尾部總存在一個(gè)結(jié)尾0,總之最后一個(gè)string要保證有一個(gè)合法的0結(jié)束,當(dāng)然可能涉及到一些數(shù)值型到string型的轉(zhuǎn)換可能會(huì)導(dǎo)致效率下降,1的缺點(diǎn)在于只有一個(gè)層次。如果將內(nèi)容看作key1\0value1\0key2\0value2\0…可解決無(wú)序問(wèn)題,但終歸只有一個(gè)層次,不方便表示樹(shù)形數(shù)據(jù)。

            方法2的效率介于13之間,2由于描述很簡(jiǎn)潔,解析也是比較快的,比1好在可以解析任意層數(shù)據(jù),嵌套N層都無(wú)所謂,閱讀也很方便,解析的時(shí)候如果原始緩沖不釋放可讓字符串不復(fù)制直接記錄在原始緩沖中的指針,這樣可進(jìn)一步提高解析效率。QQ種菜的通訊協(xié)議就是json格式的,閱讀很方便,解析效率也可以,總的效率適中。

            方法3的解析效率是最低的,好在xml描述性也比較強(qiáng),解析代碼也很多,跟上層應(yīng)用交互的時(shí)候也比較方便,作為一個(gè)支持變長(zhǎng)的選擇也是可行的,不過(guò)如果特別在意效率的情況下避免使用,xml的解析效率比 2低了近一個(gè)數(shù)量級(jí),比1可能低近2個(gè)數(shù)量級(jí)。

             

            當(dāng)然自定義包還有更多格式選擇,標(biāo)準(zhǔn)協(xié)議也有很多如im 里面常見(jiàn)的xmppgoogleprotocol buffers等,還有json的一些擴(kuò)展協(xié)議,如bjson等,如果只是處理一般的網(wǎng)游數(shù)據(jù)可能用不上這么復(fù)雜的協(xié)議,用上面提到的定長(zhǎng)struct+1 or 2 or 3基本可以解決所有協(xié)議需求。也見(jiàn)到一些朋友自定義類(lèi)型信息描述格式,個(gè)人覺(jué)得或許沒(méi)有必要,特別是json如此流行的情況下再自己定義似乎有重復(fù)發(fā)明輪子的嫌疑,當(dāng)然具體情況具體對(duì)待,一切以滿足需求為目標(biāo)。

            posted @ 2010-10-03 14:15 袁斌 閱讀(328) | 評(píng)論 (0)編輯 收藏

            我一直堅(jiān)持一個(gè)觀點(diǎn),從web體系學(xué)習(xí)服務(wù)器端程序設(shè)計(jì),web作為發(fā)展最早也是前景最廣闊的internet模型,幾乎支撐了網(wǎng)絡(luò)世界一半以上的應(yīng)用,其他email ftp等傳統(tǒng)應(yīng)用雖然產(chǎn)生時(shí)間也很早但幾乎都很沒(méi)落,只有web風(fēng)采依舊,蓬勃發(fā)展,從apache到lighttp到nginx等,一個(gè)接一個(gè)高性能的web服務(wù)器程序分別被開(kāi)發(fā)出來(lái),上層應(yīng)用cgi, isapi(nsapi), fastcgi助力,html協(xié)議也在不斷發(fā)展,html5也要登堂亮相,各種腳本語(yǔ)言爭(zhēng)相斗艷,python、php、java、asp.net等。web應(yīng)用支持了目前最大規(guī)模的數(shù)據(jù)google,支持了最大量用戶(hù)的訪問(wèn),因此各種存儲(chǔ)、云計(jì)算等都是首先在web領(lǐng)域獲得應(yīng)用,可以說(shuō)web就是it領(lǐng)域的創(chuàng)新源泉,看下apache下面有多少項(xiàng)目就可見(jiàn)一般。web體系可謂博大精深,從web體系學(xué)習(xí)服務(wù)器端程序設(shè)計(jì)是學(xué)無(wú)止境的,從nginx等服務(wù)器程序設(shè)計(jì)上可學(xué)習(xí)server程序如何分塊、如何高效,從isapi/nsapi模型上可學(xué)習(xí)如何用進(jìn)程內(nèi)模塊擴(kuò)展應(yīng)用,從fastcgi可學(xué)習(xí)如何用進(jìn)程外模塊擴(kuò)展應(yīng)用,從各種cache方案中可學(xué)習(xí)如何為server端提速,從各種腳本應(yīng)用上可學(xué)習(xí)如何為server端程序二次開(kāi)發(fā)助力,web是源泉,web的各種這方式幾乎概括了server端程序的各種架構(gòu)模型。當(dāng)然一般自定義協(xié)議服務(wù)器和web還是有些地方不同的,最顯著的區(qū)別一般也就在于協(xié)議不一樣,另外就是web是無(wú)狀態(tài)一般不保持連接,因此web需要傳遞各種session等維持狀態(tài)的數(shù)據(jù),總之從web可學(xué)習(xí)的地方實(shí)在是太多。

            簡(jiǎn)單類(lèi)比下web領(lǐng)域開(kāi)發(fā)和一般server的擴(kuò)展

            nginx模塊/apache模塊            server程序+plugin

            cgi                                      fork子進(jìn)程

            fastcgi                                 server proxy模式,由于fastcgi可網(wǎng)絡(luò)方式部署,所以很容易在一個(gè)局域網(wǎng)內(nèi)部實(shí)現(xiàn)一個(gè)ioserver+N logicserver模型

            簡(jiǎn)單類(lèi)比就可知道,如果一個(gè)server程序只要能很方便的支持plugin+fastcgi就可適應(yīng)幾乎所有各種需求,可惜的是一般的server程序幾乎都不支持這兩個(gè)模式的擴(kuò)展,大多數(shù)gameserver只支持lua等腳本,說(shuō)實(shí)在的,支持個(gè)腳本跟支持fastcgi和plugin模塊相比還是差很多,如果支持fastcgi或者plugin只要做個(gè)plugin就支持lua了。

            posted @ 2010-10-03 14:15 袁斌 閱讀(233) | 評(píng)論 (0)編輯 收藏

            Server模塊如果僅僅作為一個(gè)lib包裝出來(lái)自然不是最好,雖然可在c++工程很容易使用,效率也比較高,但要使用到其他語(yǔ)言上去就沒(méi)有辦法,如果包裝一下自然是最好的,但如何包裝呢,包裝成一個(gè)什么樣子也是很重要的,最常見(jiàn)的包裝自然是包裝成一個(gè)dll,輸出一些接口,其他上層模塊在該接口的基礎(chǔ)上使用。最簡(jiǎn)單的包裝一般可輸出如下一些接口,

             

            Public IServer:

            {

            Virtual void StartServer(LPCTSTR ports, LPCTSTR udpoorts, int iothreads, int syncthreads, int asyntchreads);

            Virtual void StopServer();

                     Virtual IClient *CreateClient();

                     Virtual void CloseClient(IClient *);

                     Virtual void OnCloseClient(IClient *);

                     Virtual void OnConnectClient(IClient *);

                     Virtual void PostSyncEvent(DWORD event, WPARAM wParam, LPARAM lParam)

                     Virtual void PostAsyncEvent(DWORD event, WPARAM wparam, LPARAM lParam);

                     Virtual void OnAsyncEvent(DWORD event, WPARAM wParam, LPARAM lParam);

                     Virtual void OnSyncEvent(DWORD event, WPARAM wParam, LPARAM lParam);

                     Virtual void OnTimer(UINT uid);

                     Virtual void AddTimer(UINT uid, DWORD tk1, DWORD duetk);

            };

             

            Public IClient

            {

                     Virtual bool SendData(void *pdata, int len);

                     Virtual bool SendFile(LPCTSTR lpfilename);

                     Virtual bool SendFile(HANDLE hFile);

                     Virtual bool SendMsg(PKHEAD *ph);

                     Virtual bool SendMsg(PKHEAD *ph, void *pdata, int len);

                     Virtual bool SendMsg(PKHEAD *ph, void *pdata, int len, byte encrypt, byte compress);

                     Virtual void DelayClose();

                     Virtual void OnDelayClose();

                     Virtual void OnClose();

                     Virtual void OnConnect();

                     Virtual void OnAsyncEvent(DWORD event, WPARAM wParam, LPARAM lParam);

                     Virtual void OnSyncEvent(DWORD event, WPARAM wParam, LPARAM lParam);

                     Virtual void PostSyncEvent(DWORD event, WPARAM wParam, LPARAM lParam);

                     Virtual void PostAsyncEvent(DWORD event, WPARAM wParam, LPARAM lParam);

                     Virtual void SetTag(DWORD wParam);

                     Virtual DWORD GetTag();

                     Virtual long GetId();

            };

             

            IServer *DllCreateObject();

             

             

            通過(guò)結(jié)合LoadLibrary并提供一個(gè)類(lèi)似DllCreateObject的形式可很容易的 模擬類(lèi)com實(shí)現(xiàn),上層可很容易的是復(fù)用dll的實(shí)現(xiàn)。

            posted @ 2010-10-03 14:14 袁斌 閱讀(166) | 評(píng)論 (0)編輯 收藏

            我寫(xiě)東西一般是即興性創(chuàng)作,一般在走路的時(shí)候很容易產(chǎn)生各種想法,高興的時(shí)候到家或到工作的地方馬上就開(kāi)寫(xiě),幾分鐘就將想法記錄下來(lái),由于寫(xiě)得快也不檢查,所以看上去可能不是很流暢,或者說(shuō)得不是很清楚,甚至還有很多錯(cuò)別字等,請(qǐng)見(jiàn)諒。如關(guān)于某個(gè)技術(shù)問(wèn)題想和我深入探討請(qǐng)和我直接聯(lián)系,qq:345585946

            posted @ 2010-10-03 14:14 袁斌 閱讀(132) | 評(píng)論 (0)編輯 收藏

            有些時(shí)候需要給資源分配一個(gè)唯一id(32bit or 64bit or CHAR[N]),這里主要說(shuō)下分配方法問(wèn)題。

            首先我們有個(gè)基本前提,如果是單線程分配,那么我們無(wú)需下面的方法,直接++value即可(CHAR型無(wú)論幾線程都可使用GUID)順序產(chǎn)生不重復(fù)序列,下面討論的方法都是多線程下的分配策略:

            方法1 win下做簡(jiǎn)單的方法莫過(guò)于使用InterlocckedIncrement(or InterlockedIncrement64)了,這個(gè)調(diào)用也很簡(jiǎn)單,每次遞增一個(gè),多線程間保證順序遞增絕無(wú)重復(fù)。此方法只可在單一進(jìn)程上使用。

             

            方法2、區(qū)間法,每個(gè)線程一次申請(qǐng)一個(gè)id區(qū)間[m, n],用完了再申請(qǐng)下一個(gè)區(qū)段,申請(qǐng)的時(shí)候鎖一次,其他時(shí)間都不用鎖,效率比3略低,比1高。此方法也只可在一個(gè)進(jìn)程上使用,當(dāng)然如果申請(qǐng)的策略修改一下也可實(shí)現(xiàn)多個(gè)進(jìn)程甚至不同機(jī)器上的進(jìn)程之間獨(dú)立分配id

             

            方法3、方法1雖然簡(jiǎn)單但畢竟InterlockedXXX系列函數(shù)調(diào)用還是有些耗時(shí)的,大概50cpu周期級(jí)別,更簡(jiǎn)單的方法可以使用線程切分原理,如有3個(gè)線程參與id分配,我們這樣分配:

            線程1 base=1, step =3,序列1,4,7,10,…

            線程2 base=2, step=3,序列2,5,8,11,…

            線程3 base=3, step=3,序列3,6,9,12,…

            絕無(wú)重復(fù),調(diào)用非常簡(jiǎn)單每個(gè)線程id = base; base += step;即可。

            此方法在單進(jìn)程上使用很簡(jiǎn)單,如果要拓展到多個(gè)進(jìn)程上使用要通過(guò)配置來(lái)實(shí)現(xiàn),但也是不難的。

             

            方法4、如果id可用GUID表示那么方法要簡(jiǎn)單一點(diǎn),生成id直接調(diào)用guid生成算法,這個(gè)id生成算法即使在多個(gè)進(jìn)程之間甚至不同機(jī)器之間也可以保證唯一,也有其價(jià)值。

            posted @ 2010-10-03 14:13 袁斌 閱讀(1097) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題
            共4頁(yè): 1 2 3 4 
            久久99精品国产麻豆不卡| 三级片免费观看久久| AV无码久久久久不卡蜜桃| 久久精品草草草| 亚洲欧洲精品成人久久曰影片 | 国产精品亚洲美女久久久| AAA级久久久精品无码区| 久久精品无码一区二区WWW| 国产精品99久久久久久人| 亚洲精品午夜国产va久久| 少妇内射兰兰久久| 久久中文精品无码中文字幕| 99精品国产在热久久| 久久精品国产2020| 久久久久亚洲av成人无码电影| 精品国产99久久久久久麻豆 | 国产成年无码久久久久毛片| 久久se精品一区精品二区国产 | 伊人久久综合成人网| yellow中文字幕久久网| 久久成人国产精品| 久久天天躁夜夜躁狠狠躁2022| 91亚洲国产成人久久精品网址| 久久婷婷激情综合色综合俺也去| 久久精品夜色噜噜亚洲A∨| 久久免费精品一区二区| 久久天天躁狠狠躁夜夜躁2O2O| 97精品伊人久久久大香线蕉| 久久久久婷婷| 亚洲午夜福利精品久久| 久久久免费观成人影院| 久久久久亚洲AV成人网人人软件| 国产精品久久国产精品99盘 | 亚洲国产精品成人久久| 性做久久久久久久| 亚洲精品无码久久千人斩| 伊人久久大香线蕉av不变影院| 国色天香久久久久久久小说| 久久亚洲日韩看片无码| 久久天天躁狠狠躁夜夜avapp| 久久丫精品国产亚洲av不卡|