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