文档章节

Devops必须留意的Mongo副本集Resync的坑

LUIS1983
 LUIS1983
发布于 2016/04/21 14:31
字数 2072
阅读 23
收藏 0

Devops一般很少时间会花在数据库的部署上,只有到了不得不去考虑的情况下,才会去考虑如何调整数据库,以适应业务的发展。mongodb本身 就很适合Devops,大部分情况下,部署基本按照说明操作一下即可。但实际操作起来,其实还有会有一些坑,比如Resync。

正常同步和oplog

mongo副本集,在正常工作的情况下,是以一种不断的、异步的方式进行同步。每个副本都会不断的记录自己进行的操作进入到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还额外提供了两个数据:

  1. tFirst 第一条oplog的时间

  2. 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的同步。例如:

  1. 使用磁盘快照,把快照的数据库文件直接覆盖到Secondary上,重启Secondary

  2. 使用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了。别问我为什么知道,我就是知道。(╯‵□′)╯︵┴─┴

遇到这种情况怎么办?

  1. 半夜Primary停机,同步数据。这对于DBA也都不奇怪,只是在用了mongo集群后没享受到mongo的便利。当然,到了半夜负载下降,相当于oplog允许的操作时间变长了,也许不用停机。

  2. 如果有很多冗余数据、日志数据什么的,可以删除,从而降低Initial Sync花费的时间,那也是很值得尝试的!

坑的真正原因

上面的坑,其实主要是在于oplog的值相对于数据量过小的时候会出现。一般默认情况下,oplog取磁盘大小的5%似乎没太大问题。坑在哪呢?

  1. 磁盘扩容

  2. 高负载

一开始我就提到,oplog的存储大小一旦确定是不会改的,也就是说,一旦随着业务的发展,进行了磁盘扩容,或者移动到了一块更大的硬盘上,oplog的大小不会随之改变!

一旦两件巧合的事情遇到了一起:磁盘曾经扩容且没有额外考虑oplog;需要新增副本或者副本stale了;此时正常的机器只有一台Primary;就会变成一件解决起来不那么轻松的事情了。

而高负载也是潜在的另外一个可能,由于负载过高,虽然oplog存储很大,但是实际上oplog所支持的停机操作时间变少了,此时也会遇到相同的情况。

防坑指南

总结一下,在用mongo副本集群的时候,随着数据的增长、磁盘的扩容,一方面在考虑sharding的同时,一定要注意当前的oplog存储是否够用,提前为下一次部署策略更换准备好,给下一次的操作留够时间。特别是Devops,平时没时间管的,一定要未雨绸缪呀。


本文转载自:

LUIS1983
粉丝 4
博文 69
码字总数 69782
作品 0
深圳
私信 提问
使用Docker和Kubernetes将MongoDB作为微服务运行

原文:Running MongoDB as a Microservice with Docker and Kubernetes 作者:Andrew Morgan 译者:徐雷 MongoDB是NoSQL排名第一的数据库,Docker是最流行的容器引擎,Kubernetes是谷歌开源的...

徐雷frank
03/16
0
0
MongoDB优化与一些需要注意的细节

这里总结下这段时间使用mongo的心得,列出了几个需要注意的地方。 1. 系统参数及mongo参数设置 mongo参数主要是storageEngine和directoryperdb,这两个参数一开始不选定后续就无法再更改。 ...

踏雪无痕SS
2017/12/09
0
0
记录一次docker集群中搭建mongodb副本集

1.创建三个装有mongo的docker容器,这里使用docker-compose,配置如下 其中mongo.conf 为yaml格式的mongodb配置文件,内容如下 执行docker-compose up -d mongo mongo2 mongo3 创建三个mongo...

roy711093
2018/10/24
0
0
搭建高可用的MongoDB集群副本集

什么是副本集呢?打魔兽世界总说打副本,其实这两个概念差不多一个意思。游戏里的副本是指玩家集中在高峰时间去一个场景打怪,会出现玩家暴多怪物少的情况,游戏开发商为了保证玩家的体验度,...

yeyu8011
2014/07/01
0
0
MongoDB Upgrade a Replica Set to 3.4

MongoDB 副本集升级 前言 Part1:写在最前 本文讲解MongoDB副本集的升级方法,以及注意事项。本文的环境为MongoDB3.2升级MongoDB3.4,低版本升级3.4的话需要优先升级到3.2版本才可以。如果发现...

dbapower
2018/07/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失

在Spring Cloud中我们用Hystrix来实现断路器,Zuul中默认是用信号量(Hystrix默认是线程)来进行隔离的,我们可以通过配置使用线程方式隔离。 在使用线程隔离的时候,有个问题是必须要解决的...

xiaomin0322
36分钟前
2
0
使用 Jenkins + Ansible 实现 Spring Boot 自动化部署101

本文首发于:Jenkins 中文社区 本文要点: 设计一条 Spring Boot 最基本的流水线:包括构建、制品上传、部署。 使用 Docker 容器运行构建逻辑。 自动化整个实验环境:包括 Jenkins 的配置,J...

Jenkins中文社区
41分钟前
2
0
springcloud配置中心和消息总线,学习,记录其中的问题

改造配置中心的客户端,接入消息总线 1.增加pom文件的引用 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20......

夜中孤影
53分钟前
3
0
gzip压缩

tar -zcvf gz包路径 被压缩的路径 tar -zcvf /home/xxx/test.tar.gz hello gz包的路径可以是 完整的也可以相对 , 被压缩的路径 不要全路径 不然压缩包里也会有全路径...

shzwork
今天
3
0
rancher-1

部署rancher 官方快速部署 https://www.cnrancher.com/quick-start/ 部署命令 mkdir /data/rancher -p# 建立存放rancher数据的目录sudo docker run -d --restart=unless-stopped -v /dat......

以谁为师
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部