欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MongoDB添加secondary节点的两种方法

程序员文章站 2022-06-05 21:00:21
前段时间维护的一个事业群的其中一条业务线的开发找到运维,提出来了一个MongoDB的优化问题,那段时间MongoDB正在从op管理移交给db进行维护,整个部门都对MongoDB的运维经验缺乏,MongoDB的优化更是一个未知的挑战。当op找到我,核心系统的公共服务平台用来进行短信服务的MongoDB ......

  前段时间维护的一个事业群的其中一条业务线的开发找到运维,提出来了一个mongodb的优化问题,那段时间mongodb正在从op管理移交给db进行维护,整个部门都对mongodb的运维经验缺乏,mongodb的优化更是一个未知的挑战。当op找到我,核心系统的公共服务平台用来进行短信服务的mongodb集群想进行一次优化,我当仁不能让的承担了这项我都觉得可能搞不定的任务。

    开发找到我提出了两点儿问题,并寻求运维团队解决这个问题,不过最终在我的理性的思考和他感性的思维碰撞下,最终我还是以胜利者的姿态胜出。我成功说服了他,并解答了他一些疑问,得到了满意的答复后再也没找我了。当然这里肯定不会就凭几句话,任你理论再怎么丰富,态度如何暧昧,不拿点儿真实数据,做点儿什么,怎么能说服经验丰富的开发认定的事儿。沟通了大半天,占据了我白天的工作时间,不过他提出来的问题还是很值得讨论。

    根据开发的逻辑,是想横向扩充secondary节点,把其他要求不高的业务放到secondary节点上,减轻primary节点的压力,达到部分读写分离,使得主要业务优先保障。我觉得这个出发点是好的,但并没有就此作出回应,其一是他没有认识到这个他认为的有延迟并不是数据库集群的问题(这里不详细讲述排查的过程,下一篇文章会讲些mongodb的写入与业务逻辑),其二是我们确实缺乏有效的资源硬件去进行扩充节点。

  不同的业务场景应用不同的架构策略,扩充secondary节点有时候不能解决问题,尤其是那些实时性很高的业务,但有时候扩充secondary节点确实有效,比如硬件升级后需要做的服务迁移,需要在线扩充secondary节点来满足业务需要的更高的硬件要求。

    mongodb的secondary节点的扩充,我总结起来有两种方式:1、rs.add()直接扩充 2、一致性备份后进行扩充(个人叫法)

  1、rs.add("host_name:port")

  具体的实现方式是登陆扩充节点的机器,编辑好配置文件,并建立相应的目录和权限,启动mongodb实例就可以了。

  需要注意的一点儿是这种扩充方式要保证同步源的数据量级,即保证在同步完数据前mongodb的oplog不会被覆盖,这点儿类似与mysql的redo log日志,如果被覆盖那么同步的数据出现不一致,导致同步失败。

  需要注意的另一点是同步数据的过程中,当集群数据达到一定量级时,同步数据的大小很大就会对网络造成一定的压力,可能对业务的核心交换机造成影响,因此需要用tc工具对同步流量做限速处理。这个限速需要考虑同步源可能不会是primary,也可能是同样角色的secondary节点,令外限速同步势必会增大同步时间,这个会增大oplog被覆盖的概率,具体限速值还是要经过计算才能把握好。

   2、一致性快照快速添加secondary节点(自我命名,欢迎各位交流)

    a)primary节点上进行一致性快照备份

    b)secondary节点上进行一致性快照恢复,仅仅对数据部分进行恢复,暂时不要对oplog进行恢复

     c)初始化oplog.rs集合,并恢复oplog记录

     d)初始化local数据库的其他两个集合db.replset.election,db.system.replset

    e)修改数据库配置并重启数据库(这一步操作前实例不开启认证模式、复制集的配置),rs.add("host_name:port")将secondary添加进集群并观察同步状态、校验数据的完整和一致性

实践的详细实践过程如下(仅供参考交流,生产环境慎用):

1、primary上进行一致性快照备份

 

 1 #primary节点或者其他secondary节点备份数据
 2 [root@172-16-3-190 mongodb]# /opt/app/mongodb/bin/mongodump -uroot -ppwd4mysql --authenticationdatabase=admin --port=27017 --oplog -o /tmp/dump_mongo/
 3 2018-08-20t15:42:47.028+0800 writing admin.system.users to 
 4 2018-08-20t15:42:47.030+0800 done dumping admin.system.users (1 document)
 5 2018-08-20t15:42:47.030+0800 writing admin.system.version to 
 6 2018-08-20t15:42:47.031+0800 done dumping admin.system.version (2 documents)
 7 2018-08-20t15:42:47.032+0800 writing super_hero.user_address to 
 8 2018-08-20t15:42:47.032+0800 writing super_hero.user_info to 
 9 2018-08-20t15:42:47.033+0800 done dumping super_hero.user_address (1 document)
10 2018-08-20t15:42:47.033+0800 done dumping super_hero.user_info (1 document)
11 2018-08-20t15:42:47.034+0800 writing captured oplog to 
12 2018-08-20t15:42:47.036+0800 dumped 1 oplog entry
13 
14 #查看备份的文件
15 [root@172-16-3-190 mongodb]# ls -lh /tmp/dump_mongo/
16 total 12k
17 drwxr-xr-x 2 root root 4.0k aug 20 15:42 admin
18 -rw-r--r-- 1 root root 110 aug 20 15:42 oplog.bson
19 drwxr-xr-x 2 root root 4.0k aug 20 15:42 super_hero
20 
21 #传递备份到准备添加为secondary的节点上
22 [root@172-16-3-190 tmp]# scp -r -p22222 /tmp/dump_mongo/ liyingxiao@172.16.3.189:/tmp

 

