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

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            把 MongoDB 當(dāng)成是純內(nèi)存數(shù)據(jù)庫來使用(Redis 風(fēng)格)

            轉(zhuǎn)載自:http://www.oschina.net/translate/how-to-use-mongodb-as-a-pure-in-memory-db-redis-style

            英文原文:How to use MongoDB as a pure in-memory DB (Redis style)


             

            基本思想

            將MongoDB用作內(nèi)存數(shù)據(jù)庫(in-memory database),也即,根本就不讓MongoDB把數(shù)據(jù)保存到磁盤中的這種用法,引起了越來越多的人的興趣。這種用法對于以下應(yīng)用場合來講,超實用:

            • 置于慢速RDBMS系統(tǒng)之前的寫操作密集型高速緩存
            • 嵌入式系統(tǒng)
            • 無需持久化數(shù)據(jù)的PCI兼容系統(tǒng)
            • 需要輕量級數(shù)據(jù)庫而且?guī)熘袛?shù)據(jù)可以很容易清除掉的單元測試(unit testing)

            如果這一切可以實現(xiàn)就真是太優(yōu)雅了:我們就能夠巧妙地在不涉及磁盤操作的情況下利用MongoDB的查詢/檢索功能。可能你也知道,在99%的情況下,磁盤IO(特別是隨機IO)是系統(tǒng)的瓶頸,而且,如果你要寫入數(shù)據(jù)的話,磁盤操作是無法避免的。

            MongoDB有一個非常酷的設(shè)計決策,就是她可以使用內(nèi)存影射文件(memory-mapped file)來處理對磁盤文件中數(shù)據(jù)的讀寫請求。這也就是說,MongoDB并不對RAM和磁盤這兩者進行區(qū)別對待,只是將文件看作一個巨大的數(shù)組,然后按照字節(jié)為單位訪問其中的數(shù)據(jù),剩下的都交由操作系統(tǒng)(OS)去處理!就是這個設(shè)計決策,才使得MongoDB可以無需任何修改就能夠運行于RAM之中。


            實現(xiàn)方法

            這一切都是通過使用一種叫做tmpfs的特殊類型文件系統(tǒng)實現(xiàn)的。在Linux中它看上去同常規(guī)的文件系統(tǒng)(FS)一樣,只是它完全位于RAM中(除非其大小超過了RAM的大小,此時它還可以進行swap,這個非常有用?。?。我的服務(wù)器中有32GB的RAM,下面讓我們創(chuàng)建一個16GB的 tmpfs:

            # mkdir /ramdata
            # mount -t tmpfs -o size=16000M tmpfs /ramdata/
            # df
            Filesystem           1K-blocks      Used Available Use% Mounted on
            /dev/xvde1             5905712   4973924    871792  86% /
            none                  15344936         0  15344936   0% /dev/shm
            tmpfs                 16384000         0  16384000   0% /ramdata
            

            接下來要用適當(dāng)?shù)脑O(shè)置啟動MongoDB。為了減小浪費的RAM數(shù)量,應(yīng)該把smallfilesnoprealloc設(shè)置為true。既然現(xiàn)在是基于RAM的,這么做完全不會降低性能。此時再使用journal就毫無意義了,所以應(yīng)該把nojournal設(shè)置為true。

            dbpath=/ramdata
            nojournal = true
            smallFiles = true
            noprealloc = true
            

            MongoDB啟動之后,你會發(fā)現(xiàn)她運行得非常好,文件系統(tǒng)中的文件也正如期待的那樣出現(xiàn)了:

            # mongo
            MongoDB shell version: 2.3.2
            connecting to: test
            > db.test.insert({a:1})
            > db.test.find()
            { "_id" : ObjectId("51802115eafa5d80b5d2c145"), "a" : 1 }
            
            # ls -l /ramdata/
            total 65684
            -rw-------. 1 root root 16777216 Apr 30 15:52 local.0
            -rw-------. 1 root root 16777216 Apr 30 15:52 local.ns
            -rwxr-xr-x. 1 root root        5 Apr 30 15:52 mongod.lock
            -rw-------. 1 root root 16777216 Apr 30 15:52 test.0
            -rw-------. 1 root root 16777216 Apr 30 15:52 test.ns
            drwxr-xr-x. 2 root root       40 Apr 30 15:52 _tmp
            

            現(xiàn)在讓我們添加一些數(shù)據(jù),證實一下其運行完全正常。我們先創(chuàng)建一個1KB的document,然后將它添加到MongoDB中4百萬次:

            > str = ""
            
            > aaa = "aaaaaaaaaa"
            aaaaaaaaaa
            > for (var i = 0; i < 100; ++i) { str += aaa; }
            
            > for (var i = 0; i < 4000000; ++i) { db.foo.insert({a: Math.random(), s: str});}
            > db.foo.stats()
            {
                    "ns" : "test.foo",
                    "count" : 4000000,
                    "size" : 4544000160,
                    "avgObjSize" : 1136.00004,
                    "storageSize" : 5030768544,
                    "numExtents" : 26,
                    "nindexes" : 1,
                    "lastExtentSize" : 536600560,
                    "paddingFactor" : 1,
                    "systemFlags" : 1,
                    "userFlags" : 0,
                    "totalIndexSize" : 129794000,
                    "indexSizes" : {
                            "_id_" : 129794000
                    },
                    "ok" : 1
            }
            

            可以看出,其中的document平均大小為1136字節(jié),數(shù)據(jù)總共占用了5GB的空間。_id之上的索引大小為130MB?,F(xiàn)在我們需要驗證一件 非常重要的事情:RAM中的數(shù)據(jù)有沒有重復(fù),是不是在MongoDB和文件系統(tǒng)中各保存了一份?還記得MongoDB并不會在她自己的進程內(nèi)緩存任何數(shù)據(jù),她的數(shù)據(jù)只會緩存到文件系統(tǒng)的緩存之中。那我們來清除一下文件系統(tǒng)的緩存,然后看看RAM中還有有什么數(shù)據(jù):
            # echo 3 > /proc/sys/vm/drop_caches 
            # free
                         total       used       free     shared    buffers     cached
            Mem:      30689876    6292780   24397096          0       1044    5817368
            -/+ buffers/cache:     474368   30215508
            Swap:            0          0          0
            

            可以看到,在已使用的6.3GB的RAM中,有5.8GB用于了文件系統(tǒng)的緩存(緩沖區(qū),buffer)。為什么即使在清除所有緩存之后,系統(tǒng)中仍然還有5.8GB的文件系統(tǒng)緩存??其原因是,Linux非常聰明,她不會在tmpfs和緩存中保存重復(fù)的數(shù)據(jù)。太棒了!這就意味著,你在RAM只有一份數(shù)據(jù)。下面我們訪問一下所有的document,并驗證一下,RAM的使用情況不會發(fā)生變化:

            > db.foo.find().itcount()
            4000000
            
            # free
                         total       used       free     shared    buffers     cached
            Mem:      30689876    6327988   24361888          0       1324    5818012
            -/+ buffers/cache:     508652   30181224
            Swap:            0          0          0
            # ls -l /ramdata/
            total 5808780
            -rw-------. 1 root root  16777216 Apr 30 15:52 local.0
            -rw-------. 1 root root  16777216 Apr 30 15:52 local.ns
            -rwxr-xr-x. 1 root root         5 Apr 30 15:52 mongod.lock
            -rw-------. 1 root root  16777216 Apr 30 16:00 test.0
            -rw-------. 1 root root  33554432 Apr 30 16:00 test.1
            -rw-------. 1 root root 536608768 Apr 30 16:02 test.10
            -rw-------. 1 root root 536608768 Apr 30 16:03 test.11
            -rw-------. 1 root root 536608768 Apr 30 16:03 test.12
            -rw-------. 1 root root 536608768 Apr 30 16:04 test.13
            -rw-------. 1 root root 536608768 Apr 30 16:04 test.14
            -rw-------. 1 root root  67108864 Apr 30 16:00 test.2
            -rw-------. 1 root root 134217728 Apr 30 16:00 test.3
            -rw-------. 1 root root 268435456 Apr 30 16:00 test.4
            -rw-------. 1 root root 536608768 Apr 30 16:01 test.5
            -rw-------. 1 root root 536608768 Apr 30 16:01 test.6
            -rw-------. 1 root root 536608768 Apr 30 16:04 test.7
            -rw-------. 1 root root 536608768 Apr 30 16:03 test.8
            -rw-------. 1 root root 536608768 Apr 30 16:02 test.9
            -rw-------. 1 root root  16777216 Apr 30 15:52 test.ns
            drwxr-xr-x. 2 root root        40 Apr 30 16:04 _tmp
            # df
            Filesystem           1K-blocks      Used Available Use% Mounted on
            /dev/xvde1             5905712   4973960    871756  86% /
            none                  15344936         0  15344936   0% /dev/shm
            tmpfs                 16384000   5808780  10575220  36% /ramdata
            

            果不其然! :)


            復(fù)制(replication)呢?

            既然服務(wù)器在重啟時RAM中的數(shù)據(jù)都會丟失,所以你可能會想使用復(fù)制。采用標(biāo)準(zhǔn)的副本集(replica set)就能夠獲得自動故障轉(zhuǎn)移(failover),還能夠提高數(shù)據(jù)讀取能力(read capacity)。如果有服務(wù)器重啟了,它就可以從同一個副本集中另外一個服務(wù)器中讀取數(shù)據(jù)從而重建自己的數(shù)據(jù)(重新同步,resync)。即使在大量數(shù)據(jù)和索引的情況下,這個過程也會足夠快,因為索引操作都是在RAM中進行的 :)

            有一點很重要,就是寫操作會寫入一個特殊的叫做oplog的collection,它位于local數(shù)據(jù)庫之中。缺省情況下,它的大小是總數(shù)據(jù)量的5%。在我這種情況下,oplog會占有16GB的5%,也就是800MB的空間。在拿不準(zhǔn)的情況下,比較安全的做法是,可以使用oplogSize這個選項為oplog選擇一個固定的大小。如果備選服務(wù)器宕機時間超過了oplog的容量,它就必須要進行重新同步了。要把它的大小設(shè)置為1GB,可以這樣:

            oplogSize = 1000
            


             

            分片(sharding)呢?

            既然擁有了MongoDB所有的查詢功能,那么用它來實現(xiàn)一個大型的服務(wù)要怎么弄?你可以隨心所欲地使用分片來實現(xiàn)一個大型可擴展的內(nèi)存數(shù)據(jù)庫。配置服務(wù)器(保存著數(shù)據(jù)塊分配情況)還還是用過采用基于磁盤的方案,因為這些服務(wù)器的活動數(shù)量不大,老從頭重建集群可不好玩。

            注意事項

            RAM屬稀缺資源,而且在這種情況下你一定想讓整個數(shù)據(jù)集都能放到RAM中。盡管tmpfs具有借助于磁盤交換(swapping)的能力,但其性能下降將非常顯著。為了充分利用RAM,你應(yīng)該考慮:

            • 使用usePowerOf2Sizes選項對存儲bucket進行規(guī)范化
            • 定期運行compact命令或者對節(jié)點進行重新同步(resync)
            • schema的設(shè)計要相當(dāng)規(guī)范化(以避免出現(xiàn)大量比較大的document)

            結(jié)論

            寶貝,你現(xiàn)在就能夠?qū)ongoDB用作內(nèi)存數(shù)據(jù)庫了,而且還能使用她的所有功能!性能嘛,應(yīng)該會相當(dāng)驚人:我在單線程/核的情況下進行測試,可以達(dá)到每秒20K個寫入的速度,而且增加多少個核就會再增加多少倍的寫入速度。


            posted on 2014-05-29 22:57 楊粼波 閱讀(494) 評論(0)  編輯 收藏 引用

            亚洲AV无码久久精品色欲| 久久99国产综合精品女同| 国产99久久久久久免费看| 久久精品草草草| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 青青草原综合久久大伊人导航 | 久久久久99这里有精品10| 思思久久99热只有频精品66| 亚洲中文久久精品无码| 国产99久久久国产精品~~牛 | 久久婷婷国产剧情内射白浆| 久久久久久久久久久久中文字幕| 91精品国产色综久久| 欧美大战日韩91综合一区婷婷久久青草| 久久综合九色综合欧美就去吻| 亚洲精品乱码久久久久久| 91超碰碰碰碰久久久久久综合| 久久精品国产男包| 久久久久99精品成人片三人毛片 | 久久强奷乱码老熟女| 2022年国产精品久久久久| 亚洲伊人久久综合影院| 国产亚洲色婷婷久久99精品91| 欧洲成人午夜精品无码区久久| 久久久精品国产Sm最大网站| 久久99精品综合国产首页| 精品伊人久久大线蕉色首页| 人妻无码久久精品| 日产久久强奸免费的看| 久久se精品一区精品二区国产| 久久综合精品国产二区无码| 国产亚洲精久久久久久无码77777| 久久99亚洲综合精品首页| 99久久免费国产精品| 97超级碰碰碰碰久久久久| 青青青青久久精品国产h| 国内精品久久久人妻中文字幕| 伊人久久大香线蕉av不变影院| 久久久久亚洲AV无码专区首JN| 色综合久久夜色精品国产| 久久99热这里只有精品66|