MongoDB 運(yùn)維實(shí)戰(zhàn)總結(jié)

一办铡、MongoDB 集群簡(jiǎn)介

MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫脐雪,其目的在于為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案付翁。下面將以3臺(tái)機(jī)器介紹最常見的集群方案尖阔。具體介紹烘豹,可以查看官網(wǎng) https://docs.mongodb.com/v3.4/introduction/

1诺祸、集群組件的介紹

mongos(路由處理):

作為Client與MongoDB集群的請(qǐng)求入口携悯,所有用戶請(qǐng)求都會(huì)透過Mongos協(xié)調(diào),它會(huì)將數(shù)據(jù)請(qǐng)求發(fā)到對(duì)應(yīng)的Shard(mongod)服務(wù)器上筷笨,再將數(shù)據(jù)合并后回傳給用戶憔鬼。

config server(配置節(jié)點(diǎn)):

即:配置服務(wù)器;主要保存數(shù)據(jù)庫的元數(shù)據(jù)胃夏,包含數(shù)據(jù)的分布(分片)以及數(shù)據(jù)結(jié)構(gòu)轴或,mongos收到client發(fā)出的需求后,會(huì)從config server加載配置信息并緩存于內(nèi)存中仰禀。

一般在生產(chǎn)環(huán)境會(huì)配置不只一臺(tái)config server照雁,因?yàn)樗4娴脑獢?shù)據(jù)極為重要,若損壞則影響整個(gè)集群運(yùn)作答恶。

shard(分片實(shí)例存儲(chǔ)數(shù)據(jù)):

shard就是分片饺蚊。MongoDB利用分片的機(jī)制來實(shí)現(xiàn)數(shù)據(jù)分布存儲(chǔ)與處理,達(dá)到橫向擴(kuò)容的目的悬嗓。默認(rèn)情況下污呼,數(shù)據(jù)在分片之間會(huì)自動(dòng)進(jìn)行移轉(zhuǎn),以達(dá)到平衡包竹,此動(dòng)作是靠一個(gè)叫平衡器(balancer)的機(jī)制達(dá)成燕酷。

replica set(副本集):

副本集實(shí)現(xiàn)了數(shù)據(jù)庫高可用,若沒做副本集周瞎,則一旦存放數(shù)據(jù)的服務(wù)器節(jié)點(diǎn)掛掉苗缩,數(shù)據(jù)就丟失了,相反若配置了副本集声诸,則同樣的數(shù)據(jù)會(huì)保存在副本服務(wù)器中(副本節(jié)點(diǎn))酱讶,一般副本集包含了一個(gè)主節(jié)點(diǎn)與多個(gè)副本節(jié)點(diǎn),必要時(shí)還會(huì)配置arbiter(仲裁結(jié)點(diǎn))作為節(jié)點(diǎn)掛掉時(shí)投票用双絮。

arbiter(仲裁節(jié)點(diǎn)):

仲裁服務(wù)器本身不包含數(shù)據(jù)浴麻,僅能在主節(jié)點(diǎn)故障時(shí),檢測(cè)所有副本服務(wù)器并選舉出新的主節(jié)點(diǎn)囤攀,其實(shí)現(xiàn)方式是通過主節(jié)點(diǎn)软免、副本節(jié)點(diǎn)、仲裁服務(wù)器之間的心跳(Heart beat)實(shí)現(xiàn)焚挠。

2膏萧、MongoDB應(yīng)用場(chǎng)景

網(wǎng)站數(shù)據(jù):適合實(shí)時(shí)的插入,更新與查詢蝌衔,并具備網(wǎng)站實(shí)時(shí)數(shù)據(jù)存儲(chǔ)所需的復(fù)制及高度伸縮性榛泛。

緩存:由于性能很高,也適合作為信息基礎(chǔ)設(shè)施的緩存層噩斟。在系統(tǒng)重啟之后曹锨,搭建的持久化緩存可以避免下層的數(shù)據(jù)源過載。

