详解MongoDB复制集(主从复制)

简介

复制集(Replica Sets)是额外的数据副本,是跨多个服务器同步数据的过程,复制集提供了冗余并增加了数据可用性,通过复制集可以对硬件故障和中断的服务进行恢复

复制集的优势

  • 让数据更安全
  • 高数据可用性(24*7)
  • 灾难恢复
  • 无停机维护(如备份、索引重建、故障转移)
  • 读缩放(额外的副本读取)
  • 副本集对应程序是透明的

复制集的特点

  • N个节点的群集
  • 任何节点可作为主节点
  • 所有写入操作都在主节点上
  • 自动故障转移
  • 自动恢复

复制集工作原理

详解MongoDB复制集(主从复制)

1.MongoDB的复制集至少需要两个节点。其中一个是主节点(Primary),负责处理客户端的请求,其余的都是从节点(Secondary),负责复制主节点上的数据。

2.MongoDB各个节点常见的搭配方式为:一主一从或一主多从。主节点记录其上的所有操作到oplog中,从节点定期轮询主节点获取的这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致

3.如上图可以看出,客户端在主节点写入数据,才从节点读取数据,主节点与从节点进行数据交互保障数据的一致性。如果其中一个节点出现故障,其他节点马上会将业务接过来而无需停机操作

一、安装MongoDB

1、自定义yum源文件

[root@redhat7_6 ~]# cd /etc/yum.repos.d/
[root@redhat7_6 yum.repos.d]# mkdir bak
[root@redhat7_6 yum.repos.d]# mv CentOS-* bak/
[root@redhat7_6 yum.repos.d]# vim local.repo

[mongodb-org]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

2、安装MongoDB

[root@redhat7_6 ~]# yum -y install mongodb-org
[root@redhat7_6 ~]# yum clean all #清除yum缓存
[root@redhat7_6 ~]# yum list #重新加载源

二、配置复制集

1、创建实例相关文件

[root@redhat7_6 ~]# mkdir -p /data/mongodb/mongodb{1,2,3,4} #创建数据目录
[root@redhat7_6 ~]# mkdir -p /data/logs/mongodb #创建日志目录
[root@redhat7_6 ~]# cd /data/logs/mongodb/
[root@redhat7_6 mongodb]# touch mongodb{1,2,3,4}.log #创建日志文件
[root@redhat7_6 mongodb]# chmod 777 *.log #修改目录权限

2、编辑实例1配置文件

[root@redhat7_6 ~]# cp -p /etc/mongod.conf /etc/mongod1.conf
[root@redhat7_6 ~]# vim /etc/mongod1.conf #修改配置文件

path: /data/logs/mongodb/mongodb1.log  #约第10行,编辑日志文件路径,对应其他的实例依次往下……
dbPath: /data/mongodb/mongodb1/        #编辑数据目录文件路径,也是一样对应其他的实例依次往下……
net:                                   #约28行,指定网络接口
  port: 27017                          #编辑端口号,实例1为27017,实例2为27018,依次往下排……
  bindIp: 0.0.0.0
replication:                           #约37行,打开复制选项注释,四台实例都要添加
  replSetName: kgcrs                   #指定复制集名称

3、编辑其他实例配置文件

[root@redhat7_6 ~]# cp -p /etc/mongod1.conf /etc/mongod2.conf #创建其他三个MongoDB实例配置文件
[root@redhat7_6 ~]# cp -p /etc/mongod1.conf /etc/mongod3.conf
[root@redhat7_6 ~]# cp -p /etc/mongod1.conf /etc/mongod4.conf
[root@redhat7_6 ~]# rm -rf /etc/mongod.conf

4、编写启动脚本

[root@redhat7_6 ~]# vim /etc/init.d/mongodb

#!/bin/bash
# descript:Mongodb Server Control Script
# Author: GuiHaiYiDao TEL:139741741741
# date:long long ago
instance=$1
action=$2
case "$action" in
        'start')
                /usr/bin/mongod -f /etc/"$instance".conf
        ;;
        'stop')
                /usr/bin/mongod -f /etc/"$instance".conf --shutdown
        ;;
        'restart')
                /usr/bin/mongod -f /etc/"$instance".conf --shutdown
                /usr/bin/mongod -f /etc/"$instance".conf
        ;;
esac

[root@redhat7_6 ~]# chmod +x /etc/init.d/mongodb

[root@redhat7_6 ~]# /etc/init.d/mongodb mongod1 start
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod2 start
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod3 start
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod4 start

[root@redhat7_6 ~]# netstat -anpt | grep 'mongod'
详解MongoDB复制集(主从复制)

5、初始化配置复制集

[root@redhat7_6 ~]# mongo --port 27017 #进入第一个实例

