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集群搭建

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

  9. windows下mongodb集群搭建

    本文介绍在windows环境下如何搭建一个高可用性的mongodb集群.系统环境为win7,mongodb版本为3.6.3. 本文采用的是分片+副本集的方式搭建集群,将分别介绍如何使用副本集和分片来提 ...

随机推荐

  1. (原创)JAVA多线程二线程池

    一,线程池的介绍 线程池包括一下三种: 线程池名称 创建方法 特点 其他 固定大小线程池 ExecutorService threadpool = Executors.newFixedThreadPo ...

  2. 第七届山东省ACM省赛

    激动人心的省赛终于结束了…平静下来再回头看真的感觉一波三折…先是赛前毫无预兆的查出突发性耳聋…伴随而来的就是左耳听力下降.轻微耳鸣.极个别情况下的头晕…不过这都还好,毕竟药物可以恢复…热身赛只过了一道 ...

  3. Win10如何隐藏Windows Defender任务栏图标

    导读 Windows 10 至发布以来就内置集成了 Windows Defender 安全防护应用,但有许多用户平常压根儿就没注意到它的存在.微软为了使安全防护功能更加明显,Windows 10 周年 ...

  4. inline-block在ie6中的经典bug

    众所周知,给元素设置 inline-block ,可以让ie下的元素出发layout:1. 但是,当给元素设置 inline-block 后,在另外一个class 样式(非设置inline-block ...

  5. Request.Querystring中文乱码问题解决

    现象:近期项目中用到查询字符串传值,如果传递的是英文一切正常,但是传递中文时,使用request.querystring[]得到的是乱码. 原因:不知道为什么,可能是编码不一致问题 解决方法1:修改w ...

  6. NodeJS V8 GC概览

    [A tour of V8: Garbage Collection] http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection 基本是 ...

  7. javascript 之封装技巧

    技术--- 闭包 javascript中的对象属性都是公开的,外界都可访问到,例: function cat(){ this.name = '猫'; this.climb = function(){ ...

  8. hbase的thriftserver开启

    说明:hbase的thriftserver默认已经编译好,可以使用,不需要跟hadoopthrift一样配置. 要使用Hbase的thrift接口,必须将它的服务启动,命令行为: hbase-deam ...

  9. python excel写入及追加写入

    # -*- coding:utf-8 _*- """ @author:Administrator @file: excel.py Description :如果行数是10 ...

  10. Android-Nexus5-命令刷机

    第一步)需要有有一部Nexus5手机: 第二步)寻找 .tgz 刷机包: 1: 2: 3.进行hammerhead-lmy47d-factory-6c1ad81e.tgz的下载: 4 进行解压: 5. ...