大尺寸剃允、低價(jià)值的數(shù)據(jù):使用傳統(tǒng)的關(guān)系數(shù)據(jù)庫存儲(chǔ)一些數(shù)據(jù)時(shí)可能會(huì)比較貴沛简,在此之前,很多程序員往往會(huì)選擇傳統(tǒng)的文件進(jìn)行存儲(chǔ)斥废。

高伸縮性的場(chǎng)景:非常適合由數(shù)十或者數(shù)百臺(tái)服務(wù)器組成的數(shù)據(jù)庫椒楣。

用于對(duì)象及JSON數(shù)據(jù)的存儲(chǔ):MongoDB的BSON數(shù)據(jù)格式非常適合文檔格式化的存儲(chǔ)及查詢。

3牡肉、選用MongoDB的緣由

選用MongoDB的數(shù)據(jù)是以BSON的數(shù)據(jù)格式捧灰,高度伸縮方便擴(kuò)展,并且數(shù)據(jù)水平擴(kuò)展非常簡(jiǎn)單统锤,支持海量數(shù)據(jù)存儲(chǔ)毛俏,性能強(qiáng)悍。

二饲窿、集群的監(jiān)測(cè)

1拧抖、監(jiān)測(cè)數(shù)據(jù)庫存儲(chǔ)統(tǒng)計(jì)信息

docker中進(jìn)入mongos或shard實(shí)例,執(zhí)行以下命令:


docker exec -it mongos bash;

mongo --port 20001;

use admin;

db.auth("root","XXX");

說明:通過此命令免绿,可以查詢集群的成員的集合數(shù)量唧席、索引數(shù)量等相關(guān)數(shù)據(jù)。


db.stats();

2嘲驾、查看數(shù)據(jù)庫的統(tǒng)計(jì)信息

說明:通過此命令淌哟,可以查看操作數(shù)量、內(nèi)存使用狀況辽故、網(wǎng)絡(luò)io等


db.runCommand( { serverStatus: 1 } )徒仓;

3、檢查復(fù)制集成員狀態(tài)


rs.status()誊垢;

三掉弛、基本的運(yùn)維操作

1症见、設(shè)置和查看慢查詢


# 設(shè)置慢查詢

db.setProfilingLevel(1,200);

# 查看慢查詢級(jí)別

db.getProfilingLevel();

# 查詢慢查詢?nèi)罩荆嗣钍轻槍?duì)于某一庫進(jìn)行設(shè)置

db.system.profile.find({ ns : 'dbName.collectionName'}).limit(10).sort( { ts : -1 } ).pretty();

2殃饿、查看執(zhí)行操作時(shí)間較長的動(dòng)作

db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }});

3谋作、動(dòng)態(tài)調(diào)整日志級(jí)別和設(shè)置緩存大小


# 設(shè)置日志級(jí)別參數(shù)

db.adminCommand( { "getParameter": 1, "logLevel":1});

# 設(shè)置cache大小參數(shù)

db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=4G"});

4、添加和移除復(fù)制集成員


# 查看復(fù)制集成員

rs.status().members;

# 添加成員

rs.add('127.0.0.1:20001')乎芳;

# 移除成員

rs.remove('127.0.0.1:20001')遵蚜;

5、設(shè)置數(shù)據(jù)庫和集合分片


# 在mongos admin庫設(shè)置庫允許分片

sh.enableSharding("dbName");

# 在mongos 的admin庫設(shè)置集合分片片鍵

sh.shardCollection("dbName.collectionName", { filedName: 1} );

6奈惑、添加和移除分片


# 查看分片狀態(tài)

sh.status()吭净;

# 在mongos執(zhí)行添加分片(可以為單個(gè)實(shí)例或復(fù)制集)

db.runCommand( { removeShard: "shardName" } );

db.runCommand({addshard:"rs1/ip-1:20001,ip-2:20001,ip-3:20001"});

# 在mongos執(zhí)行移除分片

db.runCommand( { removeShard: "shard3" } )肴甸;

# 在mongos執(zhí)行刷新mongos配置信息

