分片(sharding)是MongoDB将大型集合分割到不同伺服器(或者說叢集)上所采用的方法,主要為應對高吞吐量與大資料量的應用場景提供了方法。
和既有的分庫分表、分區方案相比,MongoDB的最大差別在于它幾乎能自動完成所有事情,隻要告訴MongoDB要配置設定資料,它就能自動維護資料在不同伺服器之間的均衡。
一. 分片的叢集元件

1.Mongos 【路由】
作為請求的通路入口,所有的請求都由mongos來路由、分發、合并,這些動作對用戶端driver透明,使用者連接配接mongos就像連接配接mongod一樣使用。Mongos會根據請求類型及shard key将請求路由到對應的Shard。
2.Config Server 【配置伺服器】
存儲Sharding Cluster 的所有中繼資料,所有的中繼資料都存儲在config資料庫;
*儲存每個分片上的chunk的資訊 * 儲存chunk上的片鍵範圍。
3. Shard 【分片】
存儲應用資料記錄。
二. 分片優勢
1.對叢集進行抽象,讓叢集“不可見”,分片對應用系統是透明的。
Mongos是專有路由程序,其會将用戶端發來的請求準确無誤的路由到叢集中的一個或者一組伺服器上,同時會把接收到的響應拼裝起來發回到用戶端。
2.保證叢集總是可讀寫
将MongoDB的分片和複制集功能結合使用,在確定資料分片到多台伺服器的同時,也確定了每分資料都有相應的備份,可以確定有伺服器壞掉時,其他的從庫可以立即接替壞掉的部分繼續工作。提高了叢集的可用性和可靠性。
3.使叢集易于擴充
當系統需要更多的空間和資源的時候,MongoDB使我們可以按需友善的擴充系統容量。
三. 分片部署注意事項(常見錯誤)
1.配置可複制集作為分片節點與配置單獨使用的可複制集基本一樣。但啟動參數中需指定—shardsvr參數。
否則,在啟動資料庫分片時報錯:{"code" : 193,"ok" : 0, "errmsg" : "Cannot accept sharding commands if not started with --shardsvr“}。
2.建立配置伺服器叢集時,不能設定見證節點。
否則,報錯 "errmsg" : "Arbiters are not allowed in replica set configurations being used for config servers"。
3.配置Mongos 執行個體時,請不要配置dbpath參數。
否則,設定dbpath參數,服務無法正常啟動,報錯:Error parsing INI config file: unrecognised option 'dbpath'。
4.配置Mongos 執行個體時,需設定Keyfile。
否則,不設定Keyfile,Service無法正常啟動, 報錯:2018-05-10T15:30:26.791+0800 W SHARDING [mongosMain] Error initializing sharding state, sleeping for 2 seconds and trying again :: caused by :: Unauthorized: Error loading clusterID :: caused by :: not authorized on config to execute command { find: “version”, readConcern: { level: “majority”, afterOpTime: { ts: Timestamp 1525937413000|2, t: 1 } }, maxTimeMS: 30000
5.分片集合設定。
分片不會預設生成,需要先在資料庫中啟動分片(sh.enableSharding(“DBName”)),然後再設定集合分片(sh.shardCollection(“Collection”{片鍵}))
四. 分片管理的注意事項(常用指令)
1.檢查shards 配置及狀态
db.runCommand({listshards:1})
2. 檢查資料庫主片的位址以及是否分區
db.getSiblingDB("config").databases.find()
3. 檢查資料塊的數量
db.chunks.count() --需切換到配置資料庫(config)
4. 檢視分片的詳細資訊,包括資料庫資訊和範圍資訊
sh.status()
5. 索引是優化查詢性能的重要手段。當在分片集合上聲明索引時,每個分片都會為自己的集合部分定義單獨的索引。分片集合隻允許在_id字段和分片鍵上建立唯一索引。
6. 分割和遷移 MongoDB底層依賴2個機制來保持叢集的平衡:分割和遷移。
分割是把一個大的資料塊分割為2個更小的資料塊的過程。遷移就是在分片之間移動資料塊的過程。當某些分片伺服器包含的資料塊資料量大大超過其他分片伺服器時就會觸發遷移的過程,這個觸發器叫做遷移回合(migration round)
6.1 遷移觸發條件
6.2 檢視Balancer 程序是否開啟 sh.getBalancerState()
6.3 停Balancer 程序 sh.stopBalancer()和開啟Balancer 程序
6.4. 預設情況下 Balancer 程序一直在運作,為了降低Balancer程序對系統的運作,可以為Balancer程序設定運作時間視窗,讓Balancer程序在指定的時間視窗操作。
6.4.1 例如設定Balancer程序在23:00到6:00時間視窗内執行。db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "23:00", stop : "6:00" } } }, true ) ;
6.4.2 删除Balancer程序運作時間視窗
6.5. 檢視塊的範圍
6.5.1 如果集合資料量較小,可以直接通過sh.status()檢視
6.5.2 如果集合資料量較大,sh.status()無法反應此集合的分塊資訊。此時,可通過執行以下指令檢視printShardingStatus(db.getSisterDB("config"),1);
6.5.3 也可将指令切換到config資料庫下,執行db.chunks.find()檢視。可以輸入制定參數,例如,檢視分片repsms2,集合cloud-docs.PushMessageRecord的塊情況(cloud-docs為資料庫名稱)
db.chunks.find({"shard" : "repsms2","ns" : "cloud-docs.PushMessageRecord"}).pretty()
五. 備注
分片叢集管理的資料量比較大,并且分片的架構相對比較複雜。是以,一定在業務需求需要上分片時,再上分片,且不可準求“炫”的技術而上分片。另外,上線後,相關的監控一定要部署,逐漸完善。
本文版權歸作者所有,未經作者同意不得轉載,謝謝配合!!!