高資料量和高吞吐量的資料庫應用會對單機的效能造成較大壓力,大的查詢會將單機的 CPU 耗盡,大的資料量對單機的儲存壓力較大,最終會耗盡系統的記憶體壓力轉移到磁碟 IO 上。
為了解決這些問題,有兩個基本的方法:
MongoDB 的分片就是水平擴充套件的體現,使用分片減少了每個分片需要處理的請求數。通過水平擴充套件,叢集可以提高自己的儲存容量和吞吐量。
通常來說,不宜過早對資料進行分片,這會增加部署的複雜性;也不應該過晚進行分片,因為很難在不停止執行的情況下對超載的系統進行分片。
通常情況下,分片用於以下情況:
一個 MongoDB 的分片叢集包含以下元件:
在一個分片服務內部,MongoDB 會把資料分為塊,每個 chunk 代表這個分片內部的一部分資料。其作用有兩個:
在 MongoDB 中,chunk 的分裂和遷移是非常耗費 IO 資源的,並且 chunk 的分裂只會發生在插入和更新時。
對於大塊和小塊的選擇,其實各有優缺點:
隨著資料的增長,其中的資料大小超過了設定的 chunk size(預設 64M),則這個 chunk 就會分裂成兩個。
資料增長的速度快慢會影響 chunk 分裂的速度,資料增長越快則 chunk 分裂的速度越快。
需要注意的是,如果分片試圖分裂的時候,其中一個設定伺服器停止執行了,那麼將無法更新後設資料,則會出現分片一直嘗試拆分塊並一直失敗,這種一直無法成功的過程最終會導致 拆分風暴。
一旦發生了分裂,比如說 Shard A 分裂成 3 個塊,Shard B 分裂成 3 個塊,而 Shard C 仍然只有 1 個塊,則各個分片上的 chunk 數量會不平衡,。
這時候,mongos 中的 balancer 執行緒就會執行自動平衡,把 chunk 從 chunk 數量最多的分片挪動到 chunk 數量最少的節點。
在對集合進行分片的時,需要選擇一個或多個組合欄位來對資料進行拆分,這個鍵(這些鍵)被稱為分片鍵。
選擇分片鍵非常重要,分片鍵的有以下注意事項:
分片過程中可以使用雜湊索引作為分片鍵,其最大的好處是能保證資料在各個節點分佈基本均勻。
對於基於雜湊的分片,MongoDB 計算一個欄位的雜湊值,並用這個雜湊值來建立資料塊。
在使用基於雜湊分片的系統中,擁有相近分片鍵的檔案很可能不會儲存在同一個資料塊中,資料的分離性更好一些。
基於雜湊分片可以很好地在叢集中分配負載,但是,如果隨機存取超出了 RAM 大小的資料時,效率會比較低。
對於基於範圍的分片,MongoDB 按照分片鍵的範圍把資料分成不同部分。
在使用分片鍵做範圍劃分的系統中,擁有相近分片鍵的檔案很可能儲存在同一個資料塊中,因此也會儲存在同一個分片中。
如果這個分片鍵是一個自增的值時,將會使 MongoDB 難以保持塊的均衡,因為 MongoDB 需要不斷將最後一個分片的資料塊移動到其他分片上。
雜湊分片更適合隨機存取,不適合範圍查詢;範圍分片則是適合範圍查詢,不適合平衡負載。
一個自定義的方案是,對自增欄位構建雜湊索引(儘可能是仍然保持有序的雜湊演演算法)即可解決。