### db.runCommand("flushRouterConfig"))寂殉;

說明:移除分片命令至少執(zhí)行兩次才能成功刪除,執(zhí)行到state為completed才真正刪除原在,否則就是沒用刪除成功不撑,該分片處于{"draining" : true}狀態(tài),該狀態(tài)下不但該分片沒用刪除成功晤斩,而且還影響接下來刪除其他分片操作焕檬,遇到該狀態(tài)再執(zhí)行一次removeshard即可,最好就是刪除分片時(shí)一直重復(fù)執(zhí)行刪除命令澳泵,直到state為completed实愚; 還有一個(gè)需要注意的地方就是:被成功刪除的分片如果想要再加入集群時(shí),必須將data數(shù)據(jù)目錄清理干凈才可以再加入集群兔辅,否則即使能加入成功也不會(huì)存儲(chǔ)數(shù)據(jù)腊敲,集合都不會(huì)被創(chuàng)建 另外:在刪除分片的時(shí)有可能整個(gè)過程出現(xiàn)無限{"draining" : true}狀態(tài),等多久還是這樣维苔,而且分片上面的塊一個(gè)都沒有移動(dòng)到別的分片碰辅,解決辦法是:在config的config數(shù)據(jù)庫的shard集合中找到該分片的信息,并將draining字段由True改為False,再繼續(xù)試著刪除操作” 上面這句會(huì)立即返回介时,實(shí)際在后臺(tái)執(zhí)行没宾。 在數(shù)據(jù)移除的過程當(dāng)中,一定要注意實(shí)例的日志信息沸柔,可能出現(xiàn)數(shù)據(jù)塊在遷移的過程中循衰,始終找不到邊界條件,導(dǎo)致一直數(shù)據(jù)遷移不成功褐澎,一直重試会钝,解決方案是刪除邊界數(shù)據(jù),重啟實(shí)例工三;迁酸。如果此分片為主分片先鱼,需要先遷移主分片。db.runCommand( { movePrimary: "XXX", to: "other" })奸鬓;在完成刪除后焙畔,所有mongos上運(yùn)行下面命令,再對(duì)外提供服務(wù)全蝶,當(dāng)然也可以重新啟動(dòng)所有mongos實(shí)例 闹蒜。

7寺枉、數(shù)據(jù)的導(dǎo)入導(dǎo)出


# 導(dǎo)出允許指定導(dǎo)出條件和字段

mongoexport -h 127.0.0.1 --port 20001 -uxxx -pxxx -d xxx -c mobileIndex -o XXX.txt

mongoimport -h 127.0.0.1 --port 20001 -uxxx -pxxx -d xxx -c mobileIndex --file XXX.txt

四抑淫、MongoDB數(shù)據(jù)遷移

1、遷移復(fù)制集當(dāng)中的成員

關(guān)閉 mongod 實(shí)例,為了確保安全關(guān)閉,使用 shutdown 命令姥闪;

將數(shù)據(jù)目錄(即 dbPath )轉(zhuǎn)移到新機(jī)器上始苇;

在新機(jī)器上啟動(dòng) mongod,其中節(jié)點(diǎn)的數(shù)據(jù)目錄為copy的文件目錄 筐喳;

連接到復(fù)制集當(dāng)前的主節(jié)點(diǎn)上催式;

如果新節(jié)點(diǎn)的地址發(fā)生變化,使用 rs.reconfig() 更新 復(fù)制集配置文檔 ;

舉例,下面的命令過程將成員中位于第 2 位的地址進(jìn)行更新:


cfg = rs.conf()

cfg.members[2].host = "127.0.0.1:27017"

rs.reconfig(cfg)

使用 rs.conf() 確認(rèn)使用了新的配置.

等待所有成員恢復(fù)正常,使用 rs.status() 檢測(cè)成員狀態(tài)避归。

2荣月、遷移復(fù)制集主節(jié)點(diǎn)

