Mongodb集群搭建之 Replica Set

Replica Set

中文翻译叫做副本集,不过我并不喜欢把英文翻译成中文,总是感觉怪怪的。其实简单来说就是集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致。如下图:

Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。

默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做Read Preference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。

仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。

介绍完了集群方案,那么现在就开始搭建了。

鉴于实验条件有限,本文都是通过Docker虚拟机实现

方案一:快速搭建 简单了解副本集集群(简单命令自动创建)

一、创建数据持久化本地目录:

mkdir -p /root/application/program/mongodb/data

二、快速启动Docker创建容器(Docker image已安装好MongoDB:3.6.3)

docker run -d -v `pwd`/data/master:/mongodb -p 27017:27017 docker.io/mongodb:3.6.3 /usr/sbin/init

三:启动mongo shell并启动相关进程

mongo --nodb

#创建一个包含三个服务器的副本集:一个主服务器和两个备份服务器

replicaSet = new ReplSetTest({"nodes" : 3})

#启动3个mongod进程

replicaSet.startSet()

#配置复制功能

replicaSet.initiate()

现在就已经有了3个mongod进程,分别运行在20000、20001和20002端口。

这样一套包含一个主服务器和两个备份服务器的副本集集群 就搭建好了

方案二:手动创建(可以在一台机器上通过不同端口搭建,也可以使用三台独立的虚拟机搭建)

1.建立数据文件夹

一般情况下不会把数据目录建立在mongodb的解压目录下,不过这里方便起见,就建在mongodb解压目录下吧。

#三个目录分别对应主,备,仲裁节点

mkdir -p /root/application/program/mongodb/data/master

mkdir -p /root/application/program/mongodb/data/slaver

mkdir -p /root/application/program/mongodb/data/arbiter

2.快速创建并启动三个Docker容器(可以理解为3台虚拟机,有独立的IP)

docker run -d -v `pwd`/data/master:/mongodb -p 27017:27017 docker.io/mongodb:3.6.3 /usr/sbin/init

docker run -d -v `pwd`/data/slaver:/mongodb -p 27018:27017 docker.io/mongodb:3.6.3 /usr/sbin/init

docker run -d -v `pwd`/data/arbiter:/mongodb -p 27019:27017 docker.io/mongodb:3.6.3 /usr/sbin/init

3.建立配置文件

由于配置比较多,所以我们将配置写到文件里。

#master.conf

  1. dbpath=/mongodb/data/master

  2. logpath=/mongodb/log/master.log

  3. pidfilepath=/mongodb/master.pid

  4. directoryperdb=true

  5. logappend=true

  6. replSet=testrs

  7. bind_ip=172.17.0.2

  8. port=27017

  9. oplogSize=10000

  10. fork=true

  11. noprealloc=true

#slaver.conf

  1. dbpath=/mongodb/data/slaver

  2. logpath=/mongodb/log/slaver.log

  3. pidfilepath=/mongodb/slaver.pid

  4. directoryperdb=true

  5. logappend=true

  6. replSet=testrs

  7. bind_ip=172.17.0.3

  8. port=27017

  9. oplogSize=10000

  10. fork=true

  11. noprealloc=true

#arbiter.conf

  1. dbpath=/mongodb/data/arbiter

  2. logpath=/mongodb/log/arbiter.log

  3. pidfilepath=/mongodb/arbiter.pid

  4. directoryperdb=true

  5. logappend=true

  6. replSet=testrs

  7. bind_ip=172.17.0.4

  8. port=27017

  9. oplogSize=10000

  10. fork=true

  11. noprealloc=true

参数解释:

dbpath:数据存放目录

logpath:日志存放路径

pidfilepath:进程文件,方便停止mongodb

directoryperdb:为每一个数据库按照数据库名建立文件夹存放

logappend:以追加的方式记录日志

replSet:replica set的名字

bind_ip:mongodb所绑定的ip地址

port:mongodb进程所使用的端口号,默认为27017

oplogSize:mongodb操作日志文件的最大大小。单位为Mb,默认为硬盘剩余空间的5%

fork:以后台方式运行进程

noprealloc:不预先分配存储

4.启动mongodb

进入每个mongodb节点的bin目录下

中间省略使用docker exec -it container_id bash 进入docker容器的步骤

  1. ./monood -f master.conf

  2. ./mongod -f slaver.conf

  3. ./mongod -f arbiter.conf

注意配置文件的路径一定要保证正确,可以是相对路径也可以是绝对路径。

5.配置主,备,仲裁节点

可以通过客户端连接mongodb,也可以直接在三个节点中选择一个连接mongodb。

  1. ./mongo --host 172.17.0.2 --port 27017   #ip和port是某个节点的地址

  2. >use admin

  3. >config={ _id:"testrs", members:[ {_id:0,host:'172.17.0.2:27017',priority:2}, {_id:1,host:'172.17.0.3:27017',priority:1},{_id:2,host:'172.17.0.4:27017',arbiterOnly:true}] };

  4. >rs.initiate(config)             #使配置生效

    或者

  5. >db.adminCommand({"replSetInitiate" : config})

    config是可以任意的名字,当然最好不要是mongodb的关键字,conf,config都可以。最外层的_id表示replica set的名字,members里包含的是所有节点的地址以及优先级。优先级最高的即成为主节点,即这里的172.17.0.2:27017。特别注意的是,对于仲裁节点,需要有个特别的配置——arbiterOnly:true。这个千万不能少了,不然主备模式就不能生效。

