分布式文档存储数据库之MongoDB副本集

  前文我们聊到了mongodb的索引的相关作用和介绍以及索引的管理,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13950287.html;今天我们来聊下mongodb的副本集;

  1、什么是副本集?主要作用是什么?它是怎么工作的呢?

  所谓副本集是指服务于同一数据集的多个mongodb实例;这意味着在mongodb中数据集副本的数量可以是多个,每个副本的数据都是一样的;副本的存在主要作用是对mongodb数据库中的数据做冗余备份和提高数据服务的可用性;在mongodb中对数据做冗余的方式有两种,一种是主从架构(master/slave),这种架构和mysql中的主从架构没有什么不同,但是在mongodb中,主从架构的方式几乎没有人用,处于废弃的状态。。另外一种是副本集(replica set),副本集本质上也是主从架构的一种,它和我们刚才说的主从架构,有一个显著的区别,副本集支持故障自动转移,不需要人工手动干预;所谓的故障自动转移是指当一个副本集中主节点因各种原因宕机或者从节点在一定时间内没有收到主节点发送到心跳信息,此时就会触发从节点重新选举主节点的操作;在多个从节点中选举出来一个主节点以后,其他从节点能够自动指向新选举的主节点同步数据,从而完成这次故障转移;

  2、mongodb副本集架构

  提示:对于mongodb中的副本集来说,为了保证数据的一致性,一个副本集中只能有一个主节点,并且只有主节点才拥有读写权限,其他从节点都只有读权限;在mongodb的副本集中,主节点我们叫做primary,从节点叫做secondary;

  3、副本集是通过什么来复制数据的呢?

  我知道mysql的主从复制是通过主节点记录写操作到binlog中,从节点通过同步主节点的binlog,然后把同步的binlog在本地进行重放,从而实现数据同步;在mongodb中也是类似的操作,不同的是在mongodb中主节点将写操作记录到oplog(操作日志),各从节点通过复制主节点的oplog,在本地重放实现数据同步;oplog的作用和mysql中的binlog的作用很类似,都是用来记录写操作事件,都是用来同步数据;mongodb中的oplog是一个定容集合,所谓定容是指它的大小是固定的,它不会像binlog随日志的增多而逐渐变大;通常oplog我们不人为指定其大小,默认就是占用所在文件系统空闲磁盘的5%;除了大小是不变的,它还有一个幂等的特点;所谓幂等就是不管在monogdb中执行多少次oplog中的操作,其最终的结果都是一样的;如果写操作日志把oplog写满了,它会从头覆盖之前的oplog,依次循环写oplog;

  4、副本集是怎么完成故障转移的?

  在前边我们聊zookeeper时,聊到过分布式场景中的选举过程;mongodb的主节点故障以后,也是通过这种机制来完成选举;在mongodb的副本集中,主节点每隔两秒向各从节点发送心跳信息,各从节点通过检测主节点的心跳信息来判定主节点是否存活;如果在一定的时间范围内,从节点没有收到主节点发送到心跳信息,此时从节点会认为主节点挂了,从而触发主节点选举的操作;这个选举和zookeeper里的选举很类似,通常情况都是大于集群总票的一半一方可以代表集群正常工作;所以通常情况mongodb副本集都是基数个节点组成;当然mongodb中也可以是偶数节点(正常提供服务的节点),如果是偶数节点,通常会借助一个仲裁节点来完成选举;仲裁节点拥有选票,但不被选举成为主节点,也不拥有副本数据,同时它必须要能够检测主节点心跳;简单总结就是mongodb副本集是通过从节点检测主节点心跳来判断主节点是否存活,如果在一定时间范围内,没有检测到主节点的心跳信息,此时就会触发主节点选举操作,如果集群节点数量为偶数个,通常会借助仲裁节点来完成选举;从而实现完成故障自动转移;

  5、mongodb副本集中特殊类型节点分类

  0优先级节点:这种节点的特点是优先级为0,可参与选举,拥有副本数据,但不被选举成为主节点,可读不可写;这种节点我们也叫冷备节点;通常用于异地容灾使用;

  被隐藏的从节点:这种节点的特点是,可参与选举,拥有副本数据,但不被选举成为主节点,对客户端不可读写也不可见;通常用于同步同一副本集中的其他节点的不同工作流的场景中;

  延迟复制的从节点:这种节点的特点是,副本数据落后主节点一个时间窗口,也就说这种节点上的副本数据总是过期的;除此它可参与选举,不可被选举为主节点;主要用于特殊功用;比如在主节点上执行了一个删除操作,我们可以在延迟复制的从节点上把数据找回;

  arbiter节点:这种就是我们说的仲裁节点,它可参与选举,不拥有副本数据,不被选举成为主节点,不可读写;主要作用是辅助判定主节点是否存活,辅助从节点完成选举,实现故障转移;

  6、创建mongodb的副本集合

  环境准备