2、secondary节点一致性快照恢复

 1 #auth=true
 2 #replset = repl_mongo
 3 #clusterauthmode=keyfile
 4 #keyfile=/opt/app/mongodb/keyfile/mongodb.key
 5 
 6 ##恢复数据
 7 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongorestore --oplogreplay --port=27017 /tmp/dump_mongo/                                          
 8 2018-08-20t15:56:32.161+0800 preparing collections to restore from
 9 2018-08-20t15:56:32.193+0800 reading metadata for super_hero.user_info from /tmp/dump_mongo/super_hero/user_info.metadata.json
10 2018-08-20t15:56:32.194+0800 reading metadata for super_hero.user_address from /tmp/dump_mongo/super_hero/user_address.metadata.json
11 2018-08-20t15:56:32.222+0800 restoring super_hero.user_address from /tmp/dump_mongo/super_hero/user_address.bson
12 2018-08-20t15:56:32.300+0800 restoring super_hero.user_info from /tmp/dump_mongo/super_hero/user_info.bson
13 2018-08-20t15:56:32.867+0800 no indexes to restore
14 2018-08-20t15:56:32.867+0800 finished restoring super_hero.user_address (1 document)
15 2018-08-20t15:56:32.881+0800 no indexes to restore
16 2018-08-20t15:56:32.881+0800 finished restoring super_hero.user_info (1 document)
17 2018-08-20t15:56:32.881+0800 restoring users from /tmp/dump_mongo/admin/system.users.bson
18 2018-08-20t15:56:32.993+0800 replaying oplog
19 2018-08-20t15:56:32.997+0800 done

3、初始化oplog.rs集合,并恢复oplog记录

  创建oplog.rs集合并初始化大小

1 use local
2 db.createcollection("oplog.rs",{"capped":true,"size":100000000})

  恢复一致性备份的oplog.rs集合的数据到secondary节点

1 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongorestore -d local -c oplog.rs --port=27017 /tmp/dump_mongo/oplog.bson  
2 2018-08-20t16:12:49.848+0800 checking for collection data in /tmp/dump_mongo/oplog.bson
3 2018-08-20t16:12:49.852+0800 restoring local.oplog.rs from /tmp/dump_mongo/oplog.bson
4 2018-08-20t16:12:49.925+0800 no indexes to restore
5 2018-08-20t16:12:49.925+0800 finished restoring local.oplog.rs (1 document)
6 2018-08-20t16:12:49.925+0800 done

4、初始化db.replset.election,db.system.replset集合,其中replset.election需要查询主节点数据并将这些数据存储到secondary节点,或者两个结合自行save到secondary节点。另集合system.replset加入复制集后可自动识别primary节点内容(这里我采取自行同步数据)

1 #primary节点
2 repl_mongo:primary> db.replset.election.find()
3 { "_id" : objectid("5b7a6ee5de7a24b82a686139"), "term" : numberlong(1), "candidateindex" : numberlong(0) }
4 #secondary节点
5 db.replset.election.save({ "_id" : objectid("5b7a6ee5de7a24b82a686139"), "term" : numberlong(1), "candidateindex" : numberlong(0) })

5、修改数据库配置并重启,添加secondary节点到复制集群中

#auth=true
#replset = repl_mongo
#clusterauthmode=keyfile
#keyfile=/opt/app/mongodb/keyfile/mongodb.key

[root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongod --shutdown -f /opt/app/mongodb/mongo.conf 
killing process with pid: 5331
[root@172-16-3-189 we_ops_admin]# vim /opt/app/mongodb/mongo.conf  #注释去掉并重启
[root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongod -f /opt/app/mongodb/mongo.conf            
about to fork child process, waiting until server is ready for connections.
forked process: 5722
child process started successfully, parent exiting

#添加secondary节点
repl_mongo:primary> rs.add({"_id":1,"host":"172.16.3.189:27017"})
{
        "ok" : 1,
        "operationtime" : timestamp(1534752953, 1),
        "$clustertime" : {
                "clustertime" : timestamp(1534752953, 1),
                "signature" : {
                        "hash" : bindata(0,"tt9nzhovydutgfznc1kg1exl0hc="),
                        "keyid" : numberlong("6591702943026642945")
                }
        }
}

6、登录添加的secondary节点,验证复制集状态,数据完整和一致性。

1 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongo -uroot -ppwd4mysql --authenticationdatabase=admin --port=27017

  重点介绍第二种省时省心但费力费操作的添加secondary节点的方法,实践过程中数据库实例前期去掉认证和复制集参数,是方便我们下面的一些需要用户权限的操作,避免建立管理员账号,后续加入集群后自行同步了primary节点的账号。重启后登录secondary节点验证服务的可用性和数据一致性时,使用集群的管理账号进入,否则会报认证的错误。

  总结如上两种扩充方式,对于方式1的扩充简单省事,需要保证oplog不被覆盖和评估同步流量的影响问题,是我们通常进行横向复制集添加secondary节点的方法。对于第二种方式,操作繁琐但不用担心oplog被覆盖,且操作期间不会过多担忧网络流量的问题,仅仅考虑网络传输的流量影响。第一种方式操作时间周期长,不可控的影响范围大费时费精力,第二种方式操作时间短,操作的步骤多,容易出现其他问题。