第二节:MongoDB复制集(主从复制)剖析和快速上手搭建

一. 复制集剖析

1. 什么是复制集

  复制集(replica set)提供了数据冗余和高可用,它是一组mongod进程,它的作用如下:

  保障数据的安全性

  数据高可用性 (24*7)

  灾难恢复

  无需停机维护(如备份,重建索引,压缩)

  分布式读取数据

  副本集对应用层是透明的

  一个复制集里面有很多数据节点(data bearing node)和一个可选择的仲裁节点(arbiter node)。数据节点的角色也分为主节点(primary node)从节点(secondary node)。所有写操作都是在主节点上的,并记录oplog(operation log)。从节点通过主节点的oplog重放来保持数据的最终一致性,这个“主从复制”是异步的。当主节点挂了,二级节点会进行新的选举(基于Raft算法),从中找一个二级节点来充当主节点的角色。仲裁节点只负责参与选举,而不存储数据。

 

2.  架构图

  MongoDB推荐的最小架构是:一个主节点,两个从节点,最大可以有50个成员节点。

读写分离架构:

 

 

 

二. 快速搭建

目标:

  搭建1主2从的复制集 集群,主节点(Primary)端口为:27018,从节点(Secondary)端口为:27019、27020.

       完成主从数据的复制

       完成主节点宕机,从节点自动选举为主节点的

 

1. 准备3个配置文件

(1). 事先创建相关路径

  A.  配置文件路径: D:\Program Files\MongoDB\Server\5.0\bin\CopyConf

  B.  日志路径: D:\Program Files\MongoDB\Server\5.0\myCopy_log

  C.  数据路径:D:\Program Files\MongoDB\Server\5.0\myCopy_data

(2). 修改数据存储路径 (以27018端口为例)

storage:
  dbPath: D:\Program Files\MongoDB\Server\5.0\myCopy_data\27018
  journal:
    enabled: true

(3). 修改日志存储路径

systemLog:
  destination: file
  logAppend: true
  path:  D:\Program Files\MongoDB\Server\5.0\myCopy_log\27018\mongod.log

(4). 修改端口

net:
  port: 27018
  bindIp: 127.0.0.1

(5). 开启复制集合

#开启复制集(名字为:ypfCopy)
replication:
   replSetName: ypfCopy

27018配置文件

# mongod.conf

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

# Where and how to store data.
storage:
  dbPath: D:\Program Files\MongoDB\Server\5.0\myCopy_data\27018
  journal:
    enabled: true
#  engine:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path:  D:\Program Files\MongoDB\Server\5.0\myCopy_log\27018\mongod.log

# network interfaces
net:
  port: 27018
  bindIp: 127.0.0.1


#processManagement:

#security:

#operationProfiling:


#开启复制集(名字为:ypfCopy)
replication:
   replSetName: ypfCopy

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:
View Code

27019配置文件

# mongod.conf

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

# Where and how to store data.
storage:
  dbPath: D:\Program Files\MongoDB\Server\5.0\myCopy_data\27019
  journal:
    enabled: true
#  engine:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path:  D:\Program Files\MongoDB\Server\5.0\myCopy_log\27019\mongod.log

# network interfaces
net:
  port: 27019
  bindIp: 127.0.0.1


#processManagement:

#security:

#operationProfiling:


#开启复制集(名字为:ypfCopy)
replication:
   replSetName: ypfCopy

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:
View Code

27020配置文件

# mongod.conf

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

# Where and how to store data.
storage:
  dbPath: D:\Program Files\MongoDB\Server\5.0\myCopy_data\27020
  journal:
    enabled: true
#  engine:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path:  D:\Program Files\MongoDB\Server\5.0\myCopy_log\27020\mongod.log

# network interfaces
net:
  port: 27020
  bindIp: 127.0.0.1


#processManagement:

#security:

#operationProfiling:


#开启复制集(名字为:ypfCopy)
replication:
   replSetName: ypfCopy

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:
View Code

 

2. 启动三个实例

在cmd中依次启动项下面三个实例:

【mongod.exe –config "D:\Program Files\MongoDB\Server\5.0\bin\CopyConf\mongod-27018.cfg"】

【mongod.exe –config "D:\Program Files\MongoDB\Server\5.0\bin\CopyConf\mongod-27019.cfg"】

【mongod.exe –config "D:\Program Files\MongoDB\Server\5.0\bin\CopyConf\mongod-27020.cfg"】

 

3.  设置主从节点

(1). 先通过指令连接到27018节点

【 mongo.exe –host 127.0.0.1 –port 27018

(2).  将连接到的当前节点(27018)初始化为主节点(Primary)

【rs.initiate()】

查看主节点状态:【rs.status()】, 从而切换到主节点

(3).  添加从节点27019

【  rs.add("127.0.0.1:27019")  】

(4). 添加从节点27020 

【  rs.add("127.0.0.1:27020")  】

(5). 查看状态

【rs.status()】

