MongoDB 3.4 - 复制集、鉴权、主从同步以及读写分离

许久没更新了。带来centos7下MongoDB3.4的复制集、鉴权、主从同步和读写分离方案。
转载请注明出处:http://blog.lzoro.com

BiuBiu

老惯例之碎碎念。
厦门的夏天又来了,热得整个人都没脾气了。
最近忙得连轴转,博客也停了很久,空闲下来还是要继续写的。

环境

一台装有vsphere6.5的宿主机,和宿主机上的centos7三台。

1
2
3
4
5
6
7
1、vsphere 6.5
2、centos 7 X 3
192.168.1.207(master)
192.168.1.245(secodary)
192.168.1.249(arbiter)
3、MongoDB 3.4
4、Java SSM 结构的应用

安装MongoDB

1、这里采用的是yum源的方式安装,所以需要先添加yum源
1
vim /etc/yum.repos.d/mongodb-org-3.4.repo
2、输入以下内容并保存,如果yum源无效,请百度新的yum源。
1
2
3
4
5
6
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=0
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.2.asc
3、执行安装
1
yum install -y mongodb-org

安装成功的提示

4、修改配置(yaml格式),如有需要可以对配置文件的标注的[1][2][3][4]点进行修改。
1
vim /etc/mongod.conf

下面为配置文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# mongod.conf

# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
destination: file
logAppend: true
# [1]日志存储路径
path: /var/log/mongodb/mongod.log

# Where and how to store data.
storage:
# [2]数据存储路径
dbPath: /var/lib/mongo
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger:

# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile

# network interfaces
net:
# [3]端口,默认为27017,可修改为其他
port: 27017
# [4]如果需要对外提供访问,请把该下面那行注释掉
bindIp: 127.0.0.1 # Listen to local interface only, comment to listen on all interfaces.


#security:

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:

#####5、分别在三台服务器上执行上述三个安装操作

配置鉴权、复制集并启动

1、从三台MongoDB中选择一台作为master,我这里是192.168.1.207,启动并创建管理员,方便开启鉴权后的操作

启动

1
mongod -f /etc/mongod.conf

连接

1
mongo --port=27017

创建账号

1
2
3
use admin;

db.createUser({user:"dba",pwd:"yourpassword",roles:[{role:"root",db:"admin"},{role:"userAdminAnyDatabase",db:"admin"}]});

2、主从间的同步需要安全机制,所以需要先生成秘钥,yourKeyFile为秘钥文件名称,可以自定义
1
openssl rand -base64 753 > yourKeyFile
3、将yourKeyFile放到MongoDB的数据存储路径下,也就是上面配置文件中的dbPath,上面的例子为/var/lib/mongo,并授权,注意你的秘钥存放路径。
1
chmod 600 yourKeyFile
4、拷贝yourKeyFile分别放到其他两台mongo服务器的数据存储路径下,也需要上面的600授权。
5、配置复制集和鉴权,还是上面的配置文件,yaml节点为securityreplication,三台机器都需要配置。
1
2
3
4
5
6
7
8
9
10
security:
# 启用鉴权
authorization: enabled
# 你的keyFile存放路径
keyFile: /var/lib/mongo/yourKeyfile
replication:
# oplogSize的大小,单位为M,建议空闲磁盘的5%
oplogSizeMB: 1024
# 复制集的名称,需要记住
replSetName: myReplSet
6、分别重启MongoDB服务,并进入master(192.168.1.207)

确认服务器的防火墙是否开放了相应的端口27017,如未开放,先开放

1
2
firewall-cmd --zone=public --add-port=27017/tcp --permanent
systemctl reload firewalld.service

若关闭Mongo时出现There doesn't seem to be a server running with dbpath: /data/db提示,则需指定数据库路径来关闭

1
mongod --shutdown --dbpaht=/var/lib/mongo

连接后,由于开启了鉴权,所以需要认证

1
2
3
4
5
6
# 连接
mongo --port=27017
# 使用admin
use admin;
# 鉴权
db.auth('dba','yourpassword');

输入配置,这里的第一个_id需要和配置里面的replSetName一致

1
2
3
4
5
6
7
8
9
10
myReplSet_conf={
_id: "myReplSet",
members: [{
_id: 0,
host: "192.168.1.207:27017"
}, {
id: 1,
host: "192.168.1.245:27017"
}]
};

初始化

1
rs.initiate(myReplSet_conf);

