需求

我们的团队需要将我们的中国 MongoDB 数据库的数据同步到日本的数据库中,因为国内的服务会产生数据,而日本那边的业务则是用这些数据做分析。有些情况下可能还需要将日本那边修改的数据再同步回国内数据库。

调研了市面上所有 MongoDB 数据库的同步工具,目前就只有 MongoShake 符合我们的要求。

简介

MongoShake 是阿里巴巴基于 Go 实现的一个 MongoDB 数据同步的开源项目,基于mongodb oplog的集群复制工具,可以满足迁移和同步的需求,进一步实现灾备和多活功能。已经在 MongoDB 云版数据库中得到了广泛应用,但是很多特性只有阿里云的 MongoDB 数据库才能使用,而自己采用开源版本搭建的数据库则无法支持,这是因为阿里云对 MongoDB 的核心做了修改。

MongoShake 支持多种方式实现数据的同步,其中有 RPC、TCP、File、Kafka、自定义的 API 以及 Direct。我们主要采用的是 Direct 这种方式同步,获取源端的 Oplog 然后直接写入目标数据库的对应 NameSpace 中。

MongoShake 支持的同步模式有:全量加增量、全量和增量,可以按需修改配置文件来实现不同的同步模式(模式选择上有些坑后面会讲到)。

同时支持黑白名单的设置,用于排除某些不需要同步的数据库或集合,或者仅同步指定的数据库或集合。

安装

访问MongoShake的 Release 页面下载编译后的可执行程序。

解压后会得到如下文件:

tar -zxvf mongo-shake-v2.6.5.tar.gz

x mongo-shake-v2.6.5/
x mongo-shake-v2.6.5/receiver.linux
x mongo-shake-v2.6.5/mongoshake-stat
x mongo-shake-v2.6.5/receiver.darwin
x mongo-shake-v2.6.5/collector.linux
x mongo-shake-v2.6.5/comparison.py
x mongo-shake-v2.6.5/receiver.conf
x mongo-shake-v2.6.5/stop.sh
x mongo-shake-v2.6.5/collector.windows
x mongo-shake-v2.6.5/collector.conf
x mongo-shake-v2.6.5/receiver.windows
x mongo-shake-v2.6.5/collector.darwin
x mongo-shake-v2.6.5/start.sh
x mongo-shake-v2.6.5/hypervisor

配置

编辑 collector.conf 文件,主要修改如下配置项:

sync_mode

用于配置同步方式,前面也提到了三种同步模式,如果目标库时新库,第一次需要做全量同步的,可以选择 all 或者 full

二者的区别是,all 会先进行全量同步,完成后自动切换为增量同步,这里有个坑,就是配置文件里一直都是 all,但是如果下次应为某种原因导致 MongoShake 进程退出了,你再次手动重启时,切记要将同步模式修改为增量模式,也就是 incr。

如果全量同步时选择的是 full ,而不是 all 模式,那么在第一次全量同步完成后,进程将会自动退出。在启动进程前,切记将同步模式修改为增量模式,也就是 incr。

否则再次启动,将会删除目标数据库的数据,重新进行全量同步。

mongo_urls

源数据库的连接地址,如:

mongodb://username:[email protected]:20040,127.0.0.1:20041。

tunnel

同步数据的方式,我们这里用最简单的直接同步到目标数据库——direct。

tunnel.address

这里配置目标数据库的地址,如:

mongodb://username:[email protected]:20040,127.0.0.1:20041。

incr_sync.oplog.gids

如果是双向同步,且两端都是阿里云的 MongoDB 服务,那么可以向阿里云申请开启 GID 防止环形复制。

开启后在阿里云 MongoDB 的 oploag 中会看到用于标记来源的 gid。

Oplog

checkpoint.storage.url

配置用于保存同步位置信息的数据库连接,如果没有设置,则默认在源端数据库中创建一个数据库和集合。

checkpoint.storage.db

配置存放 checkpoint 数据的数据库名称,默认为 mongoshake。

checkpoint.storage.collection

配置存放 checkpoint 数据的集合名词,默认为 ckpt_default。可以通过查看这个集合中的数据,知道当前 Oplog 同步到哪个时间点了,避免造成 Oplog 的大量堆积,或被覆盖,造成数据无法同步会丢失!

checkpoint.start_position

这个配置是用于设置读取源数据库 Oplog 时间点的,如果配置了一个时间点不是 1970-01-01T00:00:00Z,且在源端数据库的 Oplog 中无法找到对应的记录,那么同步服务将会启动失败!这个参数非常重要,尤其是在同步服务发送故障而停止后,需要再次重启的时候。

举个例子:

我司的数据库最近因访问量的增长,数据库的磁盘空间捉襟见肘。于是我们考虑删除一部分旧的访问数据(这也是一个坑),如果是删除某个时间段之前的数据,这种方式只能一条条执行,如果数据量大的话,将会产生大量的 Oplog。

我们的一个节点就是因为这种原因导致,短时间内产生大量 Oplog,而 Oplog 的空间是磁盘总大小的 %5,所以就导致了 Oplog 被覆盖,而当同步服务读取 Oplog 时找不到,就出现了错误,服务无法正常运行。

还有一点就是我们尝试重启同步服务时,没有修改配置文件中的 sync_modeincr。最终导致生成环境的目标数据库,被删库。

好在我们的数据库有快照,且时间间隔不算太久。

总结

如果 MongoShake 因为某种原因而停止了,再次启动前,切记检查一下同步模式,避免目标数据库被删库。然后如果启动失败,可以访问阿里云的数据库管理后台,查看最早一条 oploag 的时间,也就是上面截图中的 ts 字段,并将该时间戳专为 UTC 时区的时间,修改 checkpoint.start_position 配置项的值为哪个时间点。

I hope this is helpful, Happy hacking…