{
        "set" : "ypfCopy",
        "date" : ISODate("2022-08-29T09:33:48.857Z"),
        "myState" : 1,
        "term" : NumberLong(1),
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "heartbeatIntervalMillis" : NumberLong(2000),
        "majorityVoteCount" : 2,
        "writeMajorityCount" : 2,
        "votingMembersCount" : 3,
        "writableVotingMembersCount" : 3,
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1661765620, 1),
                        "t" : NumberLong(1)
                },
                "lastCommittedWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                "readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1661765620, 1),
                        "t" : NumberLong(1)
                },
                "appliedOpTime" : {
                        "ts" : Timestamp(1661765620, 1),
                        "t" : NumberLong(1)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1661765620, 1),
                        "t" : NumberLong(1)
                },
                "lastAppliedWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                "lastDurableWallTime" : ISODate("2022-08-29T09:33:40.074Z")
        },
        "lastStableRecoveryTimestamp" : Timestamp(1661765575, 1),
        "electionCandidateMetrics" : {
                "lastElectionReason" : "electionTimeout",
                "lastElectionDate" : ISODate("2022-08-29T09:27:59.979Z"),
                "electionTerm" : NumberLong(1),
                "lastCommittedOpTimeAtElection" : {
                        "ts" : Timestamp(1661765279, 1),
                        "t" : NumberLong(-1)
                },
                "lastSeenOpTimeAtElection" : {
                        "ts" : Timestamp(1661765279, 1),
                        "t" : NumberLong(-1)
                },
                "numVotesNeeded" : 1,
                "priorityAtElection" : 1,
                "electionTimeoutMillis" : NumberLong(10000),
                "newTermStartDate" : ISODate("2022-08-29T09:27:59.997Z"),
                "wMajorityWriteAvailabilityDate" : ISODate("2022-08-29T09:28:00.048Z")
        },
        "members" : [
                {
                        "_id" : 0,
                        "name" : "127.0.0.1:27018",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 832,
                        "optime" : {
                                "ts" : Timestamp(1661765620, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2022-08-29T09:33:40Z"),
                        "lastAppliedWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                        "lastDurableWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "electionTime" : Timestamp(1661765279, 2),
                        "electionDate" : ISODate("2022-08-29T09:27:59Z"),
                        "configVersion" : 5,
                        "configTerm" : 1,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                },
                {
                        "_id" : 1,
                        "name" : "127.0.0.1:27019",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 71,
                        "optime" : {
                                "ts" : Timestamp(1661765620, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDurable" : {
                                "ts" : Timestamp(1661765620, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2022-08-29T09:33:40Z"),
                        "optimeDurableDate" : ISODate("2022-08-29T09:33:40Z"),
                        "lastAppliedWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                        "lastDurableWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                        "lastHeartbeat" : ISODate("2022-08-29T09:33:47.060Z"),
                        "lastHeartbeatRecv" : ISODate("2022-08-29T09:33:47.062Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "",
                        "syncSourceHost" : "127.0.0.1:27018",
                        "syncSourceId" : 0,
                        "infoMessage" : "",
                        "configVersion" : 5,
                        "configTerm" : 1
                },
                {
                        "_id" : 2,
                        "name" : "127.0.0.1:27020",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 53,
                        "optime" : {
                                "ts" : Timestamp(1661765620, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDurable" : {
                                "ts" : Timestamp(1661765620, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2022-08-29T09:33:40Z"),
                        "optimeDurableDate" : ISODate("2022-08-29T09:33:40Z"),
                        "lastAppliedWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                        "lastDurableWallTime" : ISODate("2022-08-29T09:33:40.074Z"),
                        "lastHeartbeat" : ISODate("2022-08-29T09:33:47.060Z"),
                        "lastHeartbeatRecv" : ISODate("2022-08-29T09:33:47.570Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "",
                        "syncSourceHost" : "127.0.0.1:27019",
                        "syncSourceId" : 1,
                        "infoMessage" : "",
                        "configVersion" : 5,
                        "configTerm" : 1
                }
        ],
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1661765620, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1661765620, 1)
}
View Code

注: 

    截止此处一主两从的集群就已经搭建完毕了,下次直接开启上述三个实例,该主从关系依旧存在,不需要重新搭建了。

 

4.  使用Compass客户端进行链接

(1). 连接字符串为

mongodb://localhost:27018,localhost:27019,localhost:27020/?readPreference=primary&appname=MongoDB%20Compass&ssl=false

(2). 连接成功,如下图:

 

5.  代码实操测试

(1).  连接集群

  public HomeController()
  {
            // 1. 建立MongoDB连接
            //var client = new MongoClient("mongodb://localhost:27017");     //单个节点

            var client = new MongoClient("mongodb://localhost:27018,localhost:27019,localhost:27020");      //复制集- 1主2从  【正常使用】
      
            // 2. 获取数据库ShipDB 【若没有,则自动创建,插入数据的时候才生效】
            var database = client.GetDatabase("ShipDB");
            // 3. 获取表 ShipInfo【若没有,则自动创建,插入数据的时候才生效】
            shipService = database.GetCollection<ShipInfo>("ShipInfo");
   }

说明:

  如上代码,就可以实现连接到复制集集群上。

(2). 测试能否只连接主节点

   经测试,单独连接到主节点(Primary) 27018 上,可以正常进行crud。

 

(3). 测试能否直连接从节点

   经测试,从节点(Secondary) 27019、27020,不允许进行单独连接。

 

6. 测试主节点宕机,从节点选举

    主节点27018宕机, 从节点27019会被选举为主节点。

 

结论:默认只能主节点读写,从节点不能读也不能写!! 当执行指令 secondaryOk(),执行后,从节点可以读了。【正确!!!】

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2022-08-29 16:03  Yaopengfei  阅读(909)  评论(1编辑  收藏  举报