據(jù)說帶著問題學(xué)習(xí)更有效,那就先看一個MongoDB服務(wù)器的top命令結(jié)果:
10余年的臨潭網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整臨潭建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)從事“臨潭網(wǎng)站設(shè)計”,“臨潭網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。shell> top -p $(pidof mongod)
Mem: 32872124k total, 30065320k used, 2806804k free, 245020k buffers
Swap: 2097144k total, 100k used, 2097044k free, 26482048k cached
VIRT RES SHR %MEM
1892g 21g 21g 69.6
這臺MongoDB服務(wù)器有沒有性能問題?大家可以一邊思考一邊繼續(xù)閱讀。
先講講Linux是如何管理內(nèi)存的在Linux里(別的系統(tǒng)也差不多),內(nèi)存有物理內(nèi)存和虛擬內(nèi)存之說,物理內(nèi)存是什么自然無需解釋,虛擬內(nèi)存實際是物理內(nèi)存的抽象,多數(shù)情況下,出于方便性的考慮,程序訪問的都是虛擬內(nèi)存地址,然后操作系統(tǒng)會通過Page Table機(jī)制把它翻譯成物理內(nèi)存地址,詳細(xì)說明可以參考Understanding Memory和Understanding Virtual Memory,至于程序是如何使用虛擬內(nèi)存的,可以參考Playing with Virtual Memory,這里就不多費(fèi)口舌了。
很多人會把虛擬內(nèi)存和Swap混為一談,實際上Swap只是虛擬內(nèi)存引申出的一種技術(shù)而已:操作系統(tǒng)一旦物理內(nèi)存不足,為了騰出內(nèi)存空間存放新內(nèi)容,就會把當(dāng)前物理內(nèi)存中的內(nèi)容放到交換分區(qū)里,稍后用到的時候再取回來,需要注意的是,Swap的使用可能會帶來性能問題,偶爾為之無需緊張,糟糕的是物理內(nèi)存和交換分區(qū)頻繁的發(fā)生數(shù)據(jù)交換,這被稱之為Swap顛簸,一旦發(fā)生這種情況,先要明確是什么原因造成的,如果是內(nèi)存不足就好辦了,加內(nèi)存就可以解決,不過有的時候即使內(nèi)存充足也可能會出現(xiàn)這種問題,比如MySQL就有可能出現(xiàn)這樣的情況,一個可選的解決方法是限制使用Swap:
shell> sysctl -w vm.swappiness=0
查看內(nèi)存情況最常用的是free命令:
shell> free -m
total used free shared buffers cached
Mem: 32101 29377 2723 0 239 25880
-/+ buffers/cache: 3258 28842
Swap: 2047 0 2047
新手看到used一欄數(shù)值偏大,free一欄數(shù)值偏小,往往會認(rèn)為內(nèi)存要用光了。其實并非如此,之所以這樣是因為每當(dāng)我們操作文件的時候,Linux都會盡可能的把文件緩存到內(nèi)存里,這樣下次訪問的時候,就可以直接從內(nèi)存中取結(jié)果,所以cached一欄的數(shù)值非常的大,不過不用擔(dān)心,這部分內(nèi)存是可回收的,操作系統(tǒng)的虛擬內(nèi)存管理器會按照LRU算法淘汰冷數(shù)據(jù)。還有一個buffers,也是可回收的,不過它是保留給塊設(shè)備使用的。
知道了原理,我們就可以推算出系統(tǒng)可用的內(nèi)存是free + buffers + cached:
shell> echo $((2723 + 239 + 25880))
28842
至于系統(tǒng)實際使用的內(nèi)存是used – buffers – cached:
shell> echo $((29377 - 239 - 25880))
3258
除了free命令,還可以使用sar命令:
shell> sar -r
kbmemfree kbmemused %memused kbbuffers kbcached
3224392 29647732 90.19 246116 26070160
shell> sar -W
pswpin/s pswpout/s
0.00 0.00
希望你沒有被%memused嚇到,如果不幸言中,重讀本文。
再說說MongoDB是如何使用內(nèi)存的目前,MongoDB使用的是內(nèi)存映射存儲引擎,它會把數(shù)據(jù)文件映射到內(nèi)存中,如果是讀操作,內(nèi)存中的數(shù)據(jù)起到緩存的作用,如果是寫操作,內(nèi)存還可以把隨機(jī)的寫操作轉(zhuǎn)換成順序的寫操作,總之可以大幅度提升性能。MongoDB并不干涉內(nèi)存管理工作,而是把這些工作留給操作系統(tǒng)的虛擬內(nèi)存管理器去處理,這樣做的好處是簡化了MongoDB的工作,但壞處是你沒有方法很方便的控制MongoDB占多大內(nèi)存,幸運(yùn)的是虛擬內(nèi)存管理器的存在讓我們多數(shù)時候并不需要關(guān)心這個問題。
MongoDB的內(nèi)存使用機(jī)制讓它在緩存重建方面更有優(yōu)勢,簡而言之:如果重啟進(jìn)程,那么緩存依然有效,如果重啟系統(tǒng),那么可以通過拷貝數(shù)據(jù)文件到/dev/null的方式來重建緩存,更詳細(xì)的描述請參考:Cache Reheating – Not to be Ignored。
有時候,即便MongoDB使用的是64位操作系統(tǒng),也可能會遭遇OOM問題,出現(xiàn)這種情況,多半是因為限制了內(nèi)存的大小所致,可以這樣查看當(dāng)前值:
shell> ulimit -a | grep memory
多數(shù)操作系統(tǒng)缺省都是把它設(shè)置成unlimited的,如果你的操作系統(tǒng)不是,可以這樣修改:
shell> ulimit -m unlimited
shell> ulimit -v unlimited
注:ulimit的使用是有上下文的,最好放在MongoDB的啟動腳本里。
有時候,MongoDB連接數(shù)過多的話,會拖累性能,可以通過serverStatus查詢連接數(shù):
mongo> db.serverStatus().connections
每個連接都是一個線程,需要一個Stack,Linux下缺省的Stack設(shè)置一般比較大:
shell> ulimit -a | grep stack
stack size (kbytes, -s) 10240
至于MongoDB實際使用的Stack大小,可以用如下命令確認(rèn)(單位:K):
shell> cat /proc/$(pidof mongod)/limits | grep stack | awk -F 'size' '{print int($NF)/1024}'
如果Stack過大(比如:10240K)的話沒有意義,簡單對照命令結(jié)果中的Size和Rss:
shell> cat /proc/$(pidof mongod)/smaps | grep 10240 -A 10
所有連接消耗的內(nèi)存加起來會相當(dāng)驚人,推薦把Stack設(shè)置小一點(diǎn),比如說1024:
shell> ulimit -s 1024
注:從MongoDB1.8.3開始,MongoDB會在啟動時自動設(shè)置Stack。
有時候,出于某些原因,你可能想釋放掉MongoDB占用的內(nèi)存,不過前面說了,內(nèi)存管理工作是由虛擬內(nèi)存管理器控制的,幸好可以使用MongoDB內(nèi)置的closeAllDatabases命令達(dá)到目的:
mongo> use admin
mongo> db.runCommand({closeAllDatabases:1})
另外,通過調(diào)整內(nèi)核參數(shù)drop_caches也可以釋放緩存:
shell> sysctl -w vm.drop_caches=1
平時可以通過mongo命令行來監(jiān)控MongoDB的內(nèi)存使用情況,如下所示:
mongo> db.serverStatus().mem:
{
"resident" : 22346,
"virtual" : 1938524,
"mapped" : 962283
}
還可以通過mongostat命令來監(jiān)控MongoDB的內(nèi)存使用情況,如下所示:
shell> mongostat
mapped vsize res faults
940g 1893g 21.9g 0
其中內(nèi)存相關(guān)字段的含義是:
mapped:映射到內(nèi)存的數(shù)據(jù)大小 visze:占用的虛擬內(nèi)存大小 res:占用的物理內(nèi)存大小注:如果操作不能在內(nèi)存中完成,結(jié)果faults列的數(shù)值不會是0,視大小可能有性能問題。
在上面的結(jié)果中,vsize是mapped的兩倍,而mapped等于數(shù)據(jù)文件的大小,所以說vsize是數(shù)據(jù)文件的兩倍,之所以會這樣,是因為本例中,MongoDB開啟了journal,需要在內(nèi)存里多映射一次數(shù)據(jù)文件,如果關(guān)閉journal,則vsize和mapped大致相當(dāng)。
如果想驗證這一點(diǎn),可以在開啟或關(guān)閉journal后,通過pmap命令來觀察文件映射情況:
shell> pmap $(pidof mongod)
到底MongoDB配備多大內(nèi)存合適?寬泛點(diǎn)來說,多多益善,如果要確切點(diǎn)來說,這實際取決于你的數(shù)據(jù)及索引的大小,內(nèi)存如果能夠裝下全部數(shù)據(jù)加索引是最佳情況,不過很多時候,數(shù)據(jù)都會比內(nèi)存大,比如本文所涉及的MongoDB實例:
mongo> db.stats()
{
"dataSize" : 1004862191980,
"indexSize" : 1335929664
}
本例中索引只有1G多,內(nèi)存完全能裝下,而數(shù)據(jù)文件則達(dá)到了1T,估計很難找到這么大內(nèi)存,此時保證內(nèi)存能裝下熱數(shù)據(jù)即可,至于熱數(shù)據(jù)是多少,取決于具體的應(yīng)用,你也可以通過觀察faults的大小來判斷當(dāng)前內(nèi)存是否能夠裝下熱數(shù)據(jù),如果faults持續(xù)變大,就說明當(dāng)前內(nèi)存已經(jīng)不能滿足熱數(shù)據(jù)的大小了。如此一來內(nèi)存大小就明確了:內(nèi)存 > 索引 + 熱數(shù)據(jù),最好有點(diǎn)富余,畢竟操作系統(tǒng)本身正常運(yùn)轉(zhuǎn)也需要消耗一部分內(nèi)存。
不登高山,怎知天高;不臨深溪,焉知地厚!站在堅實的土地上,做著生命中最真實的事情;像一棵挺拔的大樹,認(rèn)可自己的命運(yùn)并敢于迎接屬于這一方天空的風(fēng)風(fēng)雨雨。
標(biāo)題名稱:MongoDB與內(nèi)存【轉(zhuǎn)載】-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://jinyejixie.com/article24/dsipce.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站策劃、企業(yè)建站、商城網(wǎng)站、搜索引擎優(yōu)化、網(wǎng)站營銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容