在遷移主節(jié)點(diǎn)的時(shí)候,需要復(fù)制集選舉出一個(gè)新的主節(jié)點(diǎn),在進(jìn)行選舉的時(shí)候,復(fù)制集將讀寫,通常,這只會(huì)持續(xù)很短的時(shí)間,不過,應(yīng)該盡可能在影響較小的時(shí)間段內(nèi)遷移主節(jié)點(diǎn).

將主節(jié)點(diǎn)降級(jí),以使得正常的 failover開始.要將主節(jié)點(diǎn)降級(jí),連接到一個(gè)主節(jié)點(diǎn),使用 replSetStepDown方法或者使用rs.stepDown()方法,下面的例子使用了 rs.stepDown()方法進(jìn)行降級(jí):


rs.stepDown()

等主節(jié)點(diǎn)降級(jí)為從節(jié)點(diǎn),另一個(gè)成員成為 PRIMARY 之后,可以按照 “遷移復(fù)制集的一個(gè)成員”遷移這個(gè)降級(jí)了的節(jié)點(diǎn).可以使用 rs.status()來確認(rèn)狀態(tài)的改變。

3梳毙、從復(fù)制集其他節(jié)點(diǎn)恢復(fù)數(shù)據(jù)

MongoDB 通過復(fù)制集能保證高可靠的數(shù)據(jù)存儲(chǔ)哺窄,通常生產(chǎn)環(huán)境建議使用「3節(jié)點(diǎn)復(fù)制集」,這樣即使其中一個(gè)節(jié)點(diǎn)崩潰了無法啟動(dòng)账锹,我們可以直接將其數(shù)據(jù)清掉萌业,重新啟動(dòng)后,以全新的 Secondary 節(jié)點(diǎn)加入復(fù)制集奸柬,或者是將其他節(jié)點(diǎn)的數(shù)據(jù)復(fù)制過來生年,重新啟動(dòng)節(jié)點(diǎn),它會(huì)自動(dòng)的同步數(shù)據(jù)廓奕,這樣也就達(dá)到了恢復(fù)數(shù)據(jù)的目的抱婉。

1、關(guān)閉需要數(shù)據(jù)同步的節(jié)點(diǎn)

docker stop node; # docker環(huán)境中

db.shutdownServer({timeoutSecs: 60}); # 非docker環(huán)境

2桌粉、拷貝目標(biāo)節(jié)點(diǎn)機(jī)器的數(shù)據(jù)存儲(chǔ)目錄(/dbPath)到當(dāng)前機(jī)器的指定目錄授段。

scp 目標(biāo)節(jié)點(diǎn) shard/data -> 當(dāng)前節(jié)點(diǎn) shard/data

3、當(dāng)前節(jié)點(diǎn)以復(fù)制過來的數(shù)據(jù)文件啟動(dòng)節(jié)點(diǎn)

4番甩、將新的節(jié)點(diǎn)添加到復(fù)制集


# 進(jìn)入復(fù)制集的主節(jié)點(diǎn)侵贵,執(zhí)行添加新的節(jié)點(diǎn)命令

rs.add("hostNameNew:portNew");

# 等待所有成員恢復(fù)正常,檢測(cè)成員狀態(tài)

rs.status();

# 移除原來的節(jié)點(diǎn)

rs.remove("hostNameOld>:portOld");

五、MongoDB線上問題場(chǎng)景解決

1缘薛、MongoDB 新建索引導(dǎo)致庫被鎖

問題說明:某線上千萬級(jí)別集合窍育,為優(yōu)化業(yè)務(wù)卡睦,直接執(zhí)行新建索引命令,導(dǎo)致整個(gè)庫被鎖漱抓,應(yīng)用服務(wù)出現(xiàn)不可用表锻。

解決方案:找出此操作進(jìn)程,并且殺死乞娄。改為后臺(tái)新建索引瞬逊,速度很會(huì)慢,但是不會(huì)影響業(yè)務(wù)仪或,該索引只會(huì)在新建完成之后确镊,才會(huì)生效;


# 查詢運(yùn)行時(shí)間超過200ms操作   

db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }}) 范删;

