免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1383 | 回复: 0
打印 上一主题 下一主题

[MongoDB] MongoDB同步原理解析 [复制链接]

求职 : Linux运维
论坛徽章:
203
拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:092015小元宵徽章
日期:2015-03-06 15:58:182015年亚洲杯之约旦
日期:2015-04-05 20:08:292015年亚洲杯之澳大利亚
日期:2015-04-09 09:25:552015年亚洲杯之约旦
日期:2015-04-10 17:34:102015年亚洲杯之巴勒斯坦
日期:2015-04-10 17:35:342015年亚洲杯之日本
日期:2015-04-16 16:28:552015年亚洲杯纪念徽章
日期:2015-04-27 23:29:17操作系统版块每日发帖之星
日期:2015-06-06 22:20:00操作系统版块每日发帖之星
日期:2015-06-09 22:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-20 17:01 |只看该作者 |倒序浏览
本帖最后由 lyhabc 于 2016-07-20 17:02 编辑

MongoDB副本集数据同步](https://docs.mongodb.com/manual/core/replica-set-sync/)主要包含2个步骤

intial sync,可以理解为全量同步
replication,追同步源的oplog,可以理解为增量同步
本文是对MongoDB高可用复制集原理的补充,会详细介绍MongoDB数据同步的实现原理。

initial sync

Secondary节点当出现如下状况时,需要先进行全量同步

oplog为空
local.replset.minvalid集合里_initialSyncFlag字段设置为true
内存标记initialSyncRequested设置为true
这3个场景分别对应

新节点加入,无任何oplog,此时需先进性initial sync
initial sync开始时,会主动将_initialSyncFlag字段设置为true,正常结束后再设置为false;如果节点重启时,发现_initialSyncFlag为true,说明上次全量同步中途失败了,此时应该重新进行initial sync
当用户发送resync命令时,initialSyncRequested会设置为true,此时会重新开始一次initial sync
intial sync流程


全量同步开始,设置minvalid集合的_initialSyncFlag
获取同步源上最新oplog时间戳为t1
全量同步集合数据 (耗时)
获取同步源上最新oplog时间戳为t2
重放[t1, t2]范围内的所有oplog
获取同步源上最新oplog时间戳为t3
重放[t2, t3]范围内所有的oplog
建立集合所有索引 (耗时)
获取同步源上最新oplog时间戳为t4
重放[t3, t4]范围内所有的oplog
全量同步结束,清除minvalid集合的_initialSyncFlag
Replication

initial sync结束后,接下来Secondary就会『不断拉取主上新产生的oplog并重放『』,这个过程在Secondary同步慢问题分析也介绍过,这里从另一个角度再分析下。



producer thread,这个线程不断的从同步源上拉取oplog,并加入到一个BlockQueue的队列里保存着。
replBatcher thread,这个线程负责逐个从producer thread的队列里取出oplog,并放到自己维护的队列里。
sync线程将replBatcher thread的队列分发到默认16个replWriter线程,由replWriter thread来最终重放每条oplog。
问题来了,为什么一个简单的『拉取oplog并重放』的动作要搞得这么复杂?

性能考虑,拉取oplog是单线程进行,如果把重放也放到拉取的线程里,同步势必会很慢;所以设计上producer thread只干一件事。
为什么不将拉取的oplog直接分发给replWriter thread,而要多一个replBatcher线程来中转?

oplog重放时,要保持顺序性,而且遇到createCollection、dropCollection等DDL命令时,这些命令与其他的增删改查命令是不能并行执行的,而这些控制就是由replBatcher来完成的。
注意事项

initial sync单线程复制数据,效率比较低,生产环境应该尽量避免initial sync出现,需合理配置oplog,按默认『5%的可用磁盘空间』来配置oplog在绝大部分场景下都能满足需求,特殊的case(case1, case2)可根据实际情况设置更大的oplog。
新加入节点时,可以通过物理复制的方式来避免initial sync,将Primary上的dbpath拷贝到新的节点,直接启动,这样效率更高。
当Secondary上需要的oplog在同步源上已经滚掉时,Secondary的同步将无法正常进行,会进入RECOVERING的状态,需向Secondary主动发送resyc命令重新同步。3.2版本目前有个bug,可能导致resync不能正常工作,必须强制(kill -9)重启节点,详情参考SERVER-24773。
生产环境,最好通过db.printSlaveReplicationInfo()来监控主备同步滞后的情况,当Secondary落后太多时,要及时调查清楚原因。
当Secondary同步滞后是因为主上并发写入太高导致,(db.serverStatus().metrics.repl.buffer.sizeBytes持续接近db.serverStatus().metrics.repl.buffer.maxSizeBytes),可通过调整Secondary上replWriter并发线程数来提升。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP