摘要:正常同步和副本集,在正常工作的情况下,是以一种不断的异步的方式进行同步。是一个特殊的固定大小的,固定大小意味着,新的操作记录的写入会导致最老的操作记录的删除,以保证的大小。而且已经降级为,将无法接受请求,以及不能变成。
Devops一般很少时间会花在数据库的部署上,只有到了不得不去考虑的情况下,才会去考虑如何调整数据库,以适应业务的发展。mongodb本身就很适合Devops,大部分情况下,部署基本按照说明操作一下即可。但实际操作起来,其实还有会有一些坑,比如Resync。
正常同步和oplogmongo副本集,在正常工作的情况下,是以一种不断的、异步的方式进行同步。每个副本都会不断的记录自己进行的操作进入到oplog表里;Secondary副本就会不断的从Primary副本那里同步最新的操作,从而完成整个副本集的同步。当然Secondary的副本也可以选择从其他的Secondary副本同步,因为每个副本都会记录oplog。详细的描述可以参考官方文档Replica Set Data Synchronization。
Oplog是一个特殊的固定大小的collection,固定大小意味着,新的操作记录的写入会导致最老的操作记录的删除,以保证oplog的大小。这个值如果不去设置,mongo会自动根据硬盘大小的5%来设定。大部分情况下没有什么问题,但有一个非常重要的设(da)定(keng):
oplog一旦大小固定,那么只能通过重启+配置来进行修改
为什么这会是一个坑,后面会继续讨论。
同步延迟lag和optime副本集之间一般通过网络连接,副本集之间的性能也有可能有差异(当然最好不要有),所以同步操作有可能出现毫秒级别的延迟,甚至到1s以上,这个可以通过在任意一个副本集上执行
rs.status()
来查看所有副本集的同步状态。这个打印出的各个副本的optime,就是这个副本最后一条操作执行的时间,Secondary和Primary之间optime的时间差,其实就是同步延迟。
同步延迟一般情况下,顶多也就一两秒,但是一些异常情况,例如宕机、长时间过载overload,可能会导致这个时间越来越长。这里,我们的oplog的巨大作用就显现出来了!
Secondary和Primary之间的同步差,最大不能超过Primary的oplog能存储的条数
注意!因为Secondary是从Primary同步oplog,所以,这里只与Primary的oplog大小有关,与Secondary自身记录的oplog无关!当然,如果Secondary是从其他的Secondary同步数据,那么至于同步目标的oplog有关。
为了帮助用户直观的理解oplog里面存储了多少条操作,mongo还额外提供了两个数据:
tFirst 第一条oplog的时间
tLast 最后一条oplog的时间
这两个数据,可以通过在primary上执行:
db.getReplicationInfo()
获得。tLast - tFirst就是mongo同步机制所允许你进行停机同步数据的最大时间,当然这个时间不是固定的,如果当前的负载很低,相当于相同的oplog表可以存更长时间内的操作数据,就会给你留更多的停机操作时间。
上图中,Secondary落后于Primary,也就是说,同步延迟有10分钟(两个optime相减),但此时,Primary上存有最近20分钟的oplog,那么Secondary通过获取这些oplog,仍然能够在短时间内赶上Primary的进度。
但是,一旦optime的差距超出了Primary的tFirst,情况就不妙了,如下图:
此时,自动的同步已经无法完成同步了(stale),必须执行手动操作Resync。而且Secondary已经降级为Recovering,将无法接受请求,以及不能变成master。
Resync机制Resync机制官网有详细的介绍,基本思路就是把数据拷贝过来,再进行上面的oplog的同步。例如:
使用磁盘快照,把快照的数据库文件直接覆盖到Secondary上,重启Secondary
使用Initial Sync,把Secondary的数据清空,让mongo自动从0开始,重新同步所有数据
磁盘快照看起来很美好,但是是mongo的数据存储是分配后就不返回的,也就是说实际占用的磁盘空间要比真实数据的大小要大,使用操作系统的scp也好rsync也好,这些无用的空间也会被复制,耽误复制的时间。除此之外,建立快照本身也需要耗时,反正在阿里云上建快照并不快,200G的数据大约要1小时多。
而Initial Sync是mongo之间拷贝表数据,拷贝完了就地重建索引,所以相当于只传输了真实的表数据,连索引数据都不用传输,从整体的复制时间来看更加节省,但是会对拷贝对象Primary有一些性能影响,但毕竟只是读,而且不需要Primary停机。
Resync的大坑无论使用上面的哪种Resync机制,思路都是一致的,通过某种快速的方式同步更多的数据,然后剩下的使用oplog弥补在执行操作时的新操作。看起来很美好,而实际的执行过程中,如果操作的时间,要大于oplog所记录的时间,怎么办?将永远无法不停机Resync成功!
这里Initial Sync为什么也不能成功呢?其实在Initial Sync的日志中,就可以看出来,在STATUP2的状态,就是一张表一张表的拷数据,也就是说,就算拷贝过程中的数据已经同步过去了,当拷贝下一张表时,上一张表的数据其实已经过期了。而当数据量很大的情况下(其实不需要太大,几百G),整个拷贝过程也要持续数小时,此时如果oplog的记录时间低于STARTUP2所需要花费的时间,恭喜你,你中奖了。
当然,如果你能有一台正常同步数据的Secondary,新的机器指向这台也是可以的,但是你的架构是一台Arbiter一台Primary一台Secondary的话……就没办法了,只能指望Primary了。别问我为什么知道,我就是知道。(╯‵□′)╯︵┴─┴
遇到这种情况怎么办?
半夜Primary停机,同步数据。这对于DBA也都不奇怪,只是在用了mongo集群后没享受到mongo的便利。当然,到了半夜负载下降,相当于oplog允许的操作时间变长了,也许不用停机。
如果有很多冗余数据、日志数据什么的,可以删除,从而降低Initial Sync花费的时间,那也是很值得尝试的!
坑的真正原因上面的坑,其实主要是在于oplog的值相对于数据量过小的时候会出现。一般默认情况下,oplog取磁盘大小的5%似乎没太大问题。坑在哪呢?
磁盘扩容
高负载
一开始我就提到,oplog的存储大小一旦确定是不会改的,也就是说,一旦随着业务的发展,进行了磁盘扩容,或者移动到了一块更大的硬盘上,oplog的大小不会随之改变!
一旦两件巧合的事情遇到了一起:磁盘曾经扩容且没有额外考虑oplog;需要新增副本或者副本stale了;此时正常的机器只有一台Primary;就会变成一件解决起来不那么轻松的事情了。
而高负载也是潜在的另外一个可能,由于负载过高,虽然oplog存储很大,但是实际上oplog所支持的停机操作时间变少了,此时也会遇到相同的情况。
防坑指南总结一下,在用mongo副本集群的时候,随着数据的增长、磁盘的扩容,一方面在考虑sharding的同时,一定要注意当前的oplog存储是否够用,提前为下一次部署策略更换准备好,给下一次的操作留够时间。特别是Devops,平时没时间管的,一定要未雨绸缪呀。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/18813.html
摘要:申明本文由笔者首发于深入浅出复制中文社区深入浅出复制由于自己开了,所以将之前比较好的文章挪过来便于大家浏览。新增由于网络问题导致失败重试机制。 申明 本文由笔者首发于InfoQ:《深入浅出MongoDB复制》MongoDB中文社区:《深入浅出MongoDB复制》 由于自己开了blog,所以将之前比较好的文章挪过来便于大家浏览。 综述 笔者最近在生产环境中遇到许多复制相关问题,查阅网上资...
摘要:先睹为快振奋人心的时刻终于到来了,在经过一个上市的日子后,终于发布了。实战在线开启认证模式解读我是上海小胖,专注等开源数据库的,拥抱开源,接受收费。上海小胖原创地址欢迎各位大神前来评论。每周五,敬请期待,上海小胖独更。 MongoDB 3.6 先睹为快 Part 1 振奋人心的时刻终于到来了,在经过一个MongoDB 上市的日子后,MongoDB 终于发布了MongoDB 3.6 RC...
摘要:先睹为快振奋人心的时刻终于到来了,在经过一个上市的日子后,终于发布了。实战在线开启认证模式解读我是上海小胖,专注等开源数据库的,拥抱开源,接受收费。上海小胖原创地址欢迎各位大神前来评论。每周五,敬请期待,上海小胖独更。 MongoDB 3.6 先睹为快 Part 1 振奋人心的时刻终于到来了,在经过一个MongoDB 上市的日子后,MongoDB 终于发布了MongoDB 3.6 RC...
阅读 1143·2021-09-10 10:51
阅读 874·2019-08-30 15:53
阅读 2705·2019-08-30 12:50
阅读 959·2019-08-30 11:07
阅读 1975·2019-08-30 10:50
阅读 3563·2019-08-29 18:47
阅读 1290·2019-08-29 18:44
阅读 1579·2019-08-29 17:01