首頁 > 軟體

MongoDB超大塊資料問題解決

2023-02-10 06:02:28

引言

最近專案在使用MongoDB作為圖片和檔案的儲存資料庫,為啥不直接存MySQL裡,還要搭個MongoDB叢集,麻不麻煩?

讓我們一起,一探究竟,繼續學習解決MongoDB超大塊資料問題,實現快速入門,豐富個人簡歷,提高面試level,給自己增加一點談資,秒變面試小達人,BAT不是夢。

一、MongoDB伺服器管理

1、新增伺服器

可以在任何時間新增mongos程序,只要確保,它們的 --configdb選項指定了正確的設定伺服器副本集,並且使用者端可以立即與其建立連線。

2、修改分片中的伺服器

要修改一個分片的成員,需要直接連線到該分片的主節點,並重新設定副本集。叢集設定會檢測到變更並自動更新 config.shards

3、刪除分片

一般情況下,不應該從叢集中刪除分片,會給系統帶來不必要的壓力。

刪除分片時,要確保均衡器的開啟狀態。

均衡器的作用是把要刪除分片上的所有資料移動到其它分片,這個過程稱為排空。可以通過 removeShard命令執行排空操作。

二、均衡器

可以通過 sh.setBalancerState(false)關閉均衡器。關閉均衡器不會將正在進行的過程停止,也就是說遷移過程不會立即停止。

通過db.locks.find({"_id","balancer"})["state"]檢視均衡器是否關閉。0表示均衡器已關閉。

均衡過程會增加系統的負載,目標分片必須查詢源分片的所有檔案,並將檔案插入目標分片的塊中,然後源分片必須刪除這些檔案。

資料遷移是很消耗效能的,此時可以在config.settings集合中為均衡過程指定一個時間視窗。將其指定在一個閒暇時間執行。

如果設定了均衡視窗,應該對其進行監控,確保mongos能夠在所分配的時間內保持叢集的均衡。

均衡器使用塊的數量而不是資料的大小作為度量。移動一個塊被稱為遷移,這是MongoDB平衡資料的方式。可能會存在一個大塊的分片稱為許多小分片遷移的目標。

三、修改塊的大小

一個塊可以存放數百萬個檔案,塊越大,遷移到另一個分片所花費的時間就越長,預設情況下,塊的大小為64MB。

但對於64MB的塊,遷移時間太長了,為了加快遷移速度,可以減少塊的大小。

比如將塊的大小改為32MB。

db.settings.save({"_id","chunksize","value":32})

已經存在的塊不會發生改變,自動拆分僅會在插入或更新時發生,拆分操作是無法恢復的,如果增加了塊的大小,那麼已經存在的塊只會通過插入或更新來增長,直到它們達到新的大小。塊大小的取值範圍在1MB到1024MB。

這是一個叢集範圍的設定,會影響所有的集合和資料庫。因此,如果一個集合需要較小的塊,另一個集合需要較大的塊,那麼可能需要在這兩個大小間取一個折中的值。

如果MongoDB的遷移過於頻繁或者使用的檔案太大,則可能需要增加塊的大小。

四、超大塊

一個塊的所有資料都位於某個特定的分片上。如果最終這個分片擁有的塊比其它分片多,那麼MongoDB會將一些塊移動到其它分片上。

當一個塊大於 config.settings中所設定的最大塊大小時,均衡器就不允許移動這個塊了。這些不可拆分、不可移動的塊被稱為超大塊

1、分發超大塊

要解決超大塊引起的叢集不均衡問題,就必須將超大塊均勻地分配到各個分片中。

2、分發超大塊步驟:

  • 關閉均衡器 sh.setBalancerState(false)
  • 因為MongoDB不允許移動超過最大塊大小的塊,所以要暫時先增大塊大小,使其超過現有的最大塊塊大小。記錄下當時的塊大小。db.settings.save({"_id","chunksize","value":maxInteger})
  • 使用moveChunk命令移動分片中的超大塊;
  • 在源分片剩餘的塊上執行splitChunk命令,直到其塊數量與目標分片塊數量大致相同;
  • 將塊大小設定為其最初值;
  • 開啟均衡器

3、避免出現超大塊

更改片鍵,使其擁有更細粒度的分片。

通過db.currentOp()檢視當前操作,``db.currentOp()```最常見的用途是查詢慢操作。

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、輸出內容詳解:

  • opid,操作的唯一標識,可以使用這個欄位來終止操作;
  • active,操作是否正在進行,如果為false,意味著此操作已經讓出或者正在等待其它操作交出鎖;
  • secs_running,操作的持續時間,可以使用這個欄位查詢耗時過長的操作;
  • op,操作型別,通常為query、insert、update、remove;
  • desc,使用者端的識別符號,可以與紀錄檔中的訊息相關聯;
  • locks,描述操作所涉及的鎖型別;
  • waitingForLock,當前操作是否處於阻塞中並等待獲取鎖;
  • numYields,操作釋放鎖以允許其它操作進行的次數。一個操作只有在其它操作進入佇列並等待獲取它的鎖時才會讓出自己的鎖,如果沒有操作處於waitingForLock狀態,則當前操作不會讓出鎖;
  • lockStats.timeAcquiringMiros,操作為了獲取鎖所花費的時間;

通過``db.currentOp()找到慢查詢後,可以通過db.killOp(opid)```的方式將其終止。

並不是所有操作都可以被終止,只有當操作讓出時,才能終止,因此,更新、查詢、刪除操作都可以被終止,但持有或等待鎖的操作不能被終止。

如果MongoDB中的請求發生了堆積,那麼這些寫操作將堆積在作業系統的通訊端緩衝區,當終止MongoDB正在執行的寫操作時,MongoDB依舊會處理緩衝區的寫操作。可以通過開啟寫入確認機制,保證每次寫操作都要等前一個寫操作完成後才能執行,而不是僅僅等到前一個寫操作處於資料庫伺服器的緩衝區就開始下一次寫入。

五、系統分析器

系統分析器可以提供大量關於耗時過長操作的資訊,但系統分析器會嚴重的降低MongoDB的效率,因為每次寫操作都會將其記錄在system.profile中記錄一下。每次讀操作都必須等待system.profile寫入完畢才行。

開啟分析器:

MongoDB Enterprise > db.setProfilingLevel(2)
{ "was" : 0, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }

slowms決定了在紀錄檔中列印慢速操作的閾值。比如slowms設定為100,那麼每個耗時超過100毫秒的操作都會被記錄在紀錄檔中,即使分析器是關閉的。

查詢分析級別:

MongoDB Enterprise > db.getProfilingLevel()
2

重新啟動MongoDB資料庫會重置分析級別。

六、一些常見的輔助命令

通過Object.bsonsize函數獲取其在磁碟中儲存大小,單位是位元組。

> Object.bsonsize(db.worker.find())
65194

使用mongotop統計哪些集合最繁忙。

使用mongotop --locks統計每個資料庫的鎖資訊。

mongostat提供了整個伺服器範圍的資訊。

以上就是MongoDB超大塊資料問題解決的詳細內容,更多關於MongoDB超大塊資料的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com