用mongoshake实现mongo分片集群到单实例和分片集群的数据同步

一 实验环境

用mongoshake实现mongo分片集群到单实例和分片集群的数据同步

 这里演示只同步源端ccc库下的t1,t2表,ddd库下的所有表到两个目标端。

二 实验步骤

2.1 创建专用账号

2.1.1 在源端创建账号

2.1.1.1 登录其中一个mongos节点创建用户

#这里创建一个mongoshake用户,密码是123456

use admin;

db.createUser({user:"mongoshake",pwd:"123456",roles:[{role:"readWrite",db:"admin"}]});

db.grantRolesToUser("mongoshake",[{role:"read",db:"local"}])

db.grantRolesToUser("mongoshake",[{role:"readWrite",db:"mongoshake"}]);

2.1.1.2 在每个分片主节点上创建用户

use admin;

db.createUser({user:"mongoshake",pwd:"123456",roles:[{role:"readWrite",db:"admin"}]});

db.grantRolesToUser("mongoshake",[{role:"read",db:"local"}])

db.grantRolesToUser("mongoshake",[{role:"clusterMonitor",db:"admin"}])

2.1.2 在目标端创建账号

2.1.2.1 登录其中一个mongos节点创建用户

#登录mongos节点,创建一个对所有库都具有读写权限的账号

use admin;

db.createUser({user:"mongoshake",pwd:"123456",roles:[{role:"readWriteAnyDatabase",db:"admin"}]});

2.2 关闭分片集群的balancer

对于sharding的同步,需要关掉balancer进行同步,否则会有时序不一致的问题。

暂不支持move chunk的同时进行同步。

#登录其中一台mongos服务器执行

mongos> sh.getBalancerState()

true

mongos> sh.stopBalancer()

{

"ok" : 1,

"operationTime" : Timestamp(1640785850, 4),

"$clusterTime" : {

"clusterTime" : Timestamp(1640785850, 4),

"signature" : {

"hash" : BinData(0,"1YhPvOALc/9ggQN+E3+GfTDjcKs="),

"keyId" : NumberLong("7046829662332256286")

}

}

}

mongos> sh.getBalancerState()

false

2.3 安装mongoshake

#在所有目标端都安装下mongoshake(若目标端是mongo分片集群,则只在分片集群其中一台服务器上安装即可)

Mongo shake下载地址:

Releases · alibaba/MongoShake · GitHub

cd /opt

tar -xvf mongo-shake-v2.4.16.tar.gz

mv mongo-shake-v2.4.16 mongoshake

cd mongoshake

2.4 配置mongoshake

2.4.1 目标端为单实例的情形

#这里以往目标端192.168.144.252同步为例

vi collector.conf

# 配置源端MongoDB连接串信息,逗号分隔同一个副本集内的节点,分号分隔分片sharding实例

mongo_urls = mongodb://mongoshake:123456@192.168.144.249:27021,192.168.144.250:27021,192.168.144.251:27021;mongodb://mongoshake:123456@192.168.144.249:27022,192.168.144.250:27022,192.168.144.251:27022;mongodb://mongoshake:123456@192.168.144.249:27023,192.168.144.250:27023,192.168.144.251:27023

# 如果源端是分片集群,mongo_cs_url这里需要指定config服务器的地址

mongo_cs_url = mongodb://mongoshake:123456@192.168.144.249:27020,192.168.144.250:27020,192.168.144.251:27020

# 配置mongos的地址,多个mongos地址以逗号分割

mongo_s_url = mongodb://mongoshake:123456@192.168.144.249:27017,192.168.144.250:27017,192.168.144.251:27017

# 配置同步模式为全量+增量模式

sync_mode = all

# 这里配置只同步ccc.t1,ccc.t2,ddd库下的所有表,请结合自己业务情况进行设置,若想同步所有库的所有表,则不需要设置此选项,按默认即可。

filter.namespace.white = ccc.t1;ccc.t2;ddd

#配置目标端地址

tunnel.address = mongodb://mongoshake:123456@192.168.144.252:27017

#设置只同步某些对象,分号分割不同namespace,每个namespace可以是db,也可以是db.collection。

checkpoint.storage.collection = ckpt_default_1

2.4.2 目标端为分片集群的情形

mongo_urls,mongo_cs_url,mongo_s_url,sync_mode,filter.namespace.white等配置同2.4.1。但是tennel.address及checkpoint.storage.collection配置的时候需要注意:

#tennel.address设置为目标端的mongos地址

tunnel.address = mongodb://mongoshake:123456@192.168.144.231:27017,192.168.144.232:27017,192.168.144.233:27017

/*

注意:这里是用逗号分隔的,不是分号,否则会报错:

[2021/12/30 22:33:10 CST] [CRIT] Replayer-1, executor-1, oplog for namespace[ddd.y3] op[i] failed. error type[*mgo.BulkError] error[index[0], msg[command insert requires authentication], dup[false]], logs number[1], firstLog: {"ts":7047498676503052294,"h":8608176140228710902,"v":2,"op":"i","ns":"ddd.y3","o":[{"Name":"_id","Value":"61cdbeb57912ca48bcaaa346"},{"Name":"name","Value":444}],"o2":null}

*/

#注意:不同mongoshake里的checkpoint.storage.collection值应该是唯一的,不能和其他的重复,示例:

checkpoint.storage.collection = ckpt_default_2

2.5 启动mongoshake

sh start.sh collector.conf

#检查是否能看到collector进程

ps -ef |grep collector | grep -v 'grep'

root     27759     1  0 18:52 ?        00:00:00 ./hypervisor --daemon --exec=./collector.linux -conf=collector.conf 1>> collector.linux.output 2>&1

root     27760 27759  0 18:52 ?        00:00:04 ./collector.linux -conf=collector.conf 1>> collector.linux.output 2>&1

/*

对应的停止命令是sh stop.sh mongoshake.pid。

日志文件路径:mongoshake/logs

有时启动mongoshake没起来,日志里也没报错,可用如下方式启动,能在启动页面就能看到有日志输出:

./collector.linux -conf=collector.conf -verbose

*/

2.6 验证数据同步

登录源端mongos,插入一条测试数据:

mongos> use ddd;

switched to db ddd

mongos> db.t1.insert({"id":1,name:"baidd"})

WriteResult({ "nInserted" : 1 })

#在目标端查看数据是否能收到:

> use ddd;

switched to db ddd

> db.t1.find();

{ "_id" : ObjectId("61cb6590a2d018cc73dee5d3"), "id" : 1, "name" : "baidd" }

发现数据过来了。

注意:

本篇文章没有开启ddl同步,若想开启ddl同步,则需要设置filter.ddl_enable = true。

若要设置该参数,还需要设置incr_sync.mongo_fetch_method = change_stream,否则会报错。但是实验的该mongoshake版本只支持部分ddl(库表的建/删,重命名),由于MongoDB本身的限制,对于建/删索引,convertToCapped,applyOps等都不支持。因此,本篇文章并未开启ddl同步。

本篇文章参考了:

https://github.com/alibaba/MongoShake/wiki/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%BD%BF%E7%94%A8%EF%BC%8C%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8C%E9%85%8D%E7%BD%AE%EF%BC%9F

MongoShake最佳实践-阿里云开发者社区

上一篇:mongo集群测试


下一篇:IDEA+Gradle+Spring Data mongo 配置 querydsl