# 殺死執(zhí)行時(shí)間過長操作操作

db.killOp(opid)

# 后臺(tái)新建索引

db.collectionNmae.ensureIndex({filedName:1}, {background:true});

2蕾域、MongoDB沒有限制內(nèi)存,導(dǎo)致實(shí)例退出

問題說明:生產(chǎn)環(huán)境某臺(tái)機(jī)器啟動(dòng)多個(gè)mongod實(shí)例到旦,運(yùn)行一段時(shí)間過后旨巷,進(jìn)程莫名被殺死;

解決方案:現(xiàn)在MongoDB使用WiredTiger作為默認(rèn)存儲(chǔ)引擎添忘,MongoDB同時(shí)使用WiredTiger內(nèi)部緩存和文件系統(tǒng)緩存采呐。從3.4開始,WiredTiger內(nèi)部緩存默認(rèn)使用較大的一個(gè):50%(RAM - 1 GB)搁骑,或256 MB斧吐。

例如,在總共4GB RAM的系統(tǒng)上靶病,WiredTiger緩存將使用1.5GB的RAM()会通。相反,具有總共1.25 GB RAM的系統(tǒng)將為WiredTiger緩存分配256 MB娄周,因?yàn)檫@超過總RAM的一半減去1千兆字節(jié)()涕侈。0.5 * (4 GB - 1GB) = 1.5 GB``0.5 * (1.25 GB - 1 GB) = 128 MB < 256 MB。如果一臺(tái)機(jī)器存在多個(gè)實(shí)例煤辨,在內(nèi)存不足的情景在裳涛,操作系統(tǒng)會(huì)殺死部分進(jìn)程;


# 要調(diào)整WiredTiger內(nèi)部緩存的大小众辨,調(diào)節(jié)cache規(guī)模不需要重啟服務(wù)端三,我們可以動(dòng)態(tài)調(diào)整:

db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=xxG"})

3、MongoDB刪除數(shù)據(jù)鹃彻,不釋放磁盤空間

問題說明:在刪除大量數(shù)據(jù)(本人操作的數(shù)據(jù)量在2000萬+)的情景下郊闯,并且在生產(chǎn)環(huán)境中請(qǐng)求量較大,此時(shí)機(jī)器的cpu負(fù)載會(huì)顯得很高,甚至機(jī)器卡頓無法操作团赁,這樣的操作應(yīng)該謹(jǐn)慎分批量操作育拨;在刪除命令執(zhí)行結(jié)束之后,發(fā)現(xiàn)磁盤的數(shù)據(jù)量大小并沒有改變欢摄。

解決方案:

  • 方案一:我們可以使用MongoDB提供的在線數(shù)據(jù)收縮的功能熬丧,通過Compact命令db.collectionName.runCommand("compact")進(jìn)行Collection級(jí)別的數(shù)據(jù)收縮,去除集合所在文件碎片怀挠。此命令是以O(shè)nline的方式提供收縮析蝴,收縮的同時(shí)會(huì)影響到線上的服務(wù)。為了解決這個(gè)問題,可以先在從節(jié)點(diǎn)執(zhí)行磁盤整理命令,操作結(jié)束后,再切換主節(jié)點(diǎn),將原來的主節(jié)點(diǎn)變?yōu)閺墓?jié)點(diǎn)筒狠,重新執(zhí)行Compact命令即可。

  • 方案二:使用從節(jié)點(diǎn)重新同步隆嗅,secondary節(jié)點(diǎn)重同步棚潦,刪除secondary節(jié)點(diǎn)中指定數(shù)據(jù),使之與primary重新開始數(shù)據(jù)同步疮跑。當(dāng)副本集成員數(shù)據(jù)太過陳舊组贺,也可以使用重新同步。數(shù)據(jù)的重新同步與直接復(fù)制數(shù)據(jù)文件不同祖娘,MongoDB會(huì)只同步數(shù)據(jù)失尖,因此重同步完成后的數(shù)據(jù)文件是沒有空集合的,以此實(shí)現(xiàn)了磁盤空間的回收渐苏。

  1. 若是primary節(jié)點(diǎn)掀潮,先強(qiáng)制將之變?yōu)閟econdary節(jié)點(diǎn),否則跳過此步驟:rs.stepdown(120)琼富;

  2. 然后在primary上刪除secondary節(jié)點(diǎn):rs.remove("IP:port");