若出现{ "ok" : 1}则表示配置成功,退出再重启则可以看到PRIMARY标识,在192.168.1.245登录,则看到的是SECONDARY

测试主从同步情况

登录主库(192.168.1.207),创建数据库,并创建用户,然后插入数据

1
2
3
4
5
6
7
8
9
10
11
12
# 连接
mongo --port=27017
# 使用admin
use admin;
# 鉴权
db.auth('dba','yourpassword');
# 创建数据库
use test;
# 创建用户
db.createUser({user:"testdba",pwd:"testpassword",roles:[{role:"dbOwner",db:"test"}]});
# 插入数据
db.testCol.insert({id:1,name:'zoro'});

登录从库(192.168.1.245),查询是否有主库插入的数据

1
2
3
4
5
6
7
8
9
10
# 连接
mongo --port=27017
# 使用test
use test;
# 鉴权
db.auth('testdba','testpassword');
# 允许读
rs.slaveOk();
# 查询
db.testCol.find();

如果有数据,则证明同步成功

实现master自动切换

MongoDB的复制集是有mater自动切换机制的,当集群中的master出现问题的时候,会由剩下的机器进行投票重新选举出master,但是,如果剩余活跃的机器是偶数个的话,比如现在只有两台/或一台,那将有可能陷入僵持,导致投票失败而没有master出现,这个时候,就需要配置一台MongoDB,作为仲裁角色加入集群(不做数据存储,只做为投票)。

1、启动最后一台mongo服务(192.168.1.249)
1
mongod -f /etc/mongod.conf
2、在主机上配置仲裁角色
1
2
3
4
5
6
7
8
# 连接
mongo --port=27017
# 使用admin
use admin;
# 鉴权
db.auth('dba','yourpassword');
# 加入仲裁角色
rs.addArb("192.168.1.249:27017");
3、查看复制集状态,以下为正常状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
{
"set" : "myReplSet",
"date" : ISODate("2018-05-25T09:46:12.137Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1527241561, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1527241561, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1527241561, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.1.207:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1403,
"optime" : {
"ts" : Timestamp(1527241561, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-25T09:46:01Z"),
"electionTime" : Timestamp(1527240420, 1),
"electionDate" : ISODate("2018-05-25T09:27:00Z"),
"configVersion" : 2,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.1.245:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1162,
"optime" : {
"ts" : Timestamp(1527241561, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1527241561, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-25T09:46:01Z"),
"optimeDurableDate" : ISODate("2018-05-25T09:46:01Z"),
"lastHeartbeat" : ISODate("2018-05-25T09:46:11.898Z"),
"lastHeartbeatRecv" : ISODate("2018-05-25T09:46:11.913Z"),
"pingMs" : NumberLong(0),
"configVersion" : 2
},
{
"_id" : 2,
"name" : "192.168.1.249:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 10,
"lastHeartbeat" : ISODate("2018-05-25T09:46:11.898Z"),
"lastHeartbeatRecv" : ISODate("2018-05-25T09:46:11.930Z"),
"pingMs" : NumberLong(0),
"configVersion" : 2
}
],
"ok" : 1
}
测试是否能够自动切换master

先关闭master服务,然后进入原先secondary的服务,查看是否被提升成master,如果是,则测试成功。

注:切换会有延迟,示网络情况而定

SSM应用中配置读写分离

格子这边的应用是用java语言,基于SringMVC + Mybatis + mongoTemplate等框架的,下面说一下在这个框架下,如何配置MongoDB的读写分离。

配置文件,省略了其他,只列出mongo的关键配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">


...

<!--mongo factory-->
<mongo:db-factory id="mongoDbFactory" mongo-ref="mongoClient" dbname="${mongodb.database}"/>
<!--mongo client config-->
<mongo:mongo-client id="mongoClient" replica-set="${mongodb.host}:${mongodb.port}"
credentials="${mongodb.username}:${mongodb.password}@${mongodb.database}">
<mongo:client-options
connections-per-host="100"
threads-allowed-to-block-for-connection-multiplier="10"
connect-timeout="10000"
max-wait-time="10000"
socket-keep-alive="true"
read-preference="SECONDARY_PREFERRED"
/>
</mongo:mongo-client>

...

配置后开启MongoDB的日志,然后启动项目,并执行MongoDB响应的写入和读取操作,观察日志打印,就可以验证读写分离是否成功,是不是很简单呢。Spring家的东西还是蛮强大的。

写在最后

如果对你有帮助,帮格子点个赞呗。
溜了溜了。

分享到