主机名 ip地址
node01 192.168.0.41
node02 192.168.0.42
node03 192.168.0.43

 

 

 

 

 

 

  在三个节点上分别做好时间同步,关闭selinux,关闭防火墙,主机名解析,有必要还可以做ssh互信。准备好基础环境以后,在三台server上配置mongodb的yum源

[root@node01 ~]# cat /etc/yum.repos.d/mongodb.repo 
[mongodb-org]
name = MongoDB Repository
baseurl = https://mirrors.aliyun.com/mongodb/yum/redhat/7/mongodb-org/4.4/x86_64/
gpgcheck = 1
enabled = 1
gpgkey = https://www.mongodb.org/static/pgp/server-4.4.asc
[root@node01 ~]# scp /etc/yum.repos.d/mongodb.repo node02:/etc/yum.repos.d/
mongodb.repo                                                                  100%  206    80.4KB/s   00:00    
[root@node01 ~]# scp /etc/yum.repos.d/mongodb.repo node03:/etc/yum.repos.d/
mongodb.repo                                                                  100%  206    88.9KB/s   00:00    
[root@node01 ~]# 

  安装mongodb-org

yum install -y mongodb-org

  准备数据目录和存放日志的目录,并将其属主和属组更改为mongod用户

[root@node01 ~]# mkdir -pv /mongodb/{data,log} 
mkdir: created directory ‘/mongodb’
mkdir: created directory ‘/mongodb/data’
mkdir: created directory ‘/mongodb/log’
[root@node01 ~]# chown -R mongod.mongod /mongodb/
[root@node01 ~]# ll -d /mongodb/
drwxr-xr-x 4 mongod mongod 29 Nov 10 19:36 /mongodb/
[root@node01 ~]# 

  提示:以上需在三个节点都要做一遍;

  配置mongodb

  提示:主要配置replication,其中oplogSizeMB用来指定oplog的大小,默认不指定,其大小就是所在文件系统空闲磁盘的%5;replSetName用来指定副本集的名称,这个名称非常重要,主要用来标识不同副本集;enableMajorityReadConcern用来指定是否开启mongodb周期性的做快照,并记录oplog的时间戳;

  完整配置

[root@node01 ~]# cat /etc/mongod.conf
systemLog:
  destination: file
  logAppend: true
  path: /mongodb/log/mongod.log

storage:
  dbPath: /mongodb/data/
  journal:
    enabled: 

processManagement:
  fork:   
  pidFilePath: /var/run/mongodb/mongod.pid
  timeZoneInfo: /usr/share/zoneinfo

net:
  port: 27017
  bindIp: 0.0.0.0

replication:
   oplogSizeMB: 2048
   replSetName: test_replset
   enableMajorityReadConcern: false



#security:

#operationProfiling:

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:
[root@node01 ~]# 
View Code

  复制配置文件到node02,node03

[root@node01 ~]# scp /etc/mongod.conf node02:/etc/
mongod.conf                                                                   100%  494   315.1KB/s   00:00    
[root@node01 ~]# scp /etc/mongod.conf node03:/etc/
mongod.conf                                                                   100%  494   351.6KB/s   00:00    
[root@node01 ~]# 

  启动服务

  提示:请确保对应节点上的mongodb所监听的端口正常即可;

  连接三个节点任意一个节点查看副本集状态

> rs.help()
        rs.status()                                { replSetGetStatus : 1 } checks repl set status
        rs.initiate()                              { replSetInitiate : null } initiates set with default settings
        rs.initiate(cfg)                           { replSetInitiate : cfg } initiates set with configuration cfg
        rs.conf()                                  get the current configuration object from local.system.replset
        rs.reconfig(cfg)                           updates the configuration of a running replica set with cfg (disconnects)
        rs.add(hostportstr)                        add a new member to the set with default attributes (disconnects)
        rs.add(membercfgobj)                       add a new member to the set with extra attributes (disconnects)
        rs.addArb(hostportstr)                     add a new member which is arbiterOnly:true (disconnects)
        rs.stepDown([stepdownSecs,catchUpSecs])   step down as primary (disconnects)
        rs.syncFrom(hostportstr)                   make a secondary sync from the given member
        rs.freeze(secs)                            make a node ineligible to become primary for the time specified
        rs.remove(hostportstr)                     remove a host from the replica set (disconnects)
        rs.secondaryOk()                               allow queries on secondary nodes

        rs.printReplicationInfo()                  check oplog size and time range
        rs.printSecondaryReplicationInfo()             check replica set members and replication lag
        db.isMaster()                              check who is primary

        reconfiguration helpers disconnect from the database so the shell will display
        an error,even if the command succeeds.
