前段时间维护的一个事业群的其中一条业务线的开发找到运维,提出来了一个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上进行一致性快照备份

 #primary节点或者其他secondary节点备份数据
[root@--- mongodb]# /opt/app/mongodb/bin/mongodump -uroot -ppwd4mysql --authenticationDatabase=admin --port= --oplog -o /tmp/dump_mongo/
--20T15::47.028+ writing admin.system.users to
--20T15::47.030+ done dumping admin.system.users ( document)
--20T15::47.030+ writing admin.system.version to
--20T15::47.031+ done dumping admin.system.version ( documents)
--20T15::47.032+ writing super_hero.user_address to
--20T15::47.032+ writing super_hero.user_info to
--20T15::47.033+ done dumping super_hero.user_address ( document)
--20T15::47.033+ done dumping super_hero.user_info ( document)
--20T15::47.034+ writing captured oplog to
--20T15::47.036+ dumped oplog entry #查看备份的文件
[root@--- mongodb]# ls -lh /tmp/dump_mongo/
total 12K
drwxr-xr-x root root .0K Aug : admin
-rw-r--r-- root root Aug : oplog.bson
drwxr-xr-x root root .0K Aug : super_hero #传递备份到准备添加为secondary的节点上
[root@--- tmp]# scp -r -P22222 /tmp/dump_mongo/ liyingxiao@172.16.3.189:/tmp

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

 #auth=true
#replSet = repl_mongo
#clusterAuthMode=keyFile
#keyFile=/opt/app/mongodb/keyfile/mongodb.key ##恢复数据
[root@--- test]# /opt/app/mongodb/bin/mongorestore --oplogReplay --port= /tmp/dump_mongo/
--20T15::32.161+ preparing collections to restore from
--20T15::32.193+ reading metadata for super_hero.user_info from /tmp/dump_mongo/super_hero/user_info.metadata.json
--20T15::32.194+ reading metadata for super_hero.user_address from /tmp/dump_mongo/super_hero/user_address.metadata.json
--20T15::32.222+ restoring super_hero.user_address from /tmp/dump_mongo/super_hero/user_address.bson
--20T15::32.300+ restoring super_hero.user_info from /tmp/dump_mongo/super_hero/user_info.bson
--20T15::32.867+ no indexes to restore
--20T15::32.867+ finished restoring super_hero.user_address ( document)
--20T15::32.881+ no indexes to restore
--20T15::32.881+ finished restoring super_hero.user_info ( document)
--20T15::32.881+ restoring users from /tmp/dump_mongo/admin/system.users.bson
--20T15::32.993+ replaying oplog
--20T15::32.997+ done

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

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

 use local
db.createCollection("oplog.rs",{"capped":true,"size":})

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

 [root@--- test]# /opt/app/mongodb/bin/mongorestore -d local -c oplog.rs --port= /tmp/dump_mongo/oplog.bson
--20T16::49.848+ checking for collection data in /tmp/dump_mongo/oplog.bson
--20T16::49.852+ restoring local.oplog.rs from /tmp/dump_mongo/oplog.bson
--20T16::49.925+ no indexes to restore
--20T16::49.925+ finished restoring local.oplog.rs ( document)
--20T16::49.925+ done

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

 #primary节点
repl_mongo:PRIMARY> db.replset.election.find()
{ "_id" : ObjectId("5b7a6ee5de7a24b82a686139"), "term" : NumberLong(), "candidateIndex" : NumberLong() }
#secondary节点
db.replset.election.save({ "_id" : ObjectId("5b7a6ee5de7a24b82a686139"), "term" : NumberLong(), "candidateIndex" : NumberLong() })

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

#auth=true
#replSet = repl_mongo
#clusterAuthMode=keyFile
#keyFile=/opt/app/mongodb/keyfile/mongodb.key [root@--- test]# /opt/app/mongodb/bin/mongod --shutdown -f /opt/app/mongodb/mongo.conf
killing process with pid:
[root@--- test]# vim /opt/app/mongodb/mongo.conf #注释去掉并重启
[root@--- test]# /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:
child process started successfully, parent exiting #添加secondary节点
repl_mongo:PRIMARY> rs.add({"_id":,"host":"172.16.3.189:27017"})
{
"ok" : ,
"operationTime" : Timestamp(, ),
"$clusterTime" : {
"clusterTime" : Timestamp(, ),
"signature" : {
"hash" : BinData(,"Tt9nzhoVYdUtGFZnc1Kg1exl0Hc="),
"keyId" : NumberLong("")
}
}
}

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

 [root@--- test]# /opt/app/mongodb/bin/mongo -uroot -ppwd4mysql --authenticationDatabase=admin --port=

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

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

 