配置的生效时间根据不同的机器配置会有长有短,配置不错的话基本上十几秒内就能生效,有的配置需要一两分钟。如果生效了,执行rs.status()命令会看到如下信息:

    testrs:SECONDARY> rs.status()

    {

    "set" : "testrs",

    "date" : ISODate("2018-08-07T07:29:24.076Z"),

    "myState" : 1,

    "term" : NumberLong(1),

    "heartbeatIntervalMillis" : NumberLong(2000),

    "optimes" : {

    "lastCommittedOpTime" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    },

    "readConcernMajorityOpTime" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    },

    "appliedOpTime" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    },

    "durableOpTime" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    }

    },

    "members" : [

    {

    "_id" : 0,

    "name" : "172.17.0.2:27017",

    "health" : 1,

    "state" : 1,

    "stateStr" : "PRIMARY",

    "uptime" : 364,

    "optime" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    },

    "optimeDate" : ISODate("2018-08-07T07:29:14Z"),

    "infoMessage" : "could not find member to sync from",

    "electionTime" : Timestamp(1533626952, 1),

    "electionDate" : ISODate("2018-08-07T07:29:12Z"),

    "configVersion" : 1,

    "self" : true

    },

    {

    "_id" : 1,

    "name" : "172.17.0.3:27017",

    "health" : 1,

    "state" : 2,

    "stateStr" : "SECONDARY",

    "uptime" : 22,

    "optime" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    },

    "optimeDurable" : {

    "ts" : Timestamp(1533626954, 1),

    "t" : NumberLong(1)

    },

    "optimeDate" : ISODate("2018-08-07T07:29:14Z"),

    "optimeDurableDate" : ISODate("2018-08-07T07:29:14Z"),

    "lastHeartbeat" : ISODate("2018-08-07T07:29:22.187Z"),

    "lastHeartbeatRecv" : ISODate("2018-08-07T07:29:22.807Z"),

    "pingMs" : NumberLong(0),

    "syncingTo" : "172.17.0.2:27017",

    "configVersion" : 1

    },

    {

    "_id" : 2,

    "name" : "172.17.0.4:27017",

    "health" : 1,

    "state" : 7,

    "stateStr" : "ARBITER",

    "uptime" : 22,

    "lastHeartbeat" : ISODate("2018-08-07T07:29:22.186Z"),

    "lastHeartbeatRecv" : ISODate("2018-08-07T07:29:23.681Z"),

    "pingMs" : NumberLong(0),

    "configVersion" : 1

    }

    ],

    "ok" : 1,

    "operationTime" : Timestamp(1533626954, 1),

    "$clusterTime" : {

    "clusterTime" : Timestamp(1533626954, 1),

    "signature" : {

    "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

    "keyId" : NumberLong(0)

    }

    }

    }

如果配置正在生效,其中会包含如下信息:

  1. "stateStr" : "RECOVERING"

同时可以查看对应节点的日志,发现正在等待别的节点生效或者正在分配数据文件。

现在基本上已经完成了集群的所有搭建工作。至于测试工作,可以留给大家自己试试。一个是往主节点插入数据,能从备节点查到之前插入的数据(查询备节点可能会遇到某个问题,可以自己去网上查查看)。二是停掉主节点,备节点能变成主节点提供服务。三是恢复主节点,备节点也能恢复其备的角色,而不是继续充当主的角色。二和三都可以通过rs.status()命令实时查看集群的变化。

5.其它操作

添加、删除新成员

1.新启动一个mongod进程

mongod --replSet spock --dbpath /mongodb/mongodb/bin/datas/m4 --logpath /mongodb/mongodb/bin/logs/m4/mongodb.log --bind_ip 172.17.0.5 --port 27020 --fork

2. 登录其中一个节点,并执行rs.add命令

mongo 172.17.0.3:27017

rs.add("172.17.0.5:27020")

删除的话 执行  rs.remove("172.17.0.5:27020")

或者

config = {

"_id" : "spock",

"members" : [

{"_id" : 0, "host" : "172.17.0.2:27017"},

{"_id" : 1, "host" : "172.17.0.3:27018"},

{"_id" : 2, "host" : "172.17.0.4:27019"},

{"_id" : 3, "host" : "172.17.0.5:27020"}

]

}

rs.reconfig(config)

MongoDb的“not master and slaveok=false”错误及解决方法

这是正常的,因为SECONDARY是不允许读写的,如果非要解决,方法如下:

SECONDARY> rs.slaveOk();

思考:

1.尽可能在副本集中使用奇数个数据成员,而不是使用仲裁者;

2. 建议大多数成员放在同一个数据中心,保证其中一个数据中心挂掉后,另一个数据中心满足“大多数”;