刪除secondary節(jié)點(diǎn)dbpath下的所有文件

將節(jié)點(diǎn)重新加入集群仪吧,然后使之自動(dòng)進(jìn)行數(shù)據(jù)的同步:rs.add("IP:port");

  1. 等數(shù)據(jù)同步完成后,循環(huán)1-4的步驟可以將集群中所有節(jié)點(diǎn)的磁盤空間釋放

針對(duì)一些特殊情況鞠眉,不能下線secondary節(jié)點(diǎn)的薯鼠,可以新增一個(gè)節(jié)點(diǎn)到副本集中,然后secondary就自動(dòng)開始數(shù)據(jù)的同步了械蹋〕龌剩總的來說,重同步的方法是比較好的哗戈,第一基本不會(huì)阻塞副本集的讀寫郊艘,第二消耗的時(shí)間相對(duì)前兩種比較短。

4、MongoDB機(jī)器負(fù)載極高

問題說明:此情景是在客戶請(qǐng)求較大的情景性纱注,由于部署MongoDB的機(jī)器包含一主一從步做,MongoDB使得IO100%,數(shù)據(jù)庫阻塞奈附,出現(xiàn)大量慢查詢全度,進(jìn)而導(dǎo)致機(jī)器負(fù)載極高,應(yīng)用服務(wù)完全不可用斥滤。

  • 解決方案:在沒有機(jī)器及時(shí)擴(kuò)容的狀況下将鸵,首要任務(wù)便是減小機(jī)器的IO,在一臺(tái)機(jī)器出現(xiàn)一主一從佑颇,在大量數(shù)據(jù)寫入的情況下顶掉,會(huì)互相搶占IO資源。于是此時(shí)摒棄了MongoDB高可用的特點(diǎn)挑胸,摘掉了復(fù)制集當(dāng)中的從節(jié)點(diǎn)痒筒,保證每臺(tái)機(jī)器只有一個(gè)節(jié)點(diǎn)可以占用磁盤資源。之后茬贵,機(jī)器負(fù)載立馬下來簿透,服務(wù)變?yōu)檎?捎脿顟B(tài)解藻,但是此時(shí)MongoDB無法保證數(shù)據(jù)的完整性老充,一旦有主節(jié)點(diǎn)掛掉便會(huì)丟失數(shù)據(jù)。此方案只是臨時(shí)方法螟左,根本解決是可以增加機(jī)器的內(nèi)存啡浊、使用固態(tài)硬盤,或者采用增加分片集來減少單個(gè)機(jī)器的讀寫壓力胶背。

# 進(jìn)入主節(jié)點(diǎn)巷嚣,執(zhí)行移除成員的命令

rs.remove("127.0.0.1:20001");

# 注意:切勿直接關(guān)停實(shí)例

5、MongoDB分片鍵選擇不當(dāng)導(dǎo)致熱讀熱寫

問題說明:生產(chǎn)環(huán)境中钳吟,某一集合的片鍵使用了與_id生成方式相似廷粒,含有時(shí)間序列的字段作為升序片鍵,導(dǎo)致數(shù)據(jù)寫入時(shí)都在一個(gè)數(shù)據(jù)塊砸抛,隨著數(shù)據(jù)量增大评雌,會(huì)造成數(shù)據(jù)遷移到前面的分區(qū),造成系統(tǒng)資源的占用直焙,偶爾出現(xiàn)慢查詢景东。

  • 解決方案:臨時(shí)方案設(shè)置數(shù)據(jù)遷移的窗口,放在在正常的時(shí)間區(qū)段奔誓,對(duì)業(yè)務(wù)造成影響斤吐。根本解決是更換片鍵搔涝。

