咱们在去年开源了MongoShake,能够用于MongoDB的数据同步,知足用户多种需求,总体介绍文档参考这里。今天,我来主要介绍一下MongoShake的最佳实践,主要涵盖如下几部分:linux
MongoShake的下载路径咱们提供在了github上,点击能够下载不一样版本的mongoshake:mongo-shake-x.y.z.tar.gz
。目前MongoShake提供了配置文件启动的方式,启动的命令行:./collector.linux -conf=collector.conf
,不一样的平台请选择不一样的二进制文件,如windows下是collector.windows。git
全部的参数都列在了配置文件里面,目前配置文件较多,用户可能比较困惑,正常状况下用户默认就行,修改的参数只有少部分。
MongoShake支持MongoDB副本集和集群版的互相同步,还能够同步到kafka模式,下面列出了几种常见的同步模式。github
假设源端是三副本:10.1.1.1:1001, 10.2.2.2:2002, 10.3.3.3:3003,目的端也是三副本:10.5.5.5:5005, 10.6.6.6:6006, 10.7.7.7:7007。同步模式是全量+增量同步。
则用户须要修改如下几个参数:golang
mongo_urls = mongodb://username:password@10.1.1.1:1001,10.2.2.2:2002,10.3.3.3:3003 #源端链接串信息,逗号分隔不一样的mongod sync_mode = all # all 表示全量+增量,document表示仅全量,oplog表示仅增量 tunnel.address = mongodb://username:password@10.5.5.5:5005, 10.6.6.6:6006, 10.7.7.7:7007 #目的端链接串信息,逗号分隔不一样的mongod
假设源一样是三副本:10.1.1.1:1001, 10.2.2.2:2002, 10.3.3.3:3003,目的端是sharding,有多个mongos:20.1.1.1:2021, 20.2.2.2:2022, 20.3.3.3:3033。mongodb
mongo_urls = mongodb://username:password@10.1.1.1:1001,10.2.2.2:2002,10.3.3.3:3003 #源端链接串信息,逗号分隔不一样的mongod sync_mode = all # all 表示全量+增量,document表示仅全量,oplog表示仅增量 tunnel.address = mongodb://username:password@20.1.1.1:2021;20.2.2.2:2022;20.3.3.3:3033 #目的端链接串信息,分号分割不一样的mongos。也能够只配置部分,配置多个mongos能够作负载均衡写入。
假设源是2节点:节点1是10.1.1.1:1001, 10.1.1.2:2002, 10.1.1.3:3003;节点2是10.2.2.1:1001, 10.2.2.2:2002, 10.2.2.3:3003。目的端是sharding,有多个mongos:20.1.1.1:2021, 20.2.2.2:2022, 20.3.3.3:3033。数据库
mongo_urls = mongodb://username1:password1@10.1.1.1:1001,10.1.1.2:2002,10.1.1.3:3003;mongodb://username2:password2@10.2.2.1:1001,10.2.2.2:2002,10.2.2.3:3003 #源端链接串信息,逗号分隔同一个shard不一样的mongod,分号分隔不一样的shard。 sync_mode = all # all 表示全量+增量,document表示仅全量,oplog表示仅增量 tunnel.address = mongodb://username:password@20.1.1.1:2021;20.2.2.2:2022;20.3.3.3:3033 #目的端链接串信息,分号分割不一样的mongos。也能够只配置部分,配置多个mongos能够作负载均衡写入。 context.storage.url = mongodb://username1:password1@10.5.5.5:5555,10.5.5.6:5556 # 若是源端是sharding,此处须要配置源端sharding的cs的地址
假设源一样是三副本:10.1.1.1:1001, 10.2.2.2:2002, 10.3.3.3:3003,目的kafka是50.1.1.1:6379,topic是test。windows
mongo_urls = mongodb://username:password@10.1.1.1:1001,10.2.2.2:2002,10.3.3.3:3003 #源端链接串信息,逗号分隔不一样的mongod sync_mode = oplog # 若是目的端不是mongodb,仅支持增量同步模式 tunnel.type = kafka tunnel.address = test@50.1.1.1:6379
云上副本集的双向同步能够参考副本集的单向同步,可是须要注意的有如下几点,假设A和B之间双向同步:api
具体请查看配置文件的注释,此处只作简单解释restful
此处记载几个常见的问题:网络
A: 不会同步。若是用户必定要把admin的库同步到别的,那么能够经过命名转换功能(配置transform.namespace)把admin库同步到别的数据库,同时配置filter.pass.special.db参数:
A: 用户能够下降全量同步配置replayer的相关参数,以下降目的端压力。
A: 用户能够定位一下看看目的慢的缘由是什么,正常状况下能够提升全量配置replayer的相关参数,以提升全量同步的性能。但也有可能,问题的瓶颈是源端/网络端/通道cpu,内存等压力太高,都是有可能的。
A: checkpoint是记录增量同步的位点状况,mongoshake的启动就是根据这个位点来进行的,好比咱们已经同步到10点钟了,那么这个时候挂掉了,若是没有位点,那么只能从头开始拉,位点的意义就是在于断点续传。在mongoshake中,位点信息是以64位时间戳来标记的(ts字段,准确的说是32位时间戳+计数),若是发生挂掉重启,那么会从源库的oplog表中寻找这个位点,并今后开始日后进行同步。
到这里,用户可能会问,那么mongoshake里面位点是存储在哪里的?存储的位置就是取决于用户context的相关配置,以副本集为例,checkpoint是存储于源库的mongoshake库的ckpt_default表,其大概内容长这个样子:
rszz-4.0-2:PRIMARY> use mongoshake switched to db mongoshake rszz-4.0-2:PRIMARY> show collections ckpt_default rszz-4.0-2:PRIMARY> db.ckpt_default.find() { "_id" : ObjectId("3d75e8b872d91278c3be0cc9"), "name" : "rszz-4.0-2", "ckpt" : Timestamp(1566556865, 196096) }
其中ckpt对应的field就是checkpoint。
用户可能还会问,那么mongoshake的checkpoint是怎么存储的,何时会存储?答案是,checkpoint是按期存储的,若是有数据同步,那么checkpoint的更新会很频繁(秒级别);若是没有数据同步,好比这个时候用户源端就是没有写入,那么默认是分钟级别更新一次心跳checkpoint。假设mongoshake数据位点记录是10:00:00,可是数据已经同步到10:00:10,这个时候mongoshake挂掉了,下次会从10:00:00从新开始同步,因为DML自己具备幂等性,数据的重复回放是OK的。那么用户可能会问,DDL怎么办?参考下面问题。
A: 设置replayer.dml_only = false
能够同步DDL。DDL不能保证幂等性。在mongoshake里面,若是发现是DDL语句,会卡一个全局的barrier,让当前DDL语句同步,而后再卡一个全局barrier,等当前DDL语句同步完成,再接着并发同步接下来的oplog,barrier的卡锁伴随着checkpoint的强制刷新。可是因为DDL同步和checkpoint的刷新并非一个院子操做,若是用户刚好在同步DDL完成和checkpoint刷新之间,进程挂掉了,那么没有办法,重启之后确定会持续报错,用户须要手动运维解决,好比跳过这个DDL,或者目的端近些一个反向操做(原来DDL是建库,须要进行删除库;原来是建索引,须要进行删索引操做)。可是,这个几率很低。
A: 不会,会持续报错,用户须要关注日志的运行状况。
A: mongoshake有提供restful接口,能够监控mongoshake的内部同步状况,参考wiki: How to monitor the MongoShake,正常状况下lsn_ckpt.time会一直增加,若是这个数值不增加了,那么就表示同步出现问题了。
A: 会同步索引,显示全量同步,全量同步完毕后会同步索引,接着是增量同步。
A: 显示全量同步,全量同步完毕会写入checkpoint,而后进行增量同步,增量同步阶段会不断更新checkpoint。对于mongoshake来讲,是否进行全量同步取决于checkpoint,若是checkpoint存在且合法,那么只会进入增量同步;不然,会先进行全量同步,而后是增量。那么checkpoint怎么知道是存在的,就是context里面的参数的位置决定;那么怎么知道checkpoint是合法的?若是最老的oplog的时间位点小于checkpoint,那么就是合法的,证实增量能接上。
A: 最须要注意的就是,全量同步完毕,增量可否接上。mongoshake是根据oplog的位点来决定全量结束是否要进行增量,若是全量花了2天,可是oplog表只能存储1天,那么全量同步完毕之后mongoshake就会报错退出,这是由于增量的位点丢失了。因此若是全量很大,同步时间势必好久,那么就须要放大oplog的表的大小以维持增量oplog。
其余还须要注意的就是压力问题,如何选取适当的参数应对对于源端/目的端的压力,减小对业务的影响。用户也能够决定从一个hidden结点,护着一个独立的secondary结点进行拉取。
A: 这个我在github的wiki基本都有总结,能够先看下github的faq。若是里面没有提到的,能够提交issue进行反馈。
A: 目前script下面有个comparison.py的全量校验脚本校验数据的一致性。那么如何进行增量的校验呢?目前尚未,敬请期待。
A: 若是源端是sharding,那么目前须要关闭balancer,在v2.1非稳定版本里面,咱们支持了不关闭balancer,用户能够进行试用,可是目前这个是非稳定版本。此外源端若是是sharding,DDL的同步(replayer.dml_only = false)不能开启。
A: 请先看下wiki: https://github.com/alibaba/MongoShake/wiki/FAQ#q-how-to-connect-to-different-tunnel-except-direct。
kafka通道中的数据是有控制信息在里面的,用户很差直接剥离,能够用receiver进行对接。目前receiver对接后全部oplog都打印到控制台,用户也能够本身修改receiver代码,对接下游服务。固然,这个须要用户懂golang语言,这可能有一些学习成本在里面。后面咱们会看看如何以更好的形式对接给用户。
A: 目前全量阶段因为是扫表等操做,会对源端产生一些影响。增量阶段,正常状况影响很小,由于目前oplog找对应ts是二分模式。
A: 能够,须要启动多个mongoshake。对于不一样的mongoshake,能够修改写入不一样地方的checkpoint便可(好比表名修改一下),或者直接修改不一样的collector.id。此外,须要注意的是,同一个目录下启动多个mongoshake,若是collector.id相同,是没法启动成功的。参考:https://github.com/alibaba/MongoShake/wiki/FAQ#q-how-to-sync-data-from-one-mongodb-to-several-target-mongodb
本文为云栖社区原创内容,未经容许不得转载。