MongoDB Sharding分片配置
生活随笔
收集整理的這篇文章主要介紹了
MongoDB Sharding分片配置
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Ps:mongod是mongodb實例,mongos被默認為為mongodb sharding的路由實例。 本文使用的mongodb版本為3.2.9,因此參考網址為:https://docs.mongodb.com/v3.2/sharding/ 此外最后幾個部分還引用了https://yq.aliyun.com/articles/60096中的一些問題描述及解決方案。 一、Sharding集群簡介
1.數據分片(Shards) 用來保存數據,保證數據的高可用性和一致性。可以是一個單獨的mongod實例,也可以是一個副本集。在生產環境下Shard一般是一個Replica Set,以防止該數據片的單點故障。可以將所有shard的副本集放在一個服務器多個mongodb實例中。 2.查詢路由(Query Routers) 路由就是mongos的實例,客戶端直接連接mongos,由mongos把讀寫請求路由到指定的Shard上去。 一個Sharding集群,可以有一個mongos,也可以如上圖所示為每個App Server配置一個mongos以減輕路由壓力。 注意這里的mongos并不要配置為rs,因為只是個路由,并不存儲數據,配置多個mongos的意思是配置多個單獨的mongos實例。 3.配置服務器(Config servers) 保存集群的元數據(metadata),包含各個Shard的路由規則。3.2版本以后config server可以配置為replica set(CSRS),3.4以后config server必須配置為rs。 config server的rs不能有arbiter(3.2.9版本是這樣,其他版本未測試),生產上建議config server的rs至少要有3個副本集成員。 MongoDB是在collection級別實現的水平分片。 ? 二、分片鍵:Shard keys
--sh.status()的相關結果: test.t shard key: { "id" : 1 } unique: false balancing: true chunks: shard1 1 shard2 1 shard3 1 { "id" : { "$minKey" : 1 } } -->> { "id" : 2 } on : shard1 Timestamp(2, 0) { "id" : 2 } -->> { "id" : 22 } on : shard3 Timestamp(3, 0) { "id" : 22 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(3, 1) 從sh.status的結果可以看到id為[1,2)的被分配至shard1,[2,22)被分配至shard2,其他的全部被分配至shard3,分布極其不均勻。 由于默認的ranged sharding策略會導致自增shard key分布及其不均勻,我們需要在定時的使用sh.splitAt()方法來為分片指定分片chunk大小: sh.splitAt("test.t",{id:500}) sh.splitAt("test.t",{id:1000}) sh.splitAt("test.t",{id:1500}) sh.splitAt("test.t",{id:2000}) for(i=1;i<=3000;i++){db.t.insert({id:i,name:"Leo"})} --sh.status()顯示的分片結果如下: test.t shard key: { "id" : 1 } unique: false balancing: true chunks: shard1 2 --shard2上有2個chunks,分別是[1500,2000]和[2000,$maxKey) shard2 2 shard3 1 { "id" : { "$minKey" : 1 } } -->> { "id" : 500 } on : shard1 Timestamp(2, 0) { "id" : 500 } -->> { "id" : 1000 } on : shard3 Timestamp(3, 0) { "id" : 1000 } -->> { "id" : 1500 } on : shard1 Timestamp(4, 0) { "id" : 1500 } -->> { "id" : 2000 } on : shard2 Timestamp(4, 1) { "id" : 2000 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(3, 3) tag aware分片策略還未測試,有待以后補充。
7.shards的擴容 當需要水平擴容時我們就需要進行shards添加了,添加步驟如下:(本例在70上直接添加單實例的27022端口的shard實例) directoryperdb=true shardsvr = true logpath=/home/mongod/shard4/mongod.log logappend=true fork=true port=27022 dbpath=/home/mongod/shard4 pidfilepath=/home/mongod/shard4/mongod.pid 啟動此實例后,在mongos上執行: sh.addShard("192.168.20.70:27022") 一段時間后sh.status()看到的結果如下: test.t shard key: { "id" : 1 } unique: false balancing: true chunks: shard1 1 shard0004 1 --mongos自動將新的單實例mongoDB的chunk命名為shard0004 shard2 2 shard3 1 { "id" : { "$minKey" : 1 } } -->> { "id" : 500 } on : shard0004 Timestamp(5, 0) { "id" : 500 } -->> { "id" : 1000 } on : shard3 Timestamp(3, 0) { "id" : 1000 } -->> { "id" : 1500 } on : shard1 Timestamp(5, 1) { "id" : 1500 } -->> { "id" : 2000 } on : shard2 Timestamp(4, 1) { "id" : 2000 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(3, 3) --可以看到balancer自動將chunk進行了遷移,遷移機制為mongodb內部決定,原理參見第八部分。 八、Sharding的負載均衡(即Balancer) MongoDB Sharding的自動負載均衡目前是由mongos的后臺線程來做的,并且每個集合同一時刻只能有一個遷移任務,負載均衡主要根據集合在各個 shard上chunk的數量來決定的,相差超過一定閾值(跟chunk總數量相關)就會觸發chunk遷移。 Balancer默認是開啟的,為了避免chunk遷移影響到線上業務,可以通過設置遷移執行窗口,比如只允許凌晨2:00-6:00期間進行遷移。 mongo --port=27019 --連接到mongos use config db.settings.update( { _id: "balancer" }, { $set: { activeWindow : { start : "02:00", stop : "06:00" } } }, { upsert: true } ) Balancer會在服務器local time的凌晨2-6點才執行chunk的balance。 另外,在進行sharding備份時(通過mongos或者單獨備份config server和所有shard),需要停止負載均衡以免備份出來的數據出現狀態不一致問題。 sh.setBalancerState("false") 或者: sh.stopBalancer() 九、其他問題 moveChunk歸檔設置 使用3.0及以前版本的Sharded cluster可能會遇到一個問題,停止寫入數據后,數據目錄里的磁盤空間占用還會一直增加。 上述行為是由sharding.archiveMovedChunks配置項決定的,該配置項在3.0及以前的版本默認為true,即在move chunk時,源shard會將遷移的chunk數據歸檔一份在數據目錄里,當出現問題時,可用于恢復。也就是說,chunk發生遷移時,源節點上的空間并沒有釋放出來,而目標節點又占用了新的空間。 在3.2版本,該配置項默認值也被設置為false,默認不會對moveChunk的數據在源shard上歸檔。 recoverShardingState設置 使用MongoDB Sharded cluster時,還可能遇到一個問題,就是啟動 shard后,shard 不能正常服務,Primary上調用ismaster時,結果卻為 true,也無法正常執行其他命令,其狀態類似如下: PRIMARY> db.isMaster() { "hosts" : [ "host1:9003", "host2:9003", "host3:9003" ], "setName" : "mongo-9003", "setVersion" : 9, "ismaster" : false, // primary 的 ismaster 為 false??? "secondary" : true, "primary" : "host1:9003", "me" : "host1:9003", "electionId" : ObjectId("57c7e62d218e9216c70aa3cf"), "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2016-09-01T12:29:27.113Z"), "maxWireVersion" : 4, "minWireVersion" : 0, "ok" : 1 } 查看其錯誤日志,會發現shard一直無法連接上config server,上述行為是由sharding.recoverShardingState選項決定,默認為true,也就是說,shard啟動時,其會連接config server進行sharding 狀態的一些初始化,而如果config server連不上,初始化工作就一直無法完成,導致 shard 狀態不正常。 有同學在將Sharded cluster所有節點都遷移到新的主機上時遇到了上述問題,因為config server的信息發生變化了,而shard啟動時還會連接之前的config server,通過在啟動命令行加上--setParameter recoverShardingState=false來啟動shard就能恢復正常了。 ? 上述默認設計的確有些不合理,config server的異常不應該去影響shard,而且最終的問題的表象也很不明確,在3.4大版本里,MongoDB也會對這塊進行修改去掉這個參數,默認不會有recoverShardingState的邏輯,具體參考SERVER-24465。
1.數據分片(Shards) 用來保存數據,保證數據的高可用性和一致性。可以是一個單獨的mongod實例,也可以是一個副本集。在生產環境下Shard一般是一個Replica Set,以防止該數據片的單點故障。可以將所有shard的副本集放在一個服務器多個mongodb實例中。 2.查詢路由(Query Routers) 路由就是mongos的實例,客戶端直接連接mongos,由mongos把讀寫請求路由到指定的Shard上去。 一個Sharding集群,可以有一個mongos,也可以如上圖所示為每個App Server配置一個mongos以減輕路由壓力。 注意這里的mongos并不要配置為rs,因為只是個路由,并不存儲數據,配置多個mongos的意思是配置多個單獨的mongos實例。 3.配置服務器(Config servers) 保存集群的元數據(metadata),包含各個Shard的路由規則。3.2版本以后config server可以配置為replica set(CSRS),3.4以后config server必須配置為rs。 config server的rs不能有arbiter(3.2.9版本是這樣,其他版本未測試),生產上建議config server的rs至少要有3個副本集成員。 MongoDB是在collection級別實現的水平分片。 ? 二、分片鍵:Shard keys
- shard key在sharding搭建完畢后是不能修改的,一個collection上只能有一個shard key。
- shard key上必須有索引(可以是以shard key開頭的聯合索引),如果沒有mongodb會為shard key創建索引。如果是已經存在的collection那么必須手動為shard key創建索引。
- 在sharding的collection中只有_id和shard key前綴的索引可以是unique index,其他索引只能是普通索引。如果一個普通key上有unique index那么你不能以其他key為shard key對collection進行sharding。
- shard key的選擇將會影響整個集群的效率,可擴展性和性能。而且也會影響你所能選擇的分片策略。
- sh.addShardTag() 給shard設置標簽A
- sh.addTagRange() 給集合的某個chunk范圍設置標簽A,最終MongoDB會保證設置標簽 A 的chunk范圍(或該范圍的超集)分布設置了標簽 A 的 shard 上。
--sh.status()的相關結果: test.t shard key: { "id" : 1 } unique: false balancing: true chunks: shard1 1 shard2 1 shard3 1 { "id" : { "$minKey" : 1 } } -->> { "id" : 2 } on : shard1 Timestamp(2, 0) { "id" : 2 } -->> { "id" : 22 } on : shard3 Timestamp(3, 0) { "id" : 22 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(3, 1) 從sh.status的結果可以看到id為[1,2)的被分配至shard1,[2,22)被分配至shard2,其他的全部被分配至shard3,分布極其不均勻。 由于默認的ranged sharding策略會導致自增shard key分布及其不均勻,我們需要在定時的使用sh.splitAt()方法來為分片指定分片chunk大小: sh.splitAt("test.t",{id:500}) sh.splitAt("test.t",{id:1000}) sh.splitAt("test.t",{id:1500}) sh.splitAt("test.t",{id:2000}) for(i=1;i<=3000;i++){db.t.insert({id:i,name:"Leo"})} --sh.status()顯示的分片結果如下: test.t shard key: { "id" : 1 } unique: false balancing: true chunks: shard1 2 --shard2上有2個chunks,分別是[1500,2000]和[2000,$maxKey) shard2 2 shard3 1 { "id" : { "$minKey" : 1 } } -->> { "id" : 500 } on : shard1 Timestamp(2, 0) { "id" : 500 } -->> { "id" : 1000 } on : shard3 Timestamp(3, 0) { "id" : 1000 } -->> { "id" : 1500 } on : shard1 Timestamp(4, 0) { "id" : 1500 } -->> { "id" : 2000 } on : shard2 Timestamp(4, 1) { "id" : 2000 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(3, 3) tag aware分片策略還未測試,有待以后補充。
7.shards的擴容 當需要水平擴容時我們就需要進行shards添加了,添加步驟如下:(本例在70上直接添加單實例的27022端口的shard實例) directoryperdb=true shardsvr = true logpath=/home/mongod/shard4/mongod.log logappend=true fork=true port=27022 dbpath=/home/mongod/shard4 pidfilepath=/home/mongod/shard4/mongod.pid 啟動此實例后,在mongos上執行: sh.addShard("192.168.20.70:27022") 一段時間后sh.status()看到的結果如下: test.t shard key: { "id" : 1 } unique: false balancing: true chunks: shard1 1 shard0004 1 --mongos自動將新的單實例mongoDB的chunk命名為shard0004 shard2 2 shard3 1 { "id" : { "$minKey" : 1 } } -->> { "id" : 500 } on : shard0004 Timestamp(5, 0) { "id" : 500 } -->> { "id" : 1000 } on : shard3 Timestamp(3, 0) { "id" : 1000 } -->> { "id" : 1500 } on : shard1 Timestamp(5, 1) { "id" : 1500 } -->> { "id" : 2000 } on : shard2 Timestamp(4, 1) { "id" : 2000 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(3, 3) --可以看到balancer自動將chunk進行了遷移,遷移機制為mongodb內部決定,原理參見第八部分。 八、Sharding的負載均衡(即Balancer) MongoDB Sharding的自動負載均衡目前是由mongos的后臺線程來做的,并且每個集合同一時刻只能有一個遷移任務,負載均衡主要根據集合在各個 shard上chunk的數量來決定的,相差超過一定閾值(跟chunk總數量相關)就會觸發chunk遷移。 Balancer默認是開啟的,為了避免chunk遷移影響到線上業務,可以通過設置遷移執行窗口,比如只允許凌晨2:00-6:00期間進行遷移。 mongo --port=27019 --連接到mongos use config db.settings.update( { _id: "balancer" }, { $set: { activeWindow : { start : "02:00", stop : "06:00" } } }, { upsert: true } ) Balancer會在服務器local time的凌晨2-6點才執行chunk的balance。 另外,在進行sharding備份時(通過mongos或者單獨備份config server和所有shard),需要停止負載均衡以免備份出來的數據出現狀態不一致問題。 sh.setBalancerState("false") 或者: sh.stopBalancer() 九、其他問題 moveChunk歸檔設置 使用3.0及以前版本的Sharded cluster可能會遇到一個問題,停止寫入數據后,數據目錄里的磁盤空間占用還會一直增加。 上述行為是由sharding.archiveMovedChunks配置項決定的,該配置項在3.0及以前的版本默認為true,即在move chunk時,源shard會將遷移的chunk數據歸檔一份在數據目錄里,當出現問題時,可用于恢復。也就是說,chunk發生遷移時,源節點上的空間并沒有釋放出來,而目標節點又占用了新的空間。 在3.2版本,該配置項默認值也被設置為false,默認不會對moveChunk的數據在源shard上歸檔。 recoverShardingState設置 使用MongoDB Sharded cluster時,還可能遇到一個問題,就是啟動 shard后,shard 不能正常服務,Primary上調用ismaster時,結果卻為 true,也無法正常執行其他命令,其狀態類似如下: PRIMARY> db.isMaster() { "hosts" : [ "host1:9003", "host2:9003", "host3:9003" ], "setName" : "mongo-9003", "setVersion" : 9, "ismaster" : false, // primary 的 ismaster 為 false??? "secondary" : true, "primary" : "host1:9003", "me" : "host1:9003", "electionId" : ObjectId("57c7e62d218e9216c70aa3cf"), "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2016-09-01T12:29:27.113Z"), "maxWireVersion" : 4, "minWireVersion" : 0, "ok" : 1 } 查看其錯誤日志,會發現shard一直無法連接上config server,上述行為是由sharding.recoverShardingState選項決定,默認為true,也就是說,shard啟動時,其會連接config server進行sharding 狀態的一些初始化,而如果config server連不上,初始化工作就一直無法完成,導致 shard 狀態不正常。 有同學在將Sharded cluster所有節點都遷移到新的主機上時遇到了上述問題,因為config server的信息發生變化了,而shard啟動時還會連接之前的config server,通過在啟動命令行加上--setParameter recoverShardingState=false來啟動shard就能恢復正常了。 ? 上述默認設計的確有些不合理,config server的異常不應該去影響shard,而且最終的問題的表象也很不明確,在3.4大版本里,MongoDB也會對這塊進行修改去掉這個參數,默認不會有recoverShardingState的邏輯,具體參考SERVER-24465。
轉載于:https://www.cnblogs.com/leohahah/p/8652572.html
總結
以上是生活随笔為你收集整理的MongoDB Sharding分片配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3-3 面向对象 本章总结
- 下一篇: Fibonacci数列时间复杂度之美妙