分片(shard)是指在将数据进行水平切分之后,将其存储到多个不同的服务器节点上的一种扩展方式。
一个复制集能承载的容量和负载是有限的,遇到以下场景就需要考虑使用分片
MongoDB 分片集群(Sharded Cluster)是对数据进行水平扩展的一种方式。MongoDB 使用 分片集群来支持大数据集和高吞吐量的业务场景。
通过分片功能,可以将一个非常大的集合分散存储到不同的分片上。
MongoDB允许通过为分片添加标签(tag)的方式来控制数据分发。
一个标签可以关联到多个分片区间(TagRange)。均衡器会优先考虑chunk是否正处于某个分片区间上(被完全包含),如果是则会将chunk迁移到分片区间所关联的分片,否则按一般情况处理。
手动均衡
通过splitAt、moveChunk命令进行手动切分、迁移。
自动均衡
MongoDB的数据均衡器运行于Primary Config Server(配置服务器的主节点)上,而该节点也同时会控制chunk数据的搬迁流程。
自动均衡流程
mongodb6.0迁移条件
如果碎片之间的数据差异(对于该集合)小于该集合配置范围大小的三倍,则认为该集合是平衡的。对于128MB的默认范围大小,对于给定的集合,两个分片必须具有至少384MB的数据大小差异,才能进行迁移。
#在每天的凌晨2点到4点运行数据均衡操作
use config
sh.setBalancerState(true)
db.settings.update(
{_id:"balancer"},
{$set:{activeWindow:{start:"02:00",stop:"04:00"}}},
{upsert:true}
)
#对分片集合中执行count命令可能会产生不准确的结果
使用db.collection.countDocuments({})方法代替
#查看均衡器是否开启
sh.getBalancerState()
#查看均衡器是否正在运行
sh.isBalancerRunning()
#查看当前均衡的窗口设定
sh.getBalancerWindow()
MongoDB 集群两地三中心部署的考量点
• 节点数量建议要5个,2+2+1模式
• 主数据中心的两个节点要设置高一点的优先级,减少跨中心换主节点
• 同城双中心之间的网络要保证低延迟和频宽,满足 writeConcern: Majority 的双中心写需求
• 使用 Retryable Writes and Retryable Reads 来保证零下线时间
• 用户需要自行处理好业务层的双中心切换
两地三中心复制集搭建
#配置域名解析
echo "192.168.139.135 mongo1 mongo01.com mongo02.com" >> /etc/hosts
echo "192.168.139.136 mongo2 mongo03.com mongo04.com" >> /etc/hosts
echo "192.168.139.137 mongo3 mongo05.com " >> /etc/hosts
#启动5个 MongoDB 实例
mkdir -p /data/member1/db /data/member1/log /data/member2/db /data/member2/log
mongod --dbpath /data/member1/db --replSet demo --bind_ip 0.0.0.0 --port 10001 --fork --logpath /data/member1/log/member1.log
mongod --dbpath /data/member2/db --replSet demo --bind_ip 0.0.0.0 --port 10002 --fork --logpath /data/member2/log/member2.log
mkdir -p /data/member3/db /data/member3/log /data/member4/db /data/member4/log
mongod --dbpath /data/member3/db --replSet demo --bind_ip 0.0.0.0 --port 10001 --fork --logpath /data/member3/log/member3.log
mongod --dbpath /data/member4/db --replSet demo --bind_ip 0.0.0.0 --port 10002 --fork --logpath /data/member4/log/member4.log
mkdir -p /data/member5/db /data/member5/log
mongod --dbpath /data/member5/db --replSet demo --bind_ip 0.0.0.0 --port 10001 --fork --logpath /data/member5/log/member5.log
mongo mongo01.com:10001
# 初始化复制集
rs.initiate({
"_id" : "demo",
"version" : 1,
"members" : [
{ "_id" : 0, "host" : "mongo01.com:10001" },
{ "_id" : 1, "host" : "mongo02.com:10002" },
{ "_id" : 2, "host" : "mongo03.com:10001" },
{ "_id" : 3, "host" : "mongo04.com:10002" },
{ "_id" : 4, "host" : "mongo05.com:10001" }
]
})
#查看复制集状态
rs.status()
#配置选举优先级
mongosh mongo01.com:10001
conf = rs.conf()
conf.members[0].priority = 5
conf.members[1].priority = 10
rs.reconfig(conf)
#使用Retryable Writes以后,即使出现数据中心故障,对前端业务没有任何中断
mongosh --retryWrites mongodb://mongo01.com:10001,mongo02.com:10002,mongo03.com:10001,mongo04.com:10002,mongo05.com:10001/test?replicaSet=demo ingest-script
#vim ingest-script
db.test.drop()
for(var i=1;i<1000;i++){
db.test.insert({item: i});
inserted = db.test.findOne({item: i});
if(inserted)
print(" Item "+ i +" was inserted " + new Date().getTime()/1000);
else
print("Unexpected "+ inserted)
sleep(2000);
}