MENU

MongoDB搭建高可用副本集群-Replica Set

2017 年 08 月 22 日 • 应用服务器

前几天吧,开发的大哥问我本地还有没资源了,现在想要装一个mongodb用,因为这东西只是听说过,也没用过,更别说搭建了,然后找了一个服务器,在官网下了一个源码包,谷歌了一下,就装上了,也启动了,然后把地址给他发过去了,可以正常使用,哈哈。然后又和我说你有时间研究一下MongoDB的集群要怎么搭建,以后有项目可能会用这个,既然来事了,说搞就搞,大概查了一下,发现MongoDB做集群的方式大概是有三种,最常用的一种也就是我现在要写的这个,英文Replica Set,翻译过来叫副本集群,已经搞出来了,经过测试得到的结论是可以正常使用,哈哈,总结一下,具体方法如下。

首先需要三台服务器,分别为主节点,备节点,及仲裁节点,主备节点存储数据,仲裁节点不存储数据,客户端同时连接主备节点,不连接仲裁节点。默认情况下,主节点提供所有增删改查服务,备节点不提供任何服务,仲裁节点是一个特殊的节点,不存储数据,他的作用是决定哪个备节点在主节点挂掉之后提升为主节点,现在是一主一从,仍需要仲裁节点来提升备节点级别,如果没有它,主的挂了备的还是备的,不会提升为主的,所以仲裁节点必须得在,现有环境如下,使用centos6.9操作系统

192.168.1.213 mongodb-master

192.168.1.166 mongodb-slave

192.168.1.251 mongodb-arbiter

安装阶段

1.下载MongoDB
[root@mongodb-master ~]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.7.tgz

下载可能会很慢,等吧。。。。

2.解压安装,配置变量

三个服务器同时操作即可,我存放的目录为/usr/local/

[root@mongodb-master ~]# tar zxf mongodb-linux-x86_64-rhel62-3.4.7.tgz -C /usr/local/
[root@mongodb-master ~]# mv /usr/local/mongodb-linux-x86_64-rhel62-3.4.7/ /usr/local/mongodb
[root@mongodb-master ~]# cat >>/etc/profile<<OEF
> export PATH=\$PATH:/usr/local/mongodb/bin
> OEF
[root@mongodb-master ~]# source /etc/profile

集群配置阶段

创建数据文件夹

创建数据文件夹,就放到MongoDB安装目录下吧,我就以一个为例子了,剩下的两个按着弄吧

[root@mongodb-master ~]# mkdir /usr/local/mongodb/data
创建配置文件,主节点,并启动
[root@mongodb-master ~]# cat >>/usr/local/mongodb/mongod.conf<<OEF
> dbpath=/usr/local/mongodb/data
> logpath=/usr/local/mongodb/log/master.log
> pidfilepath=/usr/local/mongodb/master.pid
> directoryperdb=true  
> logappend=true  
> replSet=rj_bai  
> bind_ip=192.168.1.213
> port=27017
> oplogSize=10000
> fork=true  
> noprealloc=true
> OEF
启动服务
[root@mongodb-master ~]# mongod -f /usr/local/mongodb/mongod.conf

如果你是按着我这个写的,这里会抛个错,原因是没有log那个文件夹,需要创建一下即可。

[root@mongodb-master ~]# mkdir /usr/local/mongodb/log && mongod -f /usr/local/mongodb/mongod.conf
[root@mongodb-master ~]# netstat -lntp | grep mongo
tcp        0      0 192.168.1.213:27017         0.0.0.0:*                   LISTEN      23016/mongod

备节点及仲裁节点配置文件如下,启动方式和以上一样,就不一一写了。

备节点
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/slaver.log
pidfilepath=/usr/local/mongodb/log/slaver.pid
directoryperdb=true
logappend=true
replSet=rj_bai    
bind_ip=192.168.1.166
port=27017
oplogSize=10000
fork=true
noprealloc=true
仲裁节点
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/arbiter.log
pidfilepath=/usr/local/mongodb/arbiter.pid
directoryperdb=true
logappend=true
replSet=rj_bai
bind_ip=192.168.1.251
port=27017
oplogSize=10000
fork=true
noprealloc=true
参数解释
dbpath数据库存放目录
logpath日志存放目录
pidfilepathpid文件
directoryperdb数据库按名独立存放
logappend以追加的方式记录日志
replSet replica set 的名字
bind_ip绑定的ip地址
port 指定端口号,默认27017
oplogSize操作文件最大值,单位mb,默认硬盘百分之5
fork 以后台方式运行
noprealloc不预先分配内存

集群配置

连接任意节点,我连接的213作为主节

[root@mongodb-master ~]# mongo 192.168.1.213:27017

连接后会出现几个警告,如下图

WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine

看到这个不会影响使用,只是建议使用xfs文件系统,也就是centos7系列的默认文件系统,我用的6,EXT4的,所以会抛这个,不管

WARNING: Access control is not enabled for the database.

没有对数据库进行访问控制,对数据和配置的读写访问不受限制

最后两个的解决方法,重启后只要文件系统和访问控制的错了,先不管访问控制了。

[root@mongodb-master ~]# echo "never" > /sys/kernel/mm/transparent_hugepage/enabled
[root@mongodb-master ~]# echo "never" >  /sys/kernel/mm/transparent_hugepage/defrag
开始创建集群
[root@mongodb-master ~]# mongo 192.168.1.213:27017  #登录到MongoDB
> use admin
> config={ _id:"rj_bai", members:[ {_id:0,host:'192.168.1.213:27017',priority:2}, {_id:1,host:'192.168.1.166:27017',priority:1},   
... {_id:2,host:'192.168.1.251:27017',arbiterOnly:true}] };   #创建节点
> rs.initiate(config)    #使配置生效
{ "ok" : 1 } #一定要看到这个1,如果不是1就失败了,检查是不是哪里搞错了