> rs.status()  #查看复制集的状态信息
{
    "info" : "run rs.initiate(...) if not yet done for the set",
    "ok" : 0,
    "errmsg" : "no replset config has been received", #此参数指定没有接收到复制集配置
    "code" : 94,
    "codeName" : "NotYetInitialized"
}
> cfg={"_id":"kgcrs","members":[{"_id":0,"host":"192.168.100.76:27017"},{"_id":1,"host":"192.168.100.76:27018"},{"_id":2,"host":"192.168.100.76:27019"}]}  #cfg定义变量作为初始化参数;kgcrs定义复制集名称;members定义节点成员
{
    "_id" : "kgcrs",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.100.71:27017"
        },
        {
            "_id" : 1,
            "host" : "192.168.100.72:27018"
        },
        {
            "_id" : 2,
            "host" : "192.168.100.73:27019"
        }
    ]
}
> rs.initiate(cfg)  #初始化复制集
{
    "ok" : 1,
    "operationTime" : Timestamp(1536499691, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1536499691, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
kgcrs:SECONDARY> rs.status() #再次查看复制集状态信息
{
    "set" : "kgcrs",   #复制集群集名称
    "date" : ISODate("2018-09-09T13:29:34.203Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "syncingTo" : "",
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1536499764, 1),
            "t" : NumberLong(1)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1536499764, 1),
            "t" : NumberLong(1)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1536499764, 1),
            "t" : NumberLong(1)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1536499764, 1),
            "t" : NumberLong(1)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "192.168.100.76:27017", #复制集成ip以及端口号
            "health" : 1,                                     #健康状况,1代表健康;0代表宕机
            "state" : 1,                                       #1代表主节点;2代表从节点
            "stateStr" : "PRIMARY",                  #PRIMARY代表主节点;SECONDARY代表从节点
            "uptime" : 172,
            "optime" : {
                "ts" : Timestamp(1536499764, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2018-09-09T13:29:24Z"),
            "syncingTo" : "",
            "syncSourceHost" : "",
            "syncSourceId" : -1,
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1536499703, 1),
            "electionDate" : ISODate("2018-09-09T13:28:23Z"),
            "configVersion" : 1,
            "self" : true,
            "lastHeartbeatMessage" : ""
        },
        {
            "_id" : 1,
            "name" : "192.168.100.76:27018",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 82,
            "optime" : {
                "ts" : Timestamp(1536499764, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1536499764, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2018-09-09T13:29:24Z"),
            "optimeDurableDate" : ISODate("2018-09-09T13:29:24Z"),
            "lastHeartbeat" : ISODate("2018-09-09T13:29:33.324Z"),
            "lastHeartbeatRecv" : ISODate("2018-09-09T13:29:32.404Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "192.168.100.76:27017",
            "syncSourceHost" : "192.168.100.76:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "192.168.100.76:27019",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 82,
            "optime" : {
                "ts" : Timestamp(1536499764, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1536499764, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2018-09-09T13:29:24Z"),
            "optimeDurableDate" : ISODate("2018-09-09T13:29:24Z"),
            "lastHeartbeat" : ISODate("2018-09-09T13:29:33.324Z"),
            "lastHeartbeatRecv" : ISODate("2018-09-09T13:29:32.383Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "192.168.100.76:27017",
            "syncSourceHost" : "192.168.100.76:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1536499764, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1536499764, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}

6、增加节点

kgcrs:PRIMARY> rs.add("192.168.100.76:27020")  #增加节点
{
    "ok" : 1,
    "operationTime" : Timestamp(1536500454, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1536500454, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
kgcrs:PRIMARY> rs.status() #再次查看复制集状态信息

详解MongoDB复制集(主从复制)

7、删除节点

kgcrs:PRIMARY> rs.remove("192.168.100.76:27020")  #删除节点
kgcrs:PRIMARY> rs.status() #再次查看
kgcrs:PRIMARY> exit

三、复制集切换

1、模拟故障自动转移

[root@redhat7_6 ~]# ps aux | grep mongod | grep -v grep
详解MongoDB复制集(主从复制)

[root@redhat7_6 ~]# kill -9 10706

[root@redhat7_6 ~]# mongo --port 27018

kgcrs:PRIMARY> rs.status() #查看复制状态

详解MongoDB复制集(主从复制)

2、手动进行主从切换

kgcrs:PRIMARY> exit
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod1 start #再次启动实例1

[root@redhat7_6 ~]# mongo --port 27018 #此时主节点是在第二台实例中

kgcrs:PRIMARY> rs.status()

详解MongoDB复制集(主从复制)

kgcrs:PRIMARY> rs.freeze(30)                  #暂停30秒不参加选举
kgcrs:PRIMARY> rs.stepDown(60,30)       #告知主节点交出主节点位置,然后维持从节点状态不少于60秒,同时等待30秒以使主节点和从节点日志同步
kgcrs:SECONDARY> rs.status()

详解MongoDB复制集(主从复制)

四、测试复制集同步

1、主节点添加测试数据

[root@redhat7_6 ~]# mongo --port 27017

kgcrs:PRIMARY> use supermarket
kgcrs:PRIMARY> for(var i=0;i<=100;i++)db.product.insert({"id":1,"pname":"Audi"+i})

2、手动进行主从切换

kgcrs:PRIMARY> rs.freeze(30)
kgcrs:PRIMARY> rs.stepDown(60,30) 
kgcrs:SECONDARY> rs.status()

详解MongoDB复制集(主从复制)

3、登录第二个实例服务器

[root@redhat7_6 ~]# mongo --port 27017

kgcrs:PRIMARY> use supermarket
kgcrs:PRIMARY> db.product.find()

详解MongoDB复制集(主从复制)

猜你喜欢

转载自blog.51cto.com/11905606/2174286