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. 创建一个简单的terraform module

      terraform module可以实现代码的复用,同时方便分享,下面创建一个简单的基于localfile && template provider 的module module ...

  2. 在sorted range上的操作(includes,set_union,set_intersection,set_difference)

    includes //版本一:用operator <比较元素 template <class InputerIterator1,class InputerIterator2> boo ...

  3. 对某个区间操作(sort,stable_sort,parital_sort,parital_sort_copy,nth_element,is_sorted)

    sort //版本一 template <class RandomAccessIterator> void sort(RandomAccessIterator first,RandomAc ...

  4. Gitlab备份与恢复、迁移与升级

    0.Gitlab安装 1.安装和配置必要的依赖关系 在CentOS7,下面的命令将在系统防火墙打开HTTP和SSH访问.   yum install curl openssh-server postf ...

  5. unicodedata.normalize()/使用strip()、rstrip()和lstrip()/encode和decode 笔记(具体可看 《Python Cookbook》3rd Edition 2.9~2.11)

    unicodedata.normalize()清理字符串 # normalize()的第一个参数指定字符串标准化的方式,分别有NFD/NFC >>> s1 = 'Spicy Jala ...

  6. 编译小米mini openwrt

    编译小米mini openwrt 1.下载openwrt源码包:进入要下载保存的文件目录,输入 git clone git://git.openwrt.org/15.05/openwrt.git 2. ...

  7. mysql exists及not exists的使用

    对exists及not exists的使用根据下面的示例进行解释 如sql: select sname from student where exists (select * from score)) ...

  8. 黄聪:JQUERY的datatables插件,Date range filter时间段筛选功能

    需配合moment插件实现:http://momentjs.com/ 演示:http://live.datatables.net/zuciyawi/1/edit HTML代码 <!DOCTYPE ...

  9. 解决js输出汉字乱码问题

    当我们需要使用js输出汉字时,偶然会出现输出的中文汉字乱码的情况,在网上收了很多解决方案 1.在mata中加 <meta content="text/html; charset=utf ...

  10. 天朝屁民每天做T跟菜贩一样,进菜-卖菜,为伟大的菜贩精神点赞

    天朝屁民每天做T跟菜贩一样,进菜-卖菜,为伟大的菜贩精神点赞