# 連接mongos實(shí)例,執(zhí)行以下命令

db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "23:00", stop : "4:00" } } }, true )和措;

# 查看均衡窗口

sh.getBalancerWindow()庄呈;

六、MongoDB優(yōu)化建議

1派阱、應(yīng)用層面優(yōu)化

  • 查詢優(yōu)化:確認(rèn)你的查詢是否充分利用到了索引诬留,用explain命令查看一下查詢執(zhí)行的情況,添加必要的索引贫母,避免掃表操作文兑。

  • 合理設(shè)計(jì)分片鍵:增量sharding-key:適合于可劃分范圍的字段,比如integer腺劣、float绿贞、date類型的,查詢時(shí)比較快橘原。隨機(jī)sharding-key: 適用于寫操作頻繁的場(chǎng)景籍铁,而這種情況下如果在一個(gè)shard上進(jìn)行會(huì)使得這個(gè)shard負(fù)載比其他高,不夠均衡趾断,故而希望能hash查詢key拒名,將寫分布在多個(gè)shard上進(jìn)行,考慮復(fù)合key作為sharding key, 總的原則是查詢快歼冰,盡量減少跨shard查詢靡狞,balance均衡次數(shù)少耻警;單一遞增的sharding key隔嫡,可能會(huì)造成寫數(shù)據(jù)全部在最后一片上,最后一片的寫壓力增大甘穿,數(shù)據(jù)量增大腮恩,會(huì)造成數(shù)據(jù)遷移到前面的分區(qū)。MongoDB默認(rèn)是單條記錄16M温兼,尤其在使用GFS的時(shí)候秸滴,一定要注意shrading-key的設(shè)計(jì)。不合理的sharding-key會(huì)出現(xiàn)募判,多個(gè)文檔荡含,在一個(gè)chunks上,同時(shí)届垫,因?yàn)镚FS中存貯的往往是大文件释液,導(dǎo)致MongoDB在做balance的時(shí)候無法通過sharding-key來把這多個(gè)文檔分開到不同的shard上, 這時(shí)候MongoDB會(huì)不斷報(bào)錯(cuò)最后導(dǎo)致MongoDB倒掉装处。解決辦法:加大chunks大形笳(治標(biāo)),設(shè)計(jì)合理的sharding-key(治本)。

  • 通過profile來監(jiān)控?cái)?shù)據(jù):進(jìn)行優(yōu)化查看當(dāng)前是否開啟profile功能 用命令db.getProfilingLevel() 返回level等級(jí)寝蹈,值為0|1|2李命,分別代表意思:0代表關(guān)閉,1代表記錄慢命令箫老,2代表全部封字。開啟profile功能命令為 db.setProfilingLevel(level); #level等級(jí),值level為1的時(shí)候耍鬓,慢命令默認(rèn)值為100ms周叮,更改為db.setProfilingLevel(level,slowms)如db.setProfilingLevel(1,50)這樣就更改為50毫秒通過db.system.profile.find() 查看當(dāng)前的監(jiān)控日志。

2界斜、硬件層面優(yōu)化

  • 確定熱數(shù)據(jù)大蟹碌ⅰ:可能你的數(shù)據(jù)集非常大,但是這并不那么重要各薇,重要的是你的熱數(shù)據(jù)集有多大项贺,你經(jīng)常訪問的數(shù)據(jù)有多大(包括經(jīng)常訪問的數(shù)據(jù)和所有索引數(shù)據(jù))。使用MongoDB峭判,你最好保證你的熱數(shù)據(jù)在你機(jī)器的內(nèi)存大小之下开缎,保證內(nèi)存能容納所有熱數(shù)據(jù);

  • 選擇正確的文件系統(tǒng):MongoDB的數(shù)據(jù)文件是采用的預(yù)分配模式林螃,并且在Replication里面奕删,Master和Replica Sets的非Arbiter節(jié)點(diǎn)都是會(huì)預(yù)先創(chuàng)建足夠的空文件用以存儲(chǔ)操作日志。這些文件分配操作在一些文件系統(tǒng)上可能會(huì)非常慢疗认,導(dǎo)致進(jìn)程被Block完残。所以我們應(yīng)該選擇那些空間分配快速的文件系統(tǒng)。這里的結(jié)論是盡量不要用ext3横漏,用ext4或xfs谨设;

