要做一个mongodb集群的迁移和恢复,真是折腾死人了。记录并顺便吐槽一下:
mongodb的tools真的是太简易、粗糙、丑陋了。
线上的源数据库是腾讯的服务,要废弃搬迁到内网,足足折腾了一个星期。
线上源数据库环境如下:
- 云数据库 TencentDB
- 4C/8GB/500GB
- 3节点
于是在线下对等建立了mongo集群,同样配置,同样3节点。
噩梦由此开始啊,注意线下集群的memory配置一定要高:
- 32GB
- 用户名和密码一定要和线上完全一致
- 如果用户名密码不一致,Document恢复完毕,Index无法建立,因为是完全恢复,会覆盖admin这个db
然后开始dump线上数据
1mongodump --uri="mongodb://root:xxxxxxxx@10.1.2.3:27017/?authSource=admin"
然后生成一个24G大小得dump文件夹,压缩后2.4G,传输到线下库上准备恢复
1# 大量恢复必须扩大文件句柄,否则过不去
2ulimit -n 655360
3
4# 一定要记录下来开始的时间戳,后面有用
5date
6Sun May 11 06:34:02 PM CST 2025
7
8# 开始恢复,漫长的一天开始了
9# 必须放到screen中执行,否则网络不好,断了也会很悲剧
10
11screen -L
12
13./mongorestore \
14 --drop \
15 --host=192.168.111.222 \
16 --port=27017 \
17 --username=root \
18 --authenticationDatabase=admin \
19 --nsExclude=admin \
20 /root/dump
21
22 ctrl+a+d
其实刚开始线下三节点得配置是8G,然后恢复用了一晚,报错,直接把shard3给打崩了,虽然三节点都是docker启动得,有自动恢复机制,但是mongorestore可不管这个,中断期间有1000个Document没有恢复成功。
重试了2次后才发现这问题,2天已经过去了,意识到就立刻把内存提升到32G,再次进行恢复。
但是新建的集群的密码跟源库这时是不一致的,又一天过去了,Document文档是恢复完毕,Index又无法建立,因为用户名和密码不一致,Fuck!
又双叒再次开始恢复,这下天下大吉了,然后这还不算完!
restore后,其实又过了一天,那要追平之后的数据,就得用上实时同步工具了,这里用的是阿里的mongoshake
下载:
1wget https://github.com/alibaba/MongoShake/releases/download/release-v2.8.5-20250403/mongo-shake-v2.8.5.tgz
2
3tar zxvf mongo-shake-v2.8.5.tgz
4cd mongo-shake-v2.8.5
5wget https://raw.githubusercontent.com/alibaba/MongoShake/refs/heads/develop/conf/collector.conf
我们需要注意collector.conf
的以下地方:
1# 源数据库
2mongo_urls = mongodb://root:xxxxxxxx@10.1.2.3:27017/?authSource=admin
3# 目标数据库
4tunnel.address = mongodb://root:xxxxxxxx@192.168.4.5:27017/?authSource=admin
5
6# 同步模式,all表示全量+增量同步,full表示全量同步,incr表示增量同步。
7# 也就是说,其实我们一开始就可以用full模式来进行同步,那为什么不呢?看下面的解释
8sync_mode = incr
9
10# 那还有一个问题:就是如果mongoshake的collector进程掉了,比如被OOM了
11# 下次再启动,会重新全量同步还是接着增量同步呢?
12# 答案是:同步的时候,collector会在源库建立一个mongoshake的db,里面有个表ckpt_default,里面放着同步信息
13# collector重启后会读取这个表进行增量同步,哪怕 sync_mode=full
14# 所以如果想重启后重新全量同步,那就需要手动删了这个表,或者换个表名,比如换成ckpt_sync
15
16# 那mongoshake实际是根据oplog进行同步的,那如果以前的oplog有删除,我们就必须用dump和restore进行一次完整备份恢复
17# 然后再进行追平,那刚开始我们记录下来的时间戳就有用了
18# Sun May 11 06:34:02 PM CST 2025 下午16点34分
19# collector用的是UST时间,我们的时间是东八区,CST,所以要减去8小时,16-8=8
20# 那就是:2025-05-11T08:30:00Z 时间稍稍前推一点,然后追平数据
21
22checkpoint.storage.db = mongoshake
23checkpoint.storage.collection = ckpt_default
24checkpoint.start_position = 2025-05-11T08:30:00Z
然后注意,源库实际是个代理,直接连的话,有三个节点,而mongoshake是够不到这三个节点的,所以需要强制改成一个直接连接:
1mongo_urls = mongodb://root:xxxxxxxx@10.1.2.3:27017/?authSource=admin&connect=direct
然后就开始同步
1# 注意,一定放到screen里
2screen -L
3
4# verbose 需要是0,记录到文本文件,便于之后持续观察
5./collector.linux -conf=collector.conf -verbose 0
看日志有同步的,就OK