MongoDB添加secondary节点的两种方法的更多相关文章

  1. WebGL中添加天空盒的两种方法

    天空盒 的添加可以让模型所在的场景非常漂亮,而其原理也是非常简单的,相信看完下面代码就可以明白了. 说到天空盒的两种方法,倒不如说是两种写法,分别用了纹理加载的两个方法:loadTexture和loa ...

  2. DataGridView动态添加新行的两种方法

    简单介绍如何为DataGridView控件动态添加新行的两种方 法: 方法一: int index=this.dataGridView1.Rows.Add();this.dataGridView1.R ...

  3. windows 7中添加新硬件的两种方法(本地回环网卡)

    最近在windows7上使用VMwareWorkstation7玩一些实验,遇到需要配置不同网络的问题. 因为在windows2003server上习惯使用要本地回环网卡了,那就想着在Windows7 ...

  4. 为WebService添加身份验证的两种方法

    方法一:SoapHeader 辅助类:MySoapHeader //SoapHeader 添加引用 using System.Web.Services.Protocols; #region 配置登录标 ...

  5. Linux添加系统环境变量的两种方法

    方法一 export PATH=/usr/local/bin:$PATH 这种方法的PATH 在终端关闭 后就会消失.所以还是建议通过编辑/etc/profile来改PATH 方法二 # vim /e ...

  6. Windows添加启动项的两种方法

    方案1直接将脚本放到启动文件夹里面 C:\Users\XXX\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 方案2 Win ...

  7. idea添加svn项目的两种方法

    1.是直接用svn客户端检出后,在idea直接打开其项目. 2.直接在idea里面拉取svn的项目

  8. Linux添加系统调用的两种方法

    前言 系统调用的基本原理 系统调用其实就是函数调用,只不过调用的是内核态的函数,但是我们知道,用户态是不能随意调用内核态的函数的,所以采用软中断的方式从用户态陷入到内核态.在内核中通过软中断0X80, ...

  9. unity3d为对象添加脚本的两种方法

    首先添加一个物体,然后新建一个C#脚本.接下去有两种方法把C#脚本与物体绑定. 1.在类声明上方添加如下代码: [AddComponentMenu("a/b")] 这句话表示在该物 ...

随机推荐

  1. C++ 三大特性:封装、继承、多态性

    要讲  封装.继承.多态就必须从面向对象说起 开发一个软件是为了解决某些问题,这些问题所涉及的业务范围称为该软件的问题域.面向对象的编程语言将客观事物看作具有属性和行为(或服务)的对象,通过抽象找出同 ...

  2. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第6章编程练习9

    #include <iostream> #include <fstream> #include <cstdlib> #include <string> ...

  3. 定位方式(d16)

    一,回顾, ①selector和xpath的区别,selector是解析的html,xpth是解析的xml,所以使用selector比使用xpath快, ②定位元素的单数和复数,当使用单数定位不到元素 ...

  4. leetcode-只出现一次的数字合并两个有序数组

    题目:合并两个有序数组 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素 ...

  5. BUAA-OO-第二单元总结

    OO第二单元总结 一.第五次作业 1.1 设计策略与架构 第五次作业要求的是完成设计支持一架傻瓜电梯的电梯系统.考虑到需要数据结构存放所有的请求,因此构建了FloorRequests类用来存放所有的请 ...

  6. elasticsearch 占CPU过高

    一.线上有一台服务器cpu一直跑满,最终定位导是elasticsearch导致的 二.通过一波查找更改jvm和删除 修改后没有生效笔记尴尬 然后网友说删除索引试了试就可以了  哈哈 curl http ...

  7. Raiden Charge

    2017年10月22 周日 这是个元气满满 值得纪念的一天(不好意思走错片场了) 虽然有各种乱遭的客观元素 但我们队确确实实地打铁了 那些我们轻视的 野鸡(误)大学 都在我们前面 都说知耻而后勇 虽然 ...

  8. linux系统中的时间

    1.编程显示系统时间: #include <stdio.h> #include <time.h> /* gcc -o fix fixedFormatTime.c ./fix * ...

  9. [转] Quality Of Service In OpenStack

    http://tropicaldevel.wordpress.com/2013/07/15/quality-of-service-in-openstack/ In this post I will b ...

  10. vue+mescroll=VScrollFull

    VScrollFull 介绍 这个组件是什么? 是为了方便的使用下拉刷新,上拉加载而去封装的一个依赖于 mescroll.js 的 vue 组件(未发布,文末代码~) 封装这个组件使用了什么? mes ...