3、架構(gòu)上的優(yōu)化

? 盡可能讓主從節(jié)點(diǎn)分?jǐn)傇诓煌臋C(jī)器上缎浇,避免IO操作的與MongoDB在同一臺(tái)機(jī)器扎拣;

七、總結(jié)

MongoDB具有高性能素跺、易擴(kuò)展二蓝、易上手等特點(diǎn),在正確使用的情況下指厌,其本身性能還是非常強(qiáng)悍刊愚,在一些關(guān)鍵點(diǎn)如片鍵的選擇、內(nèi)存的大小和磁盤IO仑乌,往往是限制其性能的最大瓶頸百拓。針對(duì)于片鍵琴锭,在業(yè)務(wù)系統(tǒng)初期,可以先不對(duì)集合進(jìn)行數(shù)據(jù)分片衙传,因?yàn)榉制I一旦確定就無法修改决帖,后期可根據(jù)業(yè)務(wù)系統(tǒng)的情況,認(rèn)真篩選字段蓖捶。一般情況下地回,不建議使用升序片鍵(是一種隨著時(shí)間穩(wěn)定增長的字段,自增長的主鍵是升序鍵 ),因?yàn)檫@個(gè)會(huì)導(dǎo)致局部的熱讀熱寫俊鱼,不能發(fā)揮分片集群的真正實(shí)力刻像。建議使用hash片鍵或者隨機(jī)分發(fā)的片鍵,這樣可以保證數(shù)據(jù)的均勻分發(fā)在分片節(jié)點(diǎn)并闲;針對(duì)于內(nèi)存细睡,建議內(nèi)存的大小能夠包含熱數(shù)據(jù)的大小加索引大小,保證內(nèi)存能容納所有熱數(shù)據(jù) 帝火。針對(duì)于磁盤資源溜徙,MongoDB的高速讀寫是以磁盤的IO作為基礎(chǔ),為了保證其性能犀填,建議將主從節(jié)點(diǎn)以及高IO的應(yīng)用分離蠢壹,以保證IO資源盡可能不存在搶占。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末九巡,一起剝皮案震驚了整個(gè)濱河市图贸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冕广,老刑警劉巖疏日,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異佳窑,居然都是意外死亡制恍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門神凑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人何吝,你說我怎么就攤上這事溉委。” “怎么了爱榕?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵瓣喊,是天一觀的道長。 經(jīng)常有香客問我黔酥,道長藻三,這世上最難降的妖魔是什么洪橘? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮棵帽,結(jié)果婚禮上熄求,老公的妹妹穿的比我還像新娘。我一直安慰自己逗概,他們只是感情好弟晚,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逾苫,像睡著了一般卿城。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铅搓,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天瑟押,我揣著相機(jī)與錄音,去河邊找鬼星掰。 笑死勉耀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蹋偏。 我是一名探鬼主播便斥,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼威始!你這毒婦竟也來了枢纠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤黎棠,失蹤者是張志新(化名)和其女友劉穎晋渺,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脓斩,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡木西,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了随静。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片八千。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖燎猛,靈堂內(nèi)的尸體忽然破棺而出恋捆,到底是詐尸還是另有隱情,我是刑警寧澤重绷,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布沸停,位于F島的核電站,受9級(jí)特大地震影響昭卓,放射性物質(zhì)發(fā)生泄漏愤钾。R本人自食惡果不足惜瘟滨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望能颁。 院中可真熱鬧杂瘸,春花似錦、人聲如沸劲装。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽占业。三九已至绒怨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谦疾,已是汗流浹背南蹂。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留念恍,地道東北人六剥。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像峰伙,于是被迫代替她去往敵國和親疗疟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361