MongoDB超大塊數(shù)據(jù)問(wèn)題解決
引言
最近項(xiàng)目在使用MongoDB作為圖片和文檔的存儲(chǔ)數(shù)據(jù)庫(kù),為啥不直接存MySQL里,還要搭個(gè)MongoDB集群,麻不麻煩?
讓我們一起,一探究竟,繼續(xù)學(xué)習(xí)解決MongoDB超大塊數(shù)據(jù)問(wèn)題,實(shí)現(xiàn)快速入門,豐富個(gè)人簡(jiǎn)歷,提高面試level,給自己增加一點(diǎn)談資,秒變面試小達(dá)人,BAT不是夢(mèng)。
一、MongoDB服務(wù)器管理
1、添加服務(wù)器
可以在任何時(shí)間添加mongos進(jìn)程,只要確保,它們的 --configdb
選項(xiàng)指定了正確的配置服務(wù)器副本集,并且客戶端可以立即與其建立連接。
2、修改分片中的服務(wù)器
要修改一個(gè)分片的成員,需要直接連接到該分片的主節(jié)點(diǎn),并重新配置副本集。集群配置會(huì)檢測(cè)到變更并自動(dòng)更新 config.shards
。
3、刪除分片
一般情況下,不應(yīng)該從集群中刪除分片,會(huì)給系統(tǒng)帶來(lái)不必要的壓力。
刪除分片時(shí),要確保均衡器的打開(kāi)狀態(tài)。
均衡器的作用是把要?jiǎng)h除分片上的所有數(shù)據(jù)移動(dòng)到其它分片,這個(gè)過(guò)程稱為排空??梢酝ㄟ^(guò) removeShard
命令執(zhí)行排空操作。
二、均衡器
可以通過(guò) sh.setBalancerState(false)
關(guān)閉均衡器。關(guān)閉均衡器不會(huì)將正在進(jìn)行的過(guò)程停止,也就是說(shuō)遷移過(guò)程不會(huì)立即停止。
通過(guò)db.locks.find({"_id","balancer"})["state"]
查看均衡器是否關(guān)閉。0表示均衡器已關(guān)閉。
均衡過(guò)程會(huì)增加系統(tǒng)的負(fù)載,目標(biāo)分片必須查詢?cè)捶制乃形臋n,并將文檔插入目標(biāo)分片的塊中,然后源分片必須刪除這些文檔。
數(shù)據(jù)遷移是很消耗性能的,此時(shí)可以在config.settings
集合中為均衡過(guò)程指定一個(gè)時(shí)間窗口。將其指定在一個(gè)閑暇時(shí)間執(zhí)行。
如果設(shè)置了均衡窗口,應(yīng)該對(duì)其進(jìn)行監(jiān)控,確保mongos能夠在所分配的時(shí)間內(nèi)保持集群的均衡。
均衡器使用塊的數(shù)量而不是數(shù)據(jù)的大小作為度量。移動(dòng)一個(gè)塊被稱為遷移,這是MongoDB平衡數(shù)據(jù)的方式??赡軙?huì)存在一個(gè)大塊的分片稱為許多小分片遷移的目標(biāo)。
三、修改塊的大小
一個(gè)塊可以存放數(shù)百萬(wàn)個(gè)文檔,塊越大,遷移到另一個(gè)分片所花費(fèi)的時(shí)間就越長(zhǎng),默認(rèn)情況下,塊的大小為64MB。
但對(duì)于64MB的塊,遷移時(shí)間太長(zhǎng)了,為了加快遷移速度,可以減少塊的大小。
比如將塊的大小改為32MB。
db.settings.save({"_id","chunksize","value":32})
已經(jīng)存在的塊不會(huì)發(fā)生改變,自動(dòng)拆分僅會(huì)在插入或更新時(shí)發(fā)生,拆分操作是無(wú)法恢復(fù)的,如果增加了塊的大小,那么已經(jīng)存在的塊只會(huì)通過(guò)插入或更新來(lái)增長(zhǎng),直到它們達(dá)到新的大小。塊大小的取值范圍在1MB到1024MB。
這是一個(gè)集群范圍的設(shè)置,會(huì)影響所有的集合和數(shù)據(jù)庫(kù)。因此,如果一個(gè)集合需要較小的塊,另一個(gè)集合需要較大的塊,那么可能需要在這兩個(gè)大小間取一個(gè)折中的值。
如果MongoDB的遷移過(guò)于頻繁或者使用的文檔太大,則可能需要增加塊的大小。
四、超大塊
一個(gè)塊的所有數(shù)據(jù)都位于某個(gè)特定的分片上。如果最終這個(gè)分片擁有的塊比其它分片多,那么MongoDB會(huì)將一些塊移動(dòng)到其它分片上。
當(dāng)一個(gè)塊大于 config.settings
中所設(shè)置的最大塊大小時(shí),均衡器就不允許移動(dòng)這個(gè)塊了。這些不可拆分、不可移動(dòng)的塊被稱為超大塊。
1、分發(fā)超大塊
要解決超大塊引起的集群不均衡問(wèn)題,就必須將超大塊均勻地分配到各個(gè)分片中。
2、分發(fā)超大塊步驟:
- 關(guān)閉均衡器
sh.setBalancerState(false)
; - 因?yàn)镸ongoDB不允許移動(dòng)超過(guò)最大塊大小的塊,所以要暫時(shí)先增大塊大小,使其超過(guò)現(xiàn)有的最大塊塊大小。記錄下當(dāng)時(shí)的塊大小。
db.settings.save({"_id","chunksize","value":maxInteger})
; - 使用
moveChunk
命令移動(dòng)分片中的超大塊; - 在源分片剩余的塊上運(yùn)行
splitChunk
命令,直到其塊數(shù)量與目標(biāo)分片塊數(shù)量大致相同; - 將塊大小設(shè)置為其最初值;
- 開(kāi)啟均衡器
3、避免出現(xiàn)超大塊
更改片鍵,使其擁有更細(xì)粒度的分片。
通過(guò)db.currentOp()
查看當(dāng)前操作,``db.currentOp()```最常見(jiàn)的用途是查找慢操作。
MongoDB Enterprise > db.currentOp() { "inprog" : [ { "type" : "op", "host" : "LAPTOP-P6QEH9UD:27017", "desc" : "conn1", "connectionId" : 1, "client" : "127.0.0.1:50481", "appName" : "MongoDB Shell", "clientMetadata" : { "application" : { "name" : "MongoDB Shell" }, "driver" : { "name" : "MongoDB Internal Client", "version" : "5.0.14" }, "os" : { "type" : "Windows", "name" : "Microsoft Windows 10", "architecture" : "x86_64", "version" : "10.0 (build 19044)" } }, "active" : true, "currentOpTime" : "2023-02-07T23:12:23.086+08:00", "threaded" : true, "opid" : 422, "lsid" : { "id" : UUID("f83e33d1-9966-44a4-87de-817de0d804a3"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "secs_running" : NumberLong(0), "microsecs_running" : NumberLong(182), "op" : "command", "ns" : "admin.$cmd.aggregate", "command" : { "aggregate" : 1, "pipeline" : [ { "$currentOp" : { "allUsers" : true, "idleConnections" : false, "truncateOps" : false } }, { "$match" : { } } ], "cursor" : { }, "lsid" : { "id" : UUID("f83e33d1-9966-44a4-87de-817de0d804a3") }, "$readPreference" : { "mode" : "primaryPreferred" }, "$db" : "admin" }, "numYields" : 0, "locks" : { }, "waitingForLock" : false, "lockStats" : { }, "waitingForFlowControl" : false, "flowControlStats" : { } }, { "type" : "op", "host" : "LAPTOP-P6QEH9UD:27017", "desc" : "Checkpointer", "active" : true, "currentOpTime" : "2023-02-07T23:12:23.086+08:00", "opid" : 3, "op" : "none", "ns" : "", "command" : { }, "numYields" : 0, "locks" : { }, "waitingForLock" : false, "lockStats" : { }, "waitingForFlowControl" : false, "flowControlStats" : { } }, { "type" : "op", "host" : "LAPTOP-P6QEH9UD:27017", "desc" : "JournalFlusher", "active" : true, "currentOpTime" : "2023-02-07T23:12:23.086+08:00", "opid" : 419, "op" : "none", "ns" : "", "command" : { }, "numYields" : 0, "locks" : { }, "waitingForLock" : false, "lockStats" : { }, "waitingForFlowControl" : false, "flowControlStats" : { } } ], "ok" : 1 }
4、輸出內(nèi)容詳解:
- opid,操作的唯一標(biāo)識(shí),可以使用這個(gè)字段來(lái)終止操作;
- active,操作是否正在進(jìn)行,如果為false,意味著此操作已經(jīng)讓出或者正在等待其它操作交出鎖;
- secs_running,操作的持續(xù)時(shí)間,可以使用這個(gè)字段查詢耗時(shí)過(guò)長(zhǎng)的操作;
- op,操作類型,通常為query、insert、update、remove;
- desc,客戶端的標(biāo)識(shí)符,可以與日志中的消息相關(guān)聯(lián);
- locks,描述操作所涉及的鎖類型;
- waitingForLock,當(dāng)前操作是否處于阻塞中并等待獲取鎖;
- numYields,操作釋放鎖以允許其它操作進(jìn)行的次數(shù)。一個(gè)操作只有在其它操作進(jìn)入隊(duì)列并等待獲取它的鎖時(shí)才會(huì)讓出自己的鎖,如果沒(méi)有操作處于
waitingForLock
狀態(tài),則當(dāng)前操作不會(huì)讓出鎖; - lockStats.timeAcquiringMiros,操作為了獲取鎖所花費(fèi)的時(shí)間;
通過(guò)``db.currentOp()找到慢查詢后,可以通過(guò)db.killOp(opid)```的方式將其終止。
并不是所有操作都可以被終止,只有當(dāng)操作讓出時(shí),才能終止,因此,更新、查找、刪除操作都可以被終止,但持有或等待鎖的操作不能被終止。
如果MongoDB中的請(qǐng)求發(fā)生了堆積,那么這些寫(xiě)操作將堆積在操作系統(tǒng)的套接字緩沖區(qū),當(dāng)終止MongoDB正在運(yùn)行的寫(xiě)操作時(shí),MongoDB依舊會(huì)處理緩沖區(qū)的寫(xiě)操作??梢酝ㄟ^(guò)開(kāi)啟寫(xiě)入確認(rèn)機(jī)制,保證每次寫(xiě)操作都要等前一個(gè)寫(xiě)操作完成后才能執(zhí)行,而不是僅僅等到前一個(gè)寫(xiě)操作處于數(shù)據(jù)庫(kù)服務(wù)器的緩沖區(qū)就開(kāi)始下一次寫(xiě)入。
五、系統(tǒng)分析器
系統(tǒng)分析器可以提供大量關(guān)于耗時(shí)過(guò)長(zhǎng)操作的信息,但系統(tǒng)分析器會(huì)嚴(yán)重的降低MongoDB的效率,因?yàn)槊看螌?xiě)操作都會(huì)將其記錄在system.profile
中記錄一下。每次讀操作都必須等待system.profile
寫(xiě)入完畢才行。
開(kāi)啟分析器:
MongoDB Enterprise > db.setProfilingLevel(2) { "was" : 0, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }
slowms
決定了在日志中打印慢速操作的閾值。比如slowms
設(shè)置為100,那么每個(gè)耗時(shí)超過(guò)100毫秒的操作都會(huì)被記錄在日志中,即使分析器是關(guān)閉的。
查詢分析級(jí)別:
MongoDB Enterprise > db.getProfilingLevel() 2
重新啟動(dòng)MongoDB數(shù)據(jù)庫(kù)會(huì)重置分析級(jí)別。
六、一些常見(jiàn)的輔助命令
通過(guò)Object.bsonsize
函數(shù)獲取其在磁盤中存儲(chǔ)大小,單位是字節(jié)。
> Object.bsonsize(db.worker.find()) 65194
使用mongotop
統(tǒng)計(jì)哪些集合最繁忙。
使用mongotop --locks
統(tǒng)計(jì)每個(gè)數(shù)據(jù)庫(kù)的鎖信息。
mongostat
提供了整個(gè)服務(wù)器范圍的信息。
以上就是MongoDB超大塊數(shù)據(jù)問(wèn)題解決的詳細(xì)內(nèi)容,更多關(guān)于MongoDB超大塊數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MongoDB 3.4 安裝以 Windows 服務(wù)方式運(yùn)行的詳細(xì)步驟
這篇文章主要介紹了MongoDB 3.4 安裝以 Windows 服務(wù)方式運(yùn)行的詳細(xì)步驟,需要的朋友可以參考下2017-09-09Windows下MongoDB配置用戶權(quán)限實(shí)例
這篇文章主要介紹了Windows下MongoDB配置用戶權(quán)限實(shí)例,本文實(shí)現(xiàn)需要輸入用戶名、密碼才可以訪問(wèn)MongoDB數(shù)據(jù)庫(kù),需要的朋友可以參考下2015-01-01SpringBoot整合redis及mongodb的詳細(xì)過(guò)程
這篇文章主要介紹了SpringBoot整合redis及mongodb,本節(jié)我們來(lái)把關(guān)注點(diǎn)轉(zhuǎn)向NoSQL,文章結(jié)合示例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2022-10-10關(guān)于mongoDB數(shù)據(jù)庫(kù)添加賬號(hào)的問(wèn)題
這篇文章主要介紹了mongoDB數(shù)據(jù)庫(kù)添加賬號(hào)的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02