江苏连云港网站设计公司,品牌营销型网站,wordpress 固定,哪个网站能接效果图做MongoDB的同步原理#xff0c;官方文档介绍的比较少#xff0c;网上资料也不是太多#xff0c;下面是结合官方文档、网上资料和测试时候的日志#xff0c;整理出来的一点东西。 因为MongoDB的每个分片也是副本集#xff0c;所以只需要搞副本集的同步原理即可。
一、Initi…MongoDB的同步原理官方文档介绍的比较少网上资料也不是太多下面是结合官方文档、网上资料和测试时候的日志整理出来的一点东西。 因为MongoDB的每个分片也是副本集所以只需要搞副本集的同步原理即可。
一、Initial Sync
大体来说MongoDB副本集同步主要包含两个步骤
1. Initial Sync全量同步
2. Replication即sync oplog
先通过init sync同步全量数据再通过replication不断重放Primary上的oplog同步增量数据。全量同步完成后成员从转换 STARTUP2为SECONDARY
1.1 初始化同步过程
1) 全量同步开始获取同步源上的最新时间戳t1
2) 全量同步集合数据建立索引比较耗时
3) 获取同步源上最新的时间戳t2
4) 重放t1到t2之间所有的oplog
5) 全量同步结束
简单来说就是遍历Primary上的所有DB的所有集合将数据拷贝到自身节点然后读取全量同步开始到结束时间段内的oplog并重放。
initial sync结束后Secondary会建立到Primary上local.oplog.rs的tailable cursor不断从Primary上获取新写入的oplog并应用到自身。
1.2 初始化同步场景
Secondary节点当出现如下状况时需要先进⾏全量同步
1) oplog为空
2) local.replset.minvalid集合⾥_initialSyncFlag字段设置为true用于init sync失败处理
3) 内存标记initialSyncRequested设置为true用于resync命令resync命令只用于master/slave架构副本集无法使用这3个场景分别对应(场景2和场景3没看到官网文档有写参考张友东大神博客)
1) 新节点加⼊⽆任何oplog此时需先进性initial sync
2) initial sync开始时会主动将_initialSyncFlag字段设置为true正常结束后再设置为false如果节点重启时发现_initialSyncFlag为true说明上次全量同步中途失败了此时应该重新进⾏initial sync
3)当⽤户发送resync命令时initialSyncRequested会设置为true此时会强制重新开始⼀次initial sync1.3 疑问点解释
1.3.1 全量同步数据的时候会不会源数据的oplog被覆盖了导致全量同步失败
在3.4版本及以后不会。 下面这张图说明了3.4对全量同步的改进图来自张友东博客 官方文档是
initial sync会在为每个集合复制文档时构所有集合索引。在早期版本3.4之前的MongoDB中仅_id在此阶段构建索引。
Initial sync复制数据的时候会将新增的oplog记录存到本地3.4新增。二、Replication
2.1 sync oplog的过程
全量同步结束后Secondary就开始从结束时间点建立tailable cursor不断的从同步源拉取oplog并重放应用到自身这个过程并不是由一个线程来完成的mongodb为了提升同步效率将拉取oplog以及重放oplog分到了不同的线程来执行。 具体线程和作用如下这部分暂时没有在官方文档找到来自张友东大神博客
producer thread这个线程不断的从同步源上拉取oplog并加入到一个BlockQueue的队列里保存着BlockQueue最大存储240MB的oplog数据当超过这个阈值时就必须等到oplog被replBatcher消费掉才能继续拉取。replBatcher thread这个线程负责逐个从producer thread的队列里取出oplog并放到自己维护的队列里这个队列最多允许5000个元素并且元素总大小不超过512MB当队列满了时就需要等待oplogApplication消费掉oplogApplication会取出replBatch thread当前队列的所有元素并将元素根据docId如果存储引擎不支持文档锁则根据集合名称分散到不同的replWriter线程replWriter线程将所有的oplog应用到自身等待所有oplog都应用完毕oplogApplication线程将所有的oplog顺序写入到local.oplog.rs集合。
针对上面的叙述画了一个图方便理解 producer的buffer和apply线程的统计信息都可以通过db.serverStatus().metrics.repl来查询到。
2.2 对过程疑问点的解释
2.2.1 为什么oplog的回放要弄这么多的线程
和mysql一样一个线程做一个事情拉取oplog是单线程其他线程进行回放多个回放线程加快速度。
2.2.2 为什么需要replBatcher线程来中转
oplog重放时要保持顺序性⽽且遇到create、drop等DDL命令时这些命令与其他的增删改查命令是不能并⾏执⾏的⽽这些控制就是由replBatcher来完成的。
2.2.3 如何解决secondary节点oplog重放追不上primary问题
方法一设置更大的回放线程数 * mongod命令行指定mongod --setParameter replWriterThreadCount32* 配置文件中指定
setParameter:replWriterThreadCount: 32
方法二增大oplog的大小 方法三将writeOpsToOplog步骤分散到多个replWriter线程来并发执行看官方开发者日志已经实现了这个在3.4.0-rc2版本
2.3 注意事项
initial sync单线程复制数据效率比较低生产环境应该尽量避免initial sync出现需合理配置oplog。新加⼊节点时可以通过物理复制的⽅式来避免initial sync将Primary上的dbpath拷⻉到新的节点然后直接启动。当Secondary同步滞后是因为主上并发写入太高导致db.serverStatus().metrics.repl.buffer的 sizeBytes值持续接近maxSizeBytes的时候可通过调整Secondary上replWriter并发线程数来提升。
三、日志分析
3.1 初始化同步日志
将日志级别 verbosity设置为 1然后过滤日志 cat mg36000.log |egrep clone|index|oplog b.log 最后拿出过滤后的部分日志。3.4.21新加入节点日志
因为日志太多贴太多出来也没什么意义下面贴出了对db01库的某个
集合的日志。
可以发现是先创建collection索引然后clone集合数据和索引数据这样就完成了该集合的clone。最后将配置改为下一个集合。2019-08-21T16:50:10.8800800 D STORAGE [InitialSyncInserters-db01.test20] create uri: table:db01/index-27-154229953453504826 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { num : 1 }, name : num_1, ns : db01.test2 }),
2019-08-21T16:50:10.8820800 I INDEX [InitialSyncInserters-db01.test20] build index on: db01.test2 properties: { v: 2, key: { num: 1.0 }, name: num_1, ns: db01.test2 }
2019-08-21T16:50:10.8820800 I INDEX [InitialSyncInserters-db01.test20] building index using bulk method; build may temporarily use up to 500 megabytes of RAM
2019-08-21T16:50:10.8820800 D STORAGE [InitialSyncInserters-db01.test20] create uri: table:db01/index-28-154229953453504826 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { _id : 1 }, name : _id_, ns : db01.test2 }),
2019-08-21T16:50:10.8860800 I INDEX [InitialSyncInserters-db01.test20] build index on: db01.test2 properties: { v: 2, key: { _id: 1 }, name: _id_, ns: db01.test2 }
2019-08-21T16:50:10.8860800 I INDEX [InitialSyncInserters-db01.test20] building index using bulk method; build may temporarily use up to 500 megabytes of RAM
2019-08-21T16:50:10.9010800 D INDEX [InitialSyncInserters-db01.test20] bulk commit starting for index: num_1
2019-08-21T16:50:10.9060800 D INDEX [InitialSyncInserters-db01.test20] bulk commit starting for index: _id_
2019-08-21T16:50:10.9130800 D REPL [repl writer worker 11] collection clone finished: db01.test2
2019-08-21T16:50:10.9130800 D REPL [repl writer worker 11] collection: db01.test2, stats: { ns: db01.test2, documentsToCopy: 2000, documentsCopied: 2000, indexes: 2, fetchedBatches: 1, start: new Date(1566377410875), end: new Date(1566377410913), elapsedMillis: 38 }
2019-08-21T16:50:10.9200800 D STORAGE [InitialSyncInserters-db01.collection10] create uri: table:db01/index-30-154229953453504826 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { _id : 1 }, name : _id_, ns : db01.collection1 }),
3.6.12加入新节点日志
3.6较3.4的区别是复制数据库的线程明确了是repl writer worker 进行重放看文档其实3.4已经是如此了
还有就是明确是用cursors来进行。
其他和3.4没有区别也是创建索引然后clone数据。
2019-08-22T13:59:39.4440800 D STORAGE [repl writer worker 9] create uri: table:db01/index-32-3334250984770678501 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { _id : 1 }, name : _id_, ns : db01.collection1 }),log(enabledtrue)
2019-08-22T13:59:39.4460800 I INDEX [repl writer worker 9] build index on: db01.collection1 properties: { v: 2, key: { _id: 1 }, name: _id_, ns: db01.collection1 }
2019-08-22T13:59:39.4460800 I INDEX [repl writer worker 9] building index using bulk method; build may temporarily use up to 500 megabytes of RAM
2019-08-22T13:59:39.4470800 D REPL [replication-1] Collection cloner running with 1 cursors established.
2019-08-22T13:59:39.6810800 D INDEX [repl writer worker 7] bulk commit starting for index: _id_
2019-08-22T13:59:39.7250800 D REPL [repl writer worker 7] collection clone finished: db01.collection1
2019-08-22T13:59:39.7250800 D REPL [repl writer worker 7] database: db01, stats: { dbname: db01, collections: 1, clonedCollections: 1, start: new Date(1566453579439), end: new Date(1566453579725), elapsedMillis: 286 }
2019-08-22T13:59:39.7250800 D REPL [repl writer worker 7] collection: db01.collection1, stats: { ns: db01.collection1, documentsToCopy: 50000, documentsCopied: 50000, indexes: 1, fetchedBatches: 1, start: new Date(1566453579440), end: new Date(1566453579725), elapsedMillis: 285 }
2019-08-22T13:59:39.7310800 D STORAGE [repl writer worker 8] create uri: table:test/index-34-3334250984770678501 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { _id : 1 }, name : _id_, ns : test.user1 }),log(enabledtrue)
4.0.11加入新节点日志
使用cursors和3.6基本一致
2019-08-22T15:02:13.8060800 D STORAGE [repl writer worker 15] create uri: table:db01/index-30--463691904336459055 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { num : 1 }, name : num_1, ns : db01.collection1 }),log(enabledfalse)
2019-08-22T15:02:13.8160800 I INDEX [repl writer worker 15] build index on: db01.collection1 properties: { v: 2, key: { num: 1.0 }, name: num_1, ns: db01.collection1 }
2019-08-22T15:02:13.8160800 I INDEX [repl writer worker 15] building index using bulk method; build may temporarily use up to 500 megabytes of RAM
2019-08-22T15:02:13.8160800 D STORAGE [repl writer worker 15] create uri: table:db01/index-31--463691904336459055 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { _id : 1 }, name : _id_, ns : db01.collection1 }),log(enabledfalse)
2019-08-22T15:02:13.8190800 I INDEX [repl writer worker 15] build index on: db01.collection1 properties: { v: 2, key: { _id: 1 }, name: _id_, ns: db01.collection1 }
2019-08-22T15:02:13.8190800 I INDEX [repl writer worker 15] building index using bulk method; build may temporarily use up to 500 megabytes of RAM
2019-08-22T15:02:13.8200800 D REPL [replication-0] Collection cloner running with 1 cursors established.
3.2 复制日志
2019-08-22T15:15:17.5660800 D STORAGE [repl writer worker 2] create collection db01.collection2 { uuid: UUID(8e61a14e-280c-4da7-ad8c-f6fd086d9481) }
2019-08-22T15:15:17.5670800 I STORAGE [repl writer worker 2] createCollection: db01.collection2 with provided UUID: 8e61a14e-280c-4da7-ad8c-f6fd086d9481
2019-08-22T15:15:17.5670800 D STORAGE [repl writer worker 2] stored meta data for db01.collection2 RecordId(22)
2019-08-22T15:15:17.5800800 D STORAGE [repl writer worker 2] db01.collection2: clearing plan cache - collection info cache reset
2019-08-22T15:15:17.5800800 D STORAGE [repl writer worker 2] create uri: table:db01/index-43--463691904336459055 config: typefile,internal_page_max16k,leaf_page_max16k,checksumon,prefix_compressiontrue,block_compressor,,,,key_formatu,value_formatu,app_metadata(formatVersion8,infoObj{ v : 2, key : { _id : 1 }, name : _id_, ns : db01.collection2 }),log(enabledfalse)
原文链接 本文为云栖社区原创内容未经允许不得转载。