注意,id:的参数一定要与配置文件里的replSet名称一致,config这个名字是可以随意的

全部执行完后,生效可能需要几十秒,使用rs.status()查看信息,图太长了,就不截图了,把输出信息贴出来了

rj_bai:PRIMARY> rs.status()
{
    "set" : "rj_bai",
    "date" : ISODate("2017-08-22T07:31:09.071Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1503387066, 1),
            "t" : NumberLong(1)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1503387066, 1),
            "t" : NumberLong(1)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1503387066, 1),
            "t" : NumberLong(1)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "192.168.1.213:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1488,
            "optime" : {
                "ts" : Timestamp(1503387066, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-08-22T07:31:06Z"),
            "electionTime" : Timestamp(1503386564, 1),
            "electionDate" : ISODate("2017-08-22T07:22:44Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "192.168.1.166:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 514,
            "optime" : {
                "ts" : Timestamp(1503387066, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1503387066, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-08-22T07:31:06Z"),
            "optimeDurableDate" : ISODate("2017-08-22T07:31:06Z"),
            "lastHeartbeat" : ISODate("2017-08-22T07:31:09.051Z"),
            "lastHeartbeatRecv" : ISODate("2017-08-22T07:31:07.554Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "192.168.1.213:27017",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "192.168.1.251:27017",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 514,
            "lastHeartbeat" : ISODate("2017-08-22T07:31:09.051Z"),
            "lastHeartbeatRecv" : ISODate("2017-08-22T07:31:06.338Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 1
        }
    ],
    "ok" : 1
}

看上面的信息,PRIMARY代表主节点,SECONDARY代表从节点,ARBITER代表仲裁节点,这是登陆MongoDB的提示符信息会变为你定义的replSet名字:所对应的节点,没做之前集群之前是什么都没有的。看图

同步测试

1.主库写入数据

创建数据库,名为lc

rj_bai:PRIMARY> use lc
switched to db lc
rj_bai:PRIMARY> db
lc
rj_bai:PRIMARY> show dbs
admin  0.000GB
local  0.000GB
rj_bai:PRIMARY>

想看到数据库的列表,使用show dbs命令,MongoDB是默认不显示为空的数据库,需要插入一点数据即可。

rj_bai:PRIMARY> db.lc.insert({"name":"其实,有时候疏远不是讨厌,而是太喜欢又很无奈。"})
WriteResult({ "nInserted" : 1 })
rj_bai:PRIMARY> show dbs
admin  0.000GB
local  0.000GB
lc  0.000GB
rj_bai:PRIMARY> db.lc.find()
{ "_id" : ObjectId("599bf11c27ac749672e148d7"), "name" : "其实,有时候疏远不是讨厌,而是太喜欢又很无奈。" }
2.查询从库

从库查询,但是会抛错,如图。

原因是SECONDARY是不允许读写的,执行一条命令即可解决这个问题。

rj_bai:SECONDARY> rs.slaveOk();

在从库查了一下刚刚添加的数据,存在的,说明同步没问题,下面模拟主库宕了从的会不会自动切换为主的。

切换测试

先看一下现在的情况,主库处于存活状态,查看集群信息如下。

看集群信息在仲裁节点看就可以,现在的情况是这样,要做的是吧192.168.1.213这个节点杀了,然后192.168.1.166会顶上去

现在已经杀掉了,在仲裁节点看一下,显示192.168.1.166已经成为主节点了。

然后在192.168.1.166这个服务器上查插点数据,一会看效果。

rj_bai:PRIMARY> use lc
switched to db lc
rj_bai:PRIMARY> db.lc.find()
{ "_id" : ObjectId("599bf11c27ac749672e148d7"), "name" : "其实,有时候疏远不是讨厌,而是太喜欢又很无奈。" }
rj_bai:PRIMARY> db.lc.insert({"name":"上句话是扯淡的,忽略,忽略,哈哈"})
WriteResult({ "nInserted" : 1 })
rj_bai:PRIMARY> db.lc.find()
{ "_id" : ObjectId("599bf11c27ac749672e148d7"), "name" : "其实,有时候疏远不是讨厌,而是太喜欢又很无奈。" }
{ "_id" : ObjectId("599b8447bb6efb1da54a5393"), "name" : "上句话是扯淡的,忽略,忽略,哈哈" }

试试证明也可以正常读写,最后启动192.168.1.213,会是什么样子。

[root@mongodb-master ~]# mongod -f /usr/local/mongodb/mongod.conf

查看集群信息,主节点已经又变回了192.168.1.213服务器。

而且之前在192.168.1.166上新建的数据也同步过去了。

从中得到了一个结论,当主节点宕了以后,备节点会变为主节点继续提供服务,当指定的主节点恢复后,也就是192.168.1.213服务器,备节点由现在的主节点恢复到之前的备节点状态,而不是继续充当主节点。由于这个是第一次搞,而且只是在本地做测试库用,正常跑了两天多了吧,到目前为止没出现过有什么问题,而且生产环境中也没有实际部署使用过,可能会有坑,暂时就这样吧,有坑了再说吧,哈哈,结束。

最后编辑于: 2018 年 12 月 10 日
返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码