本篇的目的就是要在本机端大量写入资量,让次节点的更新开始跟不上主节点,藉由这样教你如何观察这个现象以及处里。
请直接参考这篇之前文章,在 local 启动一组 MongoDB replica set,并直接连上 primary。
准备了这个 script,大量写入资料进资料库中。
mongo --host localhost --port 27668 < test-data-script.js
use ith2021;
var TestDataCreator = {
template: function () {
return {
"FieldA" : NumberDecimal("10"),
"FieldB" : NumberDecimal("10"),
"FieldC" : NumberDecimal("10"),
"FieldD" : NumberDecimal("10")
};
},
insertTestData: function () {
let that = this;
let batchSize = 10000;
let totalBatch = 100000;
for (let otrItr = 0 ; otrItr < totalBatch ; otrItr++) {
let models = [];
for (let itr = 0 ; itr < batchSize ; itr++) {
let model = {};
model.insertOne = {};
model.insertOne.document = that.template();
models.push(model);
}
db.getCollection('test-data').bulkWrite(models, {ordered: false});
print(new Date() + " inserted batch ***");
}
print(new Date() + "insert " + totalBatch + " batches all done ***");
},
start: function () {
this.insertTestData();
}
};
TestDataCreator.start();
随着资料量的增长,可以看到 oplog 偶有点小小延误
ith2021-rs [direct: primary] ith2021> rs.printSecondaryReplicationInfo()
source: mongo_node1:27666
{
syncedTo: 'Sun Sep 12 2021 22:07:46 GMT+0800 (台北标准时间)',
replLag: '-2 secs (0 hrs) behind the primary '
}
---
source: mongo_node2:27667
{
syncedTo: 'Sun Sep 12 2021 22:07:46 GMT+0800 (台北标准时间)',
replLag: '-2 secs (0 hrs) behind the primary '
}
好像很可以,资料落差还在 5 秒内,这时只要去更改大量资料,就会产生大量差异。`
db.getCollection('test-data-2021-06-28').updateMany({"FieldA":10}, {$set:{"FieldA":"10-u"}})
陆续下了几个指令查看次节点资讯,我们看看发生什麽事情
test-RS:PRIMARY> db.printSlaveReplicationInfo()
source: test-rs-mongo2:27018
syncedTo: Mon Jun 28 2021 00:51:18 GMT+0800 (CST)
13 secs (0 hrs) behind the primary
source: test-rs-mongo3:27019
syncedTo: Mon Jun 28 2021 00:51:17 GMT+0800 (CST)
14 secs (0 hrs) behind the primary
test-RS:PRIMARY> db.printSlaveReplicationInfo()
source: test-rs-mongo2:27018
syncedTo: Mon Jun 28 2021 00:51:46 GMT+0800 (CST)
27 secs (0.01 hrs) behind the primary
source: test-rs-mongo3:27019
syncedTo: Mon Jun 28 2021 00:51:41 GMT+0800 (CST)
32 secs (0.01 hrs) behind the primary
test-RS:PRIMARY> db.printSlaveReplicationInfo()
source: test-rs-mongo2:27018
syncedTo: Mon Jun 28 2021 00:56:11 GMT+0800 (CST)
167 secs (0.05 hrs) behind the primary
source: test-rs-mongo3:27019
syncedTo: Mon Jun 28 2021 00:56:20 GMT+0800 (CST)
158 secs (0.04 hrs) behind the primary
这时我们看看主节点的资讯
test-RS:PRIMARY> db.printReplicationInfo()
configured oplog size: 990MB
log length start to end: 305secs (0.08hrs)
oplog first event time: Mon Jun 28 2021 00:54:03 GMT+0800 (CST)
oplog last event time: Mon Jun 28 2021 00:59:08 GMT+0800 (CST)
now: Mon Jun 28 2021 00:59:15 GMT+0800 (CST)
可以看到主节点还是不断得在写入新的资料,但是次节点的同步已经来到落後一百多秒了,再下去就会让 oplog 满出来,接着触发 full resync,让次节点失效。
其实就是透过这样的方式实验,在大流量时很容易就把同步机制弄到挂掉。
这边要特别解释一下关於 step3,我无意欺骗大家,step3 的内容是我在几个月前在本机电脑跑出来的结果。
而几个月後的现在,我改用 5版的 MongoDB 却跑不出来了,用的步骤和手法是一模一样的,暂时认为 MongoDB 在 Oplog 机制改善了不少,所以整体来说应该是件好事啦XD。
在测试过程中,资料量上到一千五百万左右,还是有遇到某个节点直接崩溃的情形。
其实说穿了目前的快速解决方案就是两个,长期下来我还是认为治标不治本。MongoDB 资料同步这一块在网路上很多人都会遇到,应该说只要把产品上线,资料量大一点就马上会体会到,最常听到的莫过於两个人同时使用系统,但是查询结果不同。
一般来说使用 replica set,主要目的也是读写分离,让收资料端能够发挥最大效益,而查询面,只要不是最即时的需求,都会放到次节点去读取。
oplog 剩余的时间,代表的是 触发全同步的剩余时间,意思是你的次节点会停止服务,接着进行同步,直到全部与主节点同步为止。但这件事背後的隐忧是,就是因为资料来不及同步,才会触发,那现在次节点无法服务,又同时在进行 full resync,会跟得上吗?这有待商榷,但是可以确定的是主节点压力又更重了,这可能会导致雪崩式的中断服务,因此这问题一定都需要即时监控的。
目前来看,如果不想要自己写服务接收指令回传的资讯,大概都是要使用云端收费服务才能有图表监控功能了。
replace
是否可以改用 update
特定栏位即可(replace对主节点更新速度最快,比 update 快到约 30%,所以请衡量使用情境)TTL
很好用,但它也是对 DB 进行 Delete
,大资料量同时触发 TTL,也是一个负担。网路上看到的解决方法多半都只有这两个:
oplog size
,这个做法就是用空间换时间,争取延长尖峰期触发 full resync 的时间。replWriterThreadCount
,提高次节点存取 thread 数。预设值是 16
。这样做代价就是记忆体使用率也会拉高。(这个项目在 MongoDB Atlas 似乎没有办法设定,但是5版的速度提升後,可能也不用改了)本系列文章会同步发表於我个人的部落格 Pie Note
<<: DAY07_终於要来资产搬点啦~啊~不是~是盘点XDDD" 搬点是要搬家是吗~
>>: Day 5 - 使用JWT Token帮Laravel 8.0做Authentication
前情提要 昨天我们成功的让 App 在本机端运作,但按下 开始预测! 後却出现了错误: 这意味着虽然...
前面说过Passer如何把请求发到MQ去 今天讲Center怎麽去找MQ把请求取出来。 Cente...
接下来的五天我们会用不同的方式来解这题题目Sort an Array,一起来复习跟朝拜大师们想出来的...
老实说我决定要写影像处理这个部分的时候还蛮犹豫的,因为在javascript 做影像处理的这个领域,...
资讯工程学系(Computer Science and Information Engineerin...