> rs.status() 
{
        "operationTime" : Timestamp(0,0),"ok" : 0,"errmsg" : "no replset config has been received","code" : 94,"codeName" : "NotYetInitialized","$clusterTime" : {
                "clusterTime" : Timestamp(0,"signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)
                }
        }
}
> 

  提示:所有关于副本集的操作命令都可以使用rs.help()方法去查看帮助;其中rs.status()是用来查看副本集状态;这里显示没有副本集配置,其原因是没有初始化副本集;

  初始化副本集

> rs.initiate()
{
        "info2" : "no configuration specified. Using a default configuration for the set","me" : "node01.test.org:27017","ok" : 1,"$clusterTime" : {
                "clusterTime" : Timestamp(1605010821,1),"keyId" : NumberLong(0)
                }
        },"operationTime" : Timestamp(1605010821,1)
}
test_replset:SECONDARY> rs.status()
{
        "set" : "test_replset","date" : ISODate("2020-11-10T12:20:32.079Z"),"myState" : 1,"term" : NumberLong(1),"syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"majorityVoteCount" : 1,"writeMajorityCount" : 1,"votingMembersCount" : 1,"writableVotingMembersCount" : 1,"optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1605010821,8),"t" : NumberLong(1)
                },"lastCommittedWallTime" : ISODate("2020-11-10T12:20:21.720Z"),"readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1605010821,"readConcernMajorityWallTime" : ISODate("2020-11-10T12:20:21.720Z"),"appliedOpTime" : {
                        "ts" : Timestamp(1605010821,"durableOpTime" : {
                        "ts" : Timestamp(1605010821,"lastAppliedWallTime" : ISODate("2020-11-10T12:20:21.720Z"),"lastDurableWallTime" : ISODate("2020-11-10T12:20:21.720Z")
        },"electionCandidateMetrics" : {
                "lastElectionReason" : "electionTimeout","lastElectionDate" : ISODate("2020-11-10T12:20:21.632Z"),"electionTerm" : NumberLong(1),"lastCommittedOpTimeAtElection" : {
                        "ts" : Timestamp(0,"t" : NumberLong(-1)
                },"lastSeenOpTimeAtElection" : {
                        "ts" : Timestamp(1605010821,"numVotesNeeded" : 1,"priorityAtElection" : 1,"electionTimeoutMillis" : NumberLong(10000),"newTermStartDate" : ISODate("2020-11-10T12:20:21.694Z"),"wMajorityWriteAvailabilityDate" : ISODate("2020-11-10T12:20:21.719Z")
        },"members" : [
                {
                        "_id" : 0,"name" : "node01.test.org:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 674,"optime" : {
                                "ts" : Timestamp(1605010821,"t" : NumberLong(1)
                        },"optimeDate" : ISODate("2020-11-10T12:20:21Z"),"infoMessage" : "Could not find member to sync from","electionTime" : Timestamp(1605010821,2),"electionDate" : ISODate("2020-11-10T12:20:21Z"),"configVersion" : 1,"configTerm" : 1,"self" : true,"lastHeartbeatMessage" : ""
                }
        ],8)
}
test_replset:PRIMARY> 

  提示:初始化副本集以后,再次查看副本集状态,它告诉我们有一个成员,其主机名为node01.test.org:27017,其health状态为1,stateStr为PRIMARY等等一堆信息;

  查看副本集配置

test_replset:PRIMARY> rs.conf()
{
        "_id" : "test_replset","version" : 1,"term" : 1,"protocolVersion" : NumberLong(1),"writeConcernMajorityJournalDefault" : true,"host" : "node01.test.org:27017","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {

                        },"slaveDelay" : NumberLong(0),"votes" : 1
                }
        ],"settings" : {
                "chainingAllowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : -1,"catchUpTakeoverDelayMillis" : 30000,"getLastErrorModes" : {

                },"getLastErrorDefaults" : {
                        "w" : 1,"wtimeout" : 0
                },"replicaSetId" : ObjectId("5faa85853d5a2d8fdf8af85e")
        }
}
test_replset:PRIMARY> 

  提示:可以看到心跳时间间隔为2s,超时为10s,选举超时时长为10等等信息;

  添加node02,node03节点到副本集成员