3.MongoDB只支持单一主节点;

4.设置延迟备份节点,要求优先级置为0(priority : 0),隐藏成员(Hidden: true),避免误操作;

5.推荐配置:两个数据中心使用偶数个数据成员,另外一台配置低的机器做仲裁者 (arbiteronly : true)

Mongodb集群搭建之 Replica Set的更多相关文章

  1. Mongodb 集群搭建以及常见错误

    Mongodb 集群搭建以及常见错误 1 关于Replica Sets +Sharding(主从复制加分片)搭建,不这详细去说,网上有很多,大部分的例子就三台服务器之间做主从复制,分2个shard,架 ...

  2. MongoDB集群搭建-副本集

    MongoDB集群搭建-副本集 概念性的知识,可以参考本人博客地址: 一.Master-Slave方案: 主从: 二.Replica Set方案: 副本集: 步骤:(只要按步骤操作,100%成功) 1 ...

  3. MongoDB集群搭建-分片

    MongoDB集群搭建-分片 一.场景: 1,机器的磁盘不够用了.使用分片解决磁盘空间的问题. 2,单个mongod已经不能满足写数据的性能要求.通过分片让写压力分散到各个分片上面,使用分片服务器自身 ...

  4. mongodb集群搭建过程记录

    mongodb集群搭建花费比较长的时间,在此记录下过程,方便以后使用 一 软件环境 系统:ubuntu 18.04,mongodb 社区版4.2 https://docs.mongodb.com/ma ...

  5. Mongodb集群搭建之 Sharding+ Replica Sets集群架构(2)

    参考http://blog.51cto.com/kaliarch/2047358 一.概述 1.1 背景 为解决mongodb在replica set每个从节点上面的数据库均是对数据库的全量拷贝,从节 ...

  6. Mongodb集群搭建的三种方式

    转自:http://blog.csdn.net/luonanqin/article/details/8497860 MongoDB是时下流行的NoSql数据库,它的存储方式是文档式存储,并不是Key- ...

  7. mongodb集群搭建(分片+副本)

    原文地址:https://www.cnblogs.com/ityouknow/p/7344005.html 相关概念 先来看一张图: 从图中可以看到有四个组件:mongos.config server ...

  8. mongodb集群搭建(分片+副本)开启安全认证

    关于安全认证得总结: 这个讲述的步骤也是先创建超管用户,关闭服务,然后生成密钥文件,开启安全认证,启动服务 相关概念 先来看一张图: 从图中可以看到有四个组件:mongos.config server ...

  9. Mongodb集群搭建

    搭建高可用Mongodb集群 http://www.lanceyan.com/category/tech/mongodb/page/2 再看MongoDB副本集  http://blog.itpub. ...

随机推荐

  1. Jenkins部署项目

    第三首先部署好Jenkins 新建一个自由项目 svn地址,credentials是指认证,点击Ad那里添加,并选择username和password方式,并输入用户名和密码 H/5 * * * * ...

  2. 我的vim(持续更新)

    保存并退出:wq 退出但不保存修改:q! 不退出vi使用shell(bash)命令:!bash (如果想回到vi,bash下输入exit回车) 设置行号 :set nu 取消行号:set nonu 设 ...

  3. out, ref 和 params 的区别和用法

    1. out 参数. 如果你在一个方法中,返回多个相同类型的值,可以考虑返回一个数组. 但是,如果返回多个不同类型的值,返回数组就不可取.这个时候可以考虑使用out参数. out参数就侧重于在一个方法 ...

  4. 20 约束 异常处理 MD5 日志

    三十九, 一.类的约束 1.抛出异常    NotImplementedError 2.抽象方法 含有抽象方法的类是抽象类 抽象类中的方法全是抽象方法的是接口 抽象类不能创建对象 二.异常处理 处理完 ...

  5. redis之 Redis持久化配置

    Redis持久化配置 Redis的持久化有2种方式   1快照  2是日志 Rdb快照的配置选项 save 900 1      // 900内,有1条写入,则产生快照 save 300 1000   ...

  6. 创建表时,主键 USING BTREE、USING HASH 的含义(待补充)

    PRIMARY KEY (`id`) USING BTREE

  7. java 连接 hiveserver2 例子

    启动了  hiveserver2 以后才能使用 程序连接 .目前的 使用的 是  server2 版本.和以前的版本驱动包名不同: package hadoop; import java.sql.Co ...

  8. WEB开发库收集

    1. EASYUI          http://www.jeasyui.com/ [INTRODUCTION] jQuery EasyUI framework helps you build yo ...

  9. Flume和Kafka整合安装

    版本号: RedHat6.5   JDK1.8    flume-1.6.0   kafka_2.11-0.8.2.1 1.flume安装 RedHat6.5安装单机flume1.6:http://b ...

  10. Excel技巧--批量生成指定名称的文件夹

    当我要按excel表当中的名字来批量生成文件夹时,手动一个个制作很麻烦(特别是成百上千个时).于是我们可以这么做: 1.在名字右侧建立公式:"MD "&A2. 2.将公式拖 ...