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

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

BiuBiu

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

环境

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

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源
vim /etc/yum.repos.d/mongodb-org-3.4.repo
2、输入以下内容并保存,如果yum源无效,请百度新的yum源。
[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、执行安装
yum install -y mongodb-org

《MongoDB 3.4 - 复制集、鉴权、主从同步以及读写分离》 安装成功的提示

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

下面为配置文件内容

# 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,启动并创建管理员,方便开启鉴权后的操作

启动

mongod -f /etc/mongod.conf

连接

mongo --port=27017

创建账号

use admin;

db.createUser({user:"dba",pwd:"yourpassword",roles:[{role:"root",db:"admin"},{role:"userAdminAnyDatabase",db:"admin"}]});
2、主从间的同步需要安全机制,所以需要先生成秘钥,yourKeyFile为秘钥文件名称,可以自定义
openssl rand -base64 753 > yourKeyFile 
3、将yourKeyFile放到MongoDB的数据存储路径下,也就是上面配置文件中的dbPath,上面的例子为/var/lib/mongo,并授权,注意你的秘钥存放路径。
chmod 600 yourKeyFile
4、拷贝yourKeyFile分别放到其他两台mongo服务器的数据存储路径下,也需要上面的600授权。
5、配置复制集和鉴权,还是上面的配置文件,yaml节点为securityreplication,三台机器都需要配置。
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,如未开放,先开放

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提示,则需指定数据库路径来关闭

mongod --shutdown --dbpath=/var/lib/mongo

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

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

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

myReplSet_conf={
    _id: "myReplSet",
    members: [{
        _id: 0,
        host: "192.168.1.207:27017"
    }, {
        id: 1,
        host: "192.168.1.245:27017"
    }]
};

初始化

rs.initiate(myReplSet_conf);

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

测试主从同步情况

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

# 连接
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),查询是否有主库插入的数据

# 连接
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)
mongod -f /etc/mongod.conf
2、在主机上配置仲裁角色
# 连接
mongo --port=27017
# 使用admin
use admin;
# 鉴权
db.auth('dba','yourpassword');
# 加入仲裁角色
rs.addArb("192.168.1.249:27017");
3、查看复制集状态,以下为正常状态
{
    "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的关键配置

<?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家的东西还是蛮强大的。

写在最后

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

    原文作者:格子Lin
    原文地址: https://www.jianshu.com/p/675f4712bf3a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