test_replset:PRIMARY> rs.add("node02")
{
        "ok" : 1,"$clusterTime" : {
                "clusterTime" : Timestamp(1605011243,"operationTime" : Timestamp(1605011243,1)
}
test_replset:PRIMARY> rs.add("node03")
{
        "ok" : 1,"$clusterTime" : {
                "clusterTime" : Timestamp(1605011250,"operationTime" : Timestamp(1605011250,1)
}
test_replset:PRIMARY> rs.status()
{
        "set" : "test_replset","date" : ISODate("2020-11-10T12:27:45.849Z"),"majorityVoteCount" : 2,"writeMajorityCount" : 2,"votingMembersCount" : 3,"writableVotingMembersCount" : 3,"optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1605011261,"lastCommittedWallTime" : ISODate("2020-11-10T12:27:41.873Z"),"readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1605011261,"readConcernMajorityWallTime" : ISODate("2020-11-10T12:27:41.873Z"),"appliedOpTime" : {
                        "ts" : Timestamp(1605011261,"durableOpTime" : {
                        "ts" : Timestamp(1605011261,"lastAppliedWallTime" : ISODate("2020-11-10T12:27:41.873Z"),"lastDurableWallTime" : ISODate("2020-11-10T12:27:41.873Z")
        },"uptime" : 1107,"optime" : {
                                "ts" : Timestamp(1605011261,"optimeDate" : ISODate("2020-11-10T12:27:41Z"),"infoMessage" : "","configVersion" : 3,"lastHeartbeatMessage" : ""
                },{
                        "_id" : 1,"name" : "node02:27017","state" : 2,"stateStr" : "SECONDARY","uptime" : 21,"optimeDurable" : {
                                "ts" : Timestamp(1605011261,"optimeDurableDate" : ISODate("2020-11-10T12:27:41Z"),"lastHeartbeat" : ISODate("2020-11-10T12:27:44.967Z"),"lastHeartbeatRecv" : ISODate("2020-11-10T12:27:43.983Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncSourceHost" : "node01.test.org:27017","syncSourceId" : 0,"configTerm" : 1
                },{
                        "_id" : 2,"name" : "node03:27017","uptime" : 14,"lastHeartbeatRecv" : ISODate("2020-11-10T12:27:44.571Z"),"pingMs" : NumberLong(1),"syncSourceHost" : "node02:27017","syncSourceId" : 1,"configTerm" : 1
                }
        ],"$clusterTime" : {
                "clusterTime" : Timestamp(1605011261,"operationTime" : Timestamp(1605011261,1)
}
test_replset:PRIMARY> 

  提示:添加节点到副本成员使用rs.add(),括号里面写主机名,或者ip地址,如果对应节点监听端口不是27017,还需要写明端口;除此我们也可以直接用一个子文档的形式,手动指定节点的各属性信息来添加节点到副本集成员;

  到此副本集的配置就完成了,三个节点都添加到副本集;

  验证:在主库上插入数据,看看从库是否都可以正常同步其数据呢?

  在主节点插入数据

test_replset:PRIMARY> use students
switched to db students
test_replset:PRIMARY> db.student_info.insert({name:"tom",age:18,gender:"M"})
WriteResult({ "nInserted" : 1 })
test_replset:PRIMARY> db.student_info.find()
{ "_id" : ObjectId("5faa89297077300f4fc31d1c"),"name" : "tom","age" : 18,"gender" : "M" }
test_replset:PRIMARY> 

  在从节点查看数据

test_replset:SECONDARY> show dbs
uncaught exception: Error: listDatabases failed:{
        "topologyVersion" : {
                "processId" : ObjectId("5faa83025f9218c5d19ea91b"),"counter" : NumberLong(4)
        },"operationTime" : Timestamp(1605011801,"errmsg" : "not master and slaveOk=false","code" : 13435,"codeName" : "NotMasterNoSlaveOk","$clusterTime" : {
                "clusterTime" : Timestamp(1605011801,"keyId" : NumberLong(0)
                }
        }
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
test_replset:SECONDARY> 

  提示:这里在从节点上没法查看数据,原因是默认情况副本集配置好以后,要在从节点运行rs.secondaryOk()来告诉从节点已经配置好了,否则它会不允许我们读,有点类似从节点为就绪的感觉;

  在从节点上运行rs.secondaryOk(),然后再次查看数据

test_replset:SECONDARY> rs.secondaryOk()  
test_replset:SECONDARY> show dbs
admin     0.000GB
config    0.000GB
local     0.000GB
students  0.000GB
test_replset:SECONDARY> use students
switched to db students
test_replset:SECONDARY> show collections
student_info
test_replset:SECONDARY> db.student_info.find().pretty()
{
        "_id" : ObjectId("5faa89297077300f4fc31d1c"),"gender" : "M"
}
test_replset:SECONDARY> 

  提示:可以看到在secondary节点上能够查询到对应数据库中的对应collection中插入的数据;

  验证:在从节点上插入数据,看看是否能插入成功?

test_replset:SECONDARY> db.student_info.insert({name:"jerry",age:19,gender:"M"})
WriteCommandError({
        "topologyVersion" : {
                "processId" : ObjectId("5faa831bde03c4ae108f0be4"),"counter" : NumberLong(3)
        },"operationTime" : Timestamp(1605012904,"errmsg" : "not master","code" : 10107,"codeName" : "NotMaster","$clusterTime" : {
                "clusterTime" : Timestamp(1605012904,"keyId" : NumberLong(0)
                }
        }
})
test_replset:SECONDARY> 

  提示:我们在从节点上插入数据,它提示我们不是主节点,不允许插入数据;这说明副本集的从节点是不允许写;

  验证:将主节点上的mongodb服务停掉,然后在其他两个节点上查看副本集状态,看看两个节点是否重新选举了master?

[root@node01 ~]# systemctl stop mongod.service 
[root@node01 ~]# ss -tnl
State      Recv-Q Send-Q           Local Address:Port                          Peer Address:Port              
LISTEN     0      128                          *:22                                       *:*                  
LISTEN     0      100                  127.0.0.1:25                                       *:*                  
LISTEN     0      128                         :::22                                      :::*                  
LISTEN     0      100                        ::1:25                                      :::*                  
[root@node01 ~]# mongo --host node02
MongoDB shell version v4.4.1
connecting to: mongodb://node02:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("90d60f76-fc95-44a8-bbf7-d927d5947331") }
MongoDB server version: 4.4.1
---
The server generated these startup warnings when booting: 
        2020-11-10T20:09:39.555+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
        2020-11-10T20:09:39.555+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
        2020-11-10T20:09:39.555+08:00: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. We suggest setting it to 'never'
---
---
        Enable MongoDB's free cloud-based monitoring service,which will then receive and display
        metrics about your deployment (disk utilization,CPU,operation statistics,etc).

        The monitoring data will be available on a MongoDB website with a unique URL accessible to you
        and anyone you share the URL with. MongoDB may use this information to make product
        improvements and to suggest MongoDB products and deployment options to you.

        To enable free monitoring,run the following command: db.enableFreeMonitoring()
        To permanently disable this reminder,run the following command: db.disableFreeMonitoring()
---
test_replset:PRIMARY> rs.status()
{
        "set" : "test_replset","date" : ISODate("2020-11-10T12:59:25.775Z"),"term" : NumberLong(2),"optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1605013164,"t" : NumberLong(2)
                },"lastCommittedWallTime" : ISODate("2020-11-10T12:59:24.417Z"),"readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1605013164,"readConcernMajorityWallTime" : ISODate("2020-11-10T12:59:24.417Z"),"appliedOpTime" : {
                        "ts" : Timestamp(1605013164,"durableOpTime" : {
                        "ts" : Timestamp(1605013164,"lastAppliedWallTime" : ISODate("2020-11-10T12:59:24.417Z"),"lastDurableWallTime" : ISODate("2020-11-10T12:59:24.417Z")
        },"electionCandidateMetrics" : {
                "lastElectionReason" : "stepUpRequestSkipDryRun","lastElectionDate" : ISODate("2020-11-10T12:58:34.398Z"),"electionTerm" : NumberLong(2),"lastCommittedOpTimeAtElection" : {
                        "ts" : Timestamp(1605013112,"lastSeenOpTimeAtElection" : {
                        "ts" : Timestamp(1605013112,"numVotesNeeded" : 2,"priorPrimaryMemberId" : 0,"numCatchUpOps" : NumberLong(0),"newTermStartDate" : ISODate("2020-11-10T12:58:34.410Z"),"wMajorityWriteAvailabilityDate" : ISODate("2020-11-10T12:58:34.506Z")
        },"health" : 0,"state" : 8,"stateStr" : "(not reachable/healthy)","uptime" : 0,"optime" : {
                                "ts" : Timestamp(0,"t" : NumberLong(-1)
                        },"optimeDurable" : {
                                "ts" : Timestamp(0,"optimeDate" : ISODate("1970-01-01T00:00:00Z"),"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),"lastHeartbeat" : ISODate("2020-11-10T12:59:24.558Z"),"lastHeartbeatRecv" : ISODate("2020-11-10T12:58:35.045Z"),"lastHeartbeatMessage" : "Error connecting to node01.test.org:27017 (192.168.0.41:27017) :: caused by :: Connection refused","uptime" : 2987,"optime" : {
                                "ts" : Timestamp(1605013164,"t" : NumberLong(2)
                        },"optimeDate" : ISODate("2020-11-10T12:59:24Z"),"electionTime" : Timestamp(1605013114,"electionDate" : ISODate("2020-11-10T12:58:34Z"),"configTerm" : 2,"uptime" : 1914,"optimeDurable" : {
                                "ts" : Timestamp(1605013164,"optimeDurableDate" : ISODate("2020-11-10T12:59:24Z"),"lastHeartbeat" : ISODate("2020-11-10T12:59:24.459Z"),"lastHeartbeatRecv" : ISODate("2020-11-10T12:59:25.506Z"),"configTerm" : 2
                }
        ],"$clusterTime" : {
                "clusterTime" : Timestamp(1605013164,"operationTime" : Timestamp(1605013164,1)
}
test_replset:PRIMARY> 

  提示:可以看到当node01上的mongodb服务停掉以后,对应的主节点也就不能够正常的向从节点发送心跳,所以剩下的两个从节点都认为主节点挂了,此时他俩就开始重新选举主节点;我们再次连接到node02上的mongodb查看副本集状态时,此时node02上的mongodb就成为了主节点;同时我们也能看到node01的健康状态为0,表示不健康;

  查看从节点的复制信息

test_replset:PRIMARY> rs.printSecondaryReplicationInfo()
source: node01.test.org:27017
        syncedTo: Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
        1605013534 secs (445837.09 hrs) behind the primary 
source: node03:27017
        syncedTo: Tue Nov 10 2020 21:05:34 GMT+0800 (CST)
        0 secs (0 hrs) behind the primary 
test_replset:PRIMARY>

  提示:这里可以看到node01落后主节点很长时间,node03不落后主节点;

  查看同步信息时间窗口,以及oplog大小

test_replset:PRIMARY> rs.printReplicationInfo()
configured oplog size:   2048MB
log length start to end: 2291secs (0.64hrs)
oplog first event time:  Tue Nov 10 2020 20:27:23 GMT+0800 (CST)
oplog last event time:   Tue Nov 10 2020 21:05:34 GMT+0800 (CST)
now:                     Tue Nov 10 2020 21:05:35 GMT+0800 (CST)
test_replset:PRIMARY>

  提示:可以看到oplog的小为2048MB,日志开始到结束的时间窗口为2291秒,意思是说当前启动副本集到查询复制信息是的时长为2291秒;第一个oplog时间时间和最后oplog事件时间以及现在的时间都可查看得到;

  移除节点(从副本集中,将node01节点移除)

test_replset:PRIMARY> rs.remove("node01.test.org:27017")
{
        "ok" : 1,"$clusterTime" : {
                "clusterTime" : Timestamp(1605014063,"operationTime" : Timestamp(1605014063,"date" : ISODate("2020-11-10T13:14:35.362Z"),"votingMembersCount" : 2,"writableVotingMembersCount" : 2,"optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1605014074,"lastCommittedWallTime" : ISODate("2020-11-10T13:14:34.514Z"),"readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1605014074,"readConcernMajorityWallTime" : ISODate("2020-11-10T13:14:34.514Z"),"appliedOpTime" : {
                        "ts" : Timestamp(1605014074,"durableOpTime" : {
                        "ts" : Timestamp(1605014074,"lastAppliedWallTime" : ISODate("2020-11-10T13:14:34.514Z"),"lastDurableWallTime" : ISODate("2020-11-10T13:14:34.514Z")
        },"members" : [
                {
                        "_id" : 1,"uptime" : 3897,"optime" : {
                                "ts" : Timestamp(1605014074,"optimeDate" : ISODate("2020-11-10T13:14:34Z"),"configVersion" : 4,"uptime" : 2824,"optime" : {
                                "ts" : Timestamp(1605014063,"optimeDurable" : {
                                "ts" : Timestamp(1605014063,"optimeDate" : ISODate("2020-11-10T13:14:23Z"),"optimeDurableDate" : ISODate("2020-11-10T13:14:23Z"),"lastHeartbeat" : ISODate("2020-11-10T13:14:33.958Z"),"lastHeartbeatRecv" : ISODate("2020-11-10T13:14:33.970Z"),"$clusterTime" : {
                "clusterTime" : Timestamp(1605014074,"operationTime" : Timestamp(1605014074,1)
}
test_replset:PRIMARY> 

  提示:移除节点需要写明对应节点的主机名地址和端口,或者是ip地址端口;这个字串必须是同加入到副本集中的名字相同才可移除,否则它会提示我们给定主机字符串找不到;

  设置node03的优先级为10

test_replset:PRIMARY> cfg = rs.conf()
{
        "_id" : "test_replset","version" : 4,"term" : 2,"host" : "node02:27017","votes" : 1
                },"host" : "node03:27017","replicaSetId" : ObjectId("5faa85853d5a2d8fdf8af85e")
        }
}
test_replset:PRIMARY> cfg.members[1].priority = 10
10
test_replset:PRIMARY> rs.reconfig(cfg)
{
        "ok" : 1,"$clusterTime" : {
                "clusterTime" : Timestamp(1605015945,"operationTime" : Timestamp(1605015945,1)
}
test_replset:PRIMARY> rs.config()
{
        "_id" : "test_replset","version" : 5,"term" : 3,"priority" : 10,"replicaSetId" : ObjectId("5faa85853d5a2d8fdf8af85e")
        }
}
test_replset:SECONDARY> 

  提示:设置某个成员的优先级,首先要把当前配置用一个变量保存,然后通过修改保存的配置变量来修改优先级以后,再使用rs.reconfig()来读取修改后的配置即可生效;这里需要注意我在修改配置文件时指定成员,是指定对应成员在members列表的下标,而非id;所以修改前要先确定对应成员的下标是多少;我们修改了node03的优先级以后,心细的你一定会发现node02此时就变成了secondary;这意味着,只要在副本集中有更高优先级的成员加入,会触发一次选举,当然选举成为主节点,影响最大的就是各节点的优先级,优先级越高,当选主节点的几率就越大;默认情况每个成员的优先级都为1,优先级设定的取值范围是0-1000;

  将node01上的mongodb服务启动起来,然后在主节点上将其添加为仲裁节点

  启动node01上的mongodb服务

[root@node01 ~]# systemctl start mongod.service 
[root@node01 ~]# ss -tnl
State      Recv-Q Send-Q           Local Address:Port                          Peer Address:Port              
LISTEN     0      128                          *:22                                       *:*                  
LISTEN     0      100                  127.0.0.1:25                                       *:*                  
LISTEN     0      128                          *:27017                                    *:*                  
LISTEN     0      128                         :::22                                      :::*                  
LISTEN     0      100                        ::1:25                                      :::*                  
[root@node01 ~]# 

  在主节点上将node01添加为仲裁节点

test_replset:PRIMARY> rs.addArb("node01")
{
        "ok" : 1,"$clusterTime" : {
                "clusterTime" : Timestamp(1605016848,"operationTime" : Timestamp(1605016848,1)
}
test_replset:PRIMARY>

  查看配置信息,看看node01上的arbiterOnly是否变成了true?

test_replset:PRIMARY> rs.config()
{
        "_id" : "test_replset","version" : 8,{
                        "_id" : 3,"host" : "node01:27017","arbiterOnly" : true,"priority" : 0,"replicaSetId" : ObjectId("5faa85853d5a2d8fdf8af85e")
        }
}
test_replset:PRIMARY> 

  提示:可以看到node01节点上的arbiterOnly属性已经启用,说明这就是一个仲裁节点;我们说过仲裁节点上没有保存副本,我们到node01上看看是否保存的有副本集数据呢?

test_replset:ARBITER> show databases
uncaught exception: Error: listDatabases failed:{
        "topologyVersion" : {
                "processId" : ObjectId("5faa9d87e504fa222c4a584d"),"counter" : NumberLong(1)
        },"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
test_replset:ARBITER> rs.secondaryOk()
test_replset:ARBITER> show databases
uncaught exception: Error: listDatabases failed:{
        "topologyVersion" : {
                "processId" : ObjectId("5faa9d87e504fa222c4a584d"),"errmsg" : "node is not in primary or recovering state","code" : 13436,"codeName" : "NotMasterOrSecondary"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
test_replset:ARBITER> 

  提示:我们在仲裁节点上查看数据库列表,它提示我们不是主节点和从节点,不允许读;既然都不允许读,写肯定是没有办法进行;

  ok,到此mongodb的副本集的配置、测试就到此为止;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读552次。com.mongodb.MongoQueryException: Query failed with error code 292 and error message 'Executor error during find command :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting.' on server 11.51.141.63:27017 _mongodb 大文件 下载失败
文章浏览阅读635次,点赞9次,收藏8次。MongoDB 是一种 NoSQL 数据库,它将每个数据存储为一个文档,这里的文档类似于 JSON/BSON 对象,具体数据结构由键值(key/value)对组成。
文章浏览阅读2.1k次。和。_mongodb 日期类型
文章浏览阅读1.7k次。Scalestack等客户期待使用MongoDB Atlas Vector Search和Amazon Bedrock构建下一代应用程序
文章浏览阅读970次。SpringBoot整合中间件mongodb、ES_springboot3 elasticsearch json数据
文章浏览阅读673次。MongoDB 简介_尚医通sql
文章浏览阅读1k次,点赞8次,收藏9次。官网下载MongoDB安装包后进行解压(因了解并不深入,故暂不进行详细说明,自行查找其他安装方法,后期了解深入后将进行该教程的完善)在bin目录下使用命令启动:./mongod --config …/mongodb.conf。该文章任然处于完善中,如果存在错误遗漏的地方,欢迎私信联系。安装相关的nuget包后即可通过以下方法连接数据。YX9010_0@的第二十篇文章。
文章浏览阅读1.2k次,点赞17次,收藏26次。社交场景, 使用 MongoDB 存储存储用户信息, 以及用户发表的朋友圈信息, 通过地理位置索引实现附近的人, 地点等功能.游戏场景, 使用 MongoDB 存储游戏用户信息, 用户的装备, 积分等直接以内嵌文档的形式存储, 方便查询, 高效率存储和访问.物流场景, 使用 MongoDB 存储订单信息, 订单状态在运送过程中会不断更新, 以 MongoDB 内嵌数组的形式来存储, 一次查询就能将订单所有的变更读取出来.物联网场景, 使用 MongoDB 存储所有接入的智能设备信息, 以及设备汇报的日
文章浏览阅读686次。您可以使用 update_one() 方法来更新 MongoDB 中调用的记录或文档。update_one() 方法的第一个参数是 query 对象,用于定义要更新的文档。注释:如果查询找到多个记录,则仅更新第一个匹配项。第二个参数是定义文档新值的对象。_python 更新 mongodb 数据
文章浏览阅读1.3k次。首先来学习一下nosql这里安装就不进行介绍 只记录一下让自己了解mongodb。_nosql注入
文章浏览阅读4.1k次,点赞8次,收藏7次。在data的目录下,创建一个db文件。因为启动MongoDB服务之前必须创建数据库文件的存放文件夹,否则命令不会自动创建,而且不能启动成功。第一步:安装时,Custom是指可以自定义安装路径,然后傻瓜式安装即可(注意:先不要安装图形化工具,否则安装时间会特别长):如果要想连接成功,必须要开服务,即mongod -dbpath C:MongoDBdatadb的cmd要一直开着。然后回车,ctrl+F输入port找到端口号,一般为:27017。打开命令行,然后找到bin文件地址,并输入。_mongodb windows安装
文章浏览阅读5.1k次,点赞3次,收藏43次。详细介绍MongoDB数据库的基本知识,安装方法,基本操作,_mongodb数据库
文章浏览阅读3.2k次。安装教程翻看以往文章。_navicat 连接mongodb
文章浏览阅读426次,点赞9次,收藏12次。win10开放端口:https://blog.csdn.net/m0_43605481/article/details/119255256。我的是阿里云服务器,所以直接在安全组中加入规则,端口范围:27017,授权对象:0.0.0.0。windows在mongodb安装文件夹的bin文件夹中的mongod.cfg。数据库名字是test,打算创建一个用户,账号aaa,密码bbb,权限readWrite。因为该用户是创建在test数据库的,所以在最后要加上test。O了,然后恢复了test的数据。
文章浏览阅读1.1k次。聚合操作主要用于处理数据并返回计算结果。聚合操作将来自多个文档的值组合在一起,按条件分组后,再进行一系列操作(如求和、平均值、最大值、最小值)以返回单个结果。MongoDB的聚合查询​聚合是MongoDB的高级查询语言,它允许我们通过转化合并由多个文档的数据来生成新的在单个文档里不存在的文档信息。MongoDB中聚合(aggregate)主要用于处理数据(例如分组统计平均值、求和、最大值等),并返回计算后的数据结果,有点类似sql语句中的count(*)、groupby。..._如何将几个db的数据统整在一起做查询
文章浏览阅读680次,点赞7次,收藏8次。(2)application.properties配置文件。(4)UserService类。(5)测试和测试结果。
文章浏览阅读1k次,点赞17次,收藏25次。Studio 3T 2023.9 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端,支持自然语言查询_mongodb客户端
文章浏览阅读1.1k次,点赞32次,收藏27次。插件式的存储引擎架构可以实现 Server 层和存储引擎层的解耦,可以支持多种存储引擎,如 MySQL 既可以支持 B-Tree 结构的 InnoDB 存储引擎,还可以支持 LSM 结构的 RocksDB 存储引擎。MongoDB 中的记录就是一个 BSON 文档,它是由键值对组成的数据结构,类似于 JSON 对象,是 MongoDB 中的基本数据单元。的简称,是 JSON 文档的二进制表示,支持将文档和数组嵌入到其他文档和数组中,还包含允许表示不属于 JSON 规范的数据类型的扩展。
文章浏览阅读5.1k次,点赞6次,收藏96次。本文设计了一种基于智能室内温度控制的自动调速风扇。以STM32系列单片机为核心主控板,通过程序代码驱动和使用温度传感器模块实现对环境温度的实时监测,并可以实时显示环境温度。同时,可以设置温度检测的上下警告值,根据需求自行调节。_stm32 温控风扇
文章浏览阅读898次,点赞13次,收藏21次。在MongoDB中,我们使用find()和find_one()方法来在集合中查找数据,就像在MySQL数据库中使用SELECT语句来在表中查找数据一样。_pymongo find_one