MongoDB副本集( ReplicaSet )

MongoDB副本集( ReplicaSet )

Scroll Down

ReplicaSet简介

MongoDB复制是将数据同步在多个服务器的过程,类似mysql Replication是一种异步复制;
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性

MongoDB复制特点

  1. mongodb的节点有三种角色:primary,seconfary,arbiter,
    primary负责处理客户端请求,读写数据;
    secondary通过oplog复制主节点上的数据,也可读数据;
    arbiter节点不存储数据,仅投票功能,所以不需要单独的硬件配置;
  2. 如果primary不可以用,secondary会提升为新的primary; 由参数electionTimeoutMillis=10s控制

MongoDB副本集架构

mongodbrs1.png
Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点;主备节点存储数据,仲裁节点不存储数据,客户端同时连接主节点与备节点,不连接仲裁节点
仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点
在MongoDB副本集中,主节点负责处理客户端的读写请求,备份节点则负责映射主节点的数据
备份节点的工作原理过程可以大致描述为,备份节点定期轮询主节点上的数据操作,然后对自己的数据副本进行这些操作,从而保证跟主节点的数据同步,至于主节点上的所有数据库状态改变的操作,都会存放在一张特定的系统表中,备份节点则是根据这些数据进行自己的数据更新
上面提到的数据库状态改变的操作,称为oplog(operation log,主节点操作记录)oplog存储在local数据库的"oplog.rs"表中。副本集中备份节点异步的从主节点同步oplog,然后重新执行它记录的操作,以此达到了数据同步的作用

Oplog注意点:

  • Oplog的大小是固定的,当集合被填满的时候,新的插入的文档会覆盖老的文档
  • Oplog同步数据
    初始化:这个过程发生在当副本集中创建一个新的数据库或其中某个节点刚从宕机中恢复,或者向副本集中添加新的成员的时候,默认的,副本集中的节点会从离它最近的节点复制oplog来同步数据,这个最近的节点可以是primary也可以是拥有最新oplog副本的secondary节点

环境说明

MongoDB-4.2.8版本
一台物理机器上三个MongoDB实例,分别占用三个节点(由于测试使用,就以端口区分,实际环境中可分布式部署)

IP端口角色
192.168.200.7727017node1 primary 主节点
192.168.200.7727018node2 secondary备节点
192.168.200.7727019node3 arbiter仲裁节点

集群部署

部署有仲裁节点的副本集群

下载安装包

官方下载地址:https://www.mongodb.com/download-center/community

[root@bash ~]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.8.tgz
[root@bash ~]# tar xvzf mongodb-linux-x86_64-rhel70-4.2.8.tgz
[root@bash ~]# mv mongodb-linux-x86_64-rhel70-4.2.8 /usr/local/mongodb
[root@bash ~]# echo "export PATH=/usr/local/mongodb/bin:$PATH" >>/etc/profile
[root@bash ~]# source /etc/profile
[root@bash ~]# mongod -version
db version v4.2.8
git version: 43d25964249164d76d5e04dd6cf38f6111e21f5f
OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
allocator: tcmalloc
modules: none
build environment:
    distmod: rhel70
    distarch: x86_64
    target_arch: x86_64

创建数据和日志目录

[root@bash ~]# cd /usr/local/mongodb
[root@bash mongodb]# groupadd mongodb
[root@bash mongodb]# useradd -s /sbin/nologin -g mongodb -M mongodb
[root@bash mongodb]# mkdir -p /usr/local/mongodb/data/{db27017,db27018,db27019}
[root@bash mongodb]# ls
bin  data  LICENSE-Community.txt  MPL-2  README  THIRD-PARTY-NOTICES  THIRD-PARTY-NOTICES.gotools
[root@bash mongodb]# mkdir -p /usr/local/mongodb/log

配置文件/etc/mongod.conf

三个节点分别创建配置文件,文件内容区别是节点不同,其他都相同,参数replSetname用来指定副本集名称为rs0

[root@bash ~]# ll /etc/mongod2701*.conf
-rw-r--r--. 1 root root 403 7月  15 16:11 /etc/mongod27017.conf
-rw-r--r--. 1 root root 403 7月  15 16:13 /etc/mongod27018.conf
-rw-r--r--. 1 root root 403 7月  15 16:13 /etc/mongod27019.conf

### mongodb配置文件每个冒号后面要有一个空格,否则会报错
[root@bash ~]# cat /etc/mongod27017.conf
systemLog:
   destination: file
   path: "/usr/local/mongodb/log/mongod27017.log"
   logAppend: true
storage:
   dbPath: /usr/local/mongodb/data/db27017
   journal:
      enabled: true
processManagement:
   fork: true
   pidFilePath: /usr/local/mongodb/data/db27017/mongod27017.pid
net:
   port: 27017
   bindIp: 0.0.0.0
setParameter:
   enableLocalhostAuthBypass: false
replication:
  replSetName: rs0

启动MongoDB集群

分别启动三个节点的MongoDB服务,并指定配置文件

[root@bash ~]# mongod --config /etc/mongod27017.conf
about to fork child process, waiting until server is ready for connections.
forked process: 11509
child process started successfully, parent exiting
[root@bash ~]# mongod --config /etc/mongod27018.conf
about to fork child process, waiting until server is ready for connections.
forked process: 11547
child process started successfully, parent exiting
[root@bash ~]# mongod --config /etc/mongod27019.conf
about to fork child process, waiting until server is ready for connections.
forked process: 11585
child process started successfully, parent exiting
[root@bash ~]# netstat -ntulp|grep mongo
tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      11509/mongod        
tcp        0      0 0.0.0.0:27018           0.0.0.0:*               LISTEN      11547/mongod        
tcp        0      0 0.0.0.0:27019           0.0.0.0:*               LISTEN      11585/mongod

配置集群

初始化集群

上述配置 没有指定哪一个是master、slave、仲裁节点,所以需要执行下副本集的初始化,随便登录到任一mongodb

> rs.initiate({"_id":"rs0",members:[{"_id":1,"host":"192.168.200.77:27017",priority:3},{"_id":2,"host":"192.168.200.77:27018", priority:9},{"_id":3,"host":"192.168.200.77:27019",arbiterOnly:true}]})
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594807539, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594807539, 1)
}
rs0:SECONDARY>

"_id": 副本集的名称
"members": 副本集的服务器列表
"_id": 服务器的唯一ID
"host": 服务器主机
"priority": 是优先级,默认为1,优先级0为被动节点,不能成为活跃节点,优先级不位0则按照有大到小选出活跃节点
"arbiterOnly": 仲裁节点,只参与投票,不接收数据,也不能成为活跃节点

rs.status() 查看状态

stateStr 为描述主节点或者复制节点

rs0:SECONDARY> rs.status()
{
	"set" : "rs0",
	"date" : ISODate("2020-07-15T10:06:33.162Z"),
	"myState" : 2,
	"term" : NumberLong(2),
	"syncingTo" : "192.168.200.77:27018",
	"syncSourceHost" : "192.168.200.77:27018",
	"syncSourceId" : 2,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 2,
	"writeMajorityCount" : 2,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1594807591, 1),
			"t" : NumberLong(2)
		},
		"lastCommittedWallTime" : ISODate("2020-07-15T10:06:31.636Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1594807591, 1),
			"t" : NumberLong(2)
		},
		"readConcernMajorityWallTime" : ISODate("2020-07-15T10:06:31.636Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1594807591, 1),
			"t" : NumberLong(2)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1594807591, 1),
			"t" : NumberLong(2)
		},
		"lastAppliedWallTime" : ISODate("2020-07-15T10:06:31.636Z"),
		"lastDurableWallTime" : ISODate("2020-07-15T10:06:31.636Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1594807550, 3),
	"lastStableCheckpointTimestamp" : Timestamp(1594807550, 3),
	"electionParticipantMetrics" : {
		"votedForCandidate" : true,
		"electionTerm" : NumberLong(2),
		"lastVoteDate" : ISODate("2020-07-15T10:06:01.634Z"),
		"electionCandidateMemberId" : 2,
		"voteReason" : "",
		"lastAppliedOpTimeAtElection" : {
			"ts" : Timestamp(1594807551, 1),
			"t" : NumberLong(1)
		},
		"maxAppliedOpTimeInSet" : {
			"ts" : Timestamp(1594807551, 1),
			"t" : NumberLong(1)
		},
		"priorityAtElection" : 3,
		"newTermStartDate" : ISODate("2020-07-15T10:06:01.635Z"),
		"newTermAppliedDate" : ISODate("2020-07-15T10:06:02.637Z")
	},
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 233,
			"optime" : {
				"ts" : Timestamp(1594807591, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-15T10:06:31Z"),
			"syncingTo" : "192.168.200.77:27018",
			"syncSourceHost" : "192.168.200.77:27018",
			"syncSourceId" : 2,
			"infoMessage" : "",
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27018",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 53,
			"optime" : {
				"ts" : Timestamp(1594807591, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594807591, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-15T10:06:31Z"),
			"optimeDurableDate" : ISODate("2020-07-15T10:06:31Z"),
			"lastHeartbeat" : ISODate("2020-07-15T10:06:32.881Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-15T10:06:31.635Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1594807561, 1),
			"electionDate" : ISODate("2020-07-15T10:06:01Z"),
			"configVersion" : 1
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27019",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 53,
			"lastHeartbeat" : ISODate("2020-07-15T10:06:32.880Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-15T10:06:32.225Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 1
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594807591, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594807591, 1)
}

数据同步验证

为了验证副本集搭建成功,在主节点中插入几条数据,然后在从节点中查看,上面配置了 27018为主节点,27017为备节点,27019为仲裁节点
在主节点上

[root@bash data]# mongo 192.168.200.77:27018/admin
rs0:PRIMARY> show dbs;
admin   0.000GB
config  0.000GB
local   0.000GB
rs0:PRIMARY> use testdb
switched to db testdb
rs0:PRIMARY> db.createCollection("testCon")
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594808507, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594808507, 1)
}
rs0:PRIMARY> for(var i=0; i<3;i++) db.testCon.insert({name:"Joe",index:i})
WriteResult({ "nInserted" : 1 })
rs0:PRIMARY> db.testCon.find()
{ "_id" : ObjectId("5f0ed8cb87ef6ea54a0dacb7"), "name" : "Joe", "index" : 0 }
{ "_id" : ObjectId("5f0ed8cb87ef6ea54a0dacb8"), "name" : "Joe", "index" : 1 }
{ "_id" : ObjectId("5f0ed8cb87ef6ea54a0dacb9"), "name" : "Joe", "index" : 2 }

在备节点上

[root@bash mongodb]# mongo 192.168.200.77:27017/admin
MongoDB shell version v4.2.8
...
rs0:SECONDARY> show dbs
2020-07-15T18:24:15.119+0800 E  QUERY    [js] uncaught exception: Error: listDatabases failed:{
	"operationTime" : Timestamp(1594808651, 1),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594808651, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:135:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:87:12
shellHelper.show@src/mongo/shell/utils.js:906:13
shellHelper@src/mongo/shell/utils.js:790:15
@(shellhelp2):1:1
#因为SECONDARY是不允许读写的,可通过如下解决
rs0:SECONDARY> rs.slaveOk()
rs0:SECONDARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
testdb  0.000GB
rs0:SECONDARY> use testdb
switched to db testdb
rs0:SECONDARY> show collections
testCon
rs0:SECONDARY> db.testCon.find()
{ "_id" : ObjectId("5f0ed8cb87ef6ea54a0dacb7"), "name" : "Joe", "index" : 0 }
{ "_id" : ObjectId("5f0ed8cb87ef6ea54a0dacb8"), "name" : "Joe", "index" : 1 }
{ "_id" : ObjectId("5f0ed8cb87ef6ea54a0dacb9"), "name" : "Joe", "index" : 2 }

在从节点中可以查看到主节点插入的数据,说明副本集搭建成功
注意:从节点中是不允许执行写操作的

模拟主节点故障及恢复

  1. 模拟主节点挂了,kiil掉主节点的进程
  2. 客户端连接从节点:mongo --host 192.168.200.77 --port 27017
rs0:PRIMARY> rs.status()
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 14791,
			"optime" : {
				"ts" : Timestamp(1594822147, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2020-07-15T14:09:07Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "could not find member to sync from",
			"electionTime" : Timestamp(1594822107, 1),
			"electionDate" : ISODate("2020-07-15T14:08:27Z"),
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27018",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2020-07-15T14:09:09.330Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-15T14:08:18.064Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "Error connecting to 192.168.200.77:27018 :: caused by :: Connection refused",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : -1
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27019",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 14611,
			"lastHeartbeat" : ISODate("2020-07-15T14:09:09.325Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-15T14:09:10.723Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 1
		}
	],

发现原来的从节点变为了主节点,而原来的主节点显示的状态是不可达、不健康的,这对于整个副本集的使用是没有影响的
3. 重新启动node2,即原来的主节点,如果启动失败,就删除掉db文件夹下的mongod.lock文件
4. 客户端连接node1,mongo --host 192.168.200.77 --port 27017,发现node2重新启动后,node1又变为从节点,而node2又变为原来的主节点,这是因为仲裁节点和设置的优先级的原因

rs0:PRIMARY> rs.status()
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 24,
			"optime" : {
				"ts" : Timestamp(1594822504, 1),
				"t" : NumberLong(4)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594822504, 1),
				"t" : NumberLong(4)
			},
			"optimeDate" : ISODate("2020-07-15T14:15:04Z"),
			"optimeDurableDate" : ISODate("2020-07-15T14:15:04Z"),
			"lastHeartbeat" : ISODate("2020-07-15T14:15:06.499Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-15T14:15:07.929Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27018",
			"syncSourceHost" : "192.168.200.77:27018",
			"syncSourceId" : 2,
			"infoMessage" : "",
			"configVersion" : 1
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27018",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 26,
			"optime" : {
				"ts" : Timestamp(1594822504, 1),
				"t" : NumberLong(4)
			},
			"optimeDate" : ISODate("2020-07-15T14:15:04Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1594822494, 1),
			"electionDate" : ISODate("2020-07-15T14:14:54Z"),
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27019",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 24,
			"lastHeartbeat" : ISODate("2020-07-15T14:15:06.499Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-15T14:15:06.829Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 1
		}
	],

如果当仲裁节点挂掉后,就集群达不到高可用了,即当主节点挂了后,从节点在没有仲裁节点的情况下,不会切换为主节点了,所以推荐使用没有仲裁节点的副本集

搭建没有仲裁节点的副本集

IP端口角色
192.168.200.7727217node6 primary 主节点
192.168.200.7727218node7 secondary备节点
192.168.200.7727219node8 secondary备节点

拷贝node1的配置文件

修改端口为27217 27218 27219 ,修改logpath dbPath pidFilePath

[root@bash ~]# cp /etc/mongod27017.conf /etc/mongod27217.conf
[root@bash ~]# cp /etc/mongod27017.conf /etc/mongod27218.conf
[root@bash ~]# cp /etc/mongod27017.conf /etc/mongod27219.conf
[root@bash ~]# ll /etc/mongod2721*
-rw-r--r--. 1 root root 403 7月  16 10:27 /etc/mongod27217.conf
-rw-r--r--. 1 root root 403 7月  16 10:27 /etc/mongod27218.conf
-rw-r--r--. 1 root root 403 7月  16 10:27 /etc/mongod27219.conf

拷贝node1的数据文件

清空node6、node7、node8的db文件夹 和 log 文件夹

[root@bash data]# pwd
/usr/local/mongodb/data
[root@bash data]# ls
db27017  db27018  db27019
[root@bash data]# cp -r db27017 db27217
[root@bash data]# cp -r db27017 db27218
[root@bash data]# cp -r db27017 db27219
[root@bash data]# ls|grep 2721
db27217
db27218
db27219
[root@bash log]# pwd
/usr/local/mongodb/log
[root@bash log]# ls
mongod27017.log  mongod27018.log  mongod27019.log
[root@bash log]# cp -r mongod27017.log mongod27217.log
[root@bash log]# cp -r mongod27017.log mongod27218.log
[root@bash log]# cp -r mongod27017.log mongod27219.log
[root@bash log]# ls|grep 2721*
mongod27217.log
mongod27218.log
mongod27219.log
[root@bash mongodb]# rm -fr data/db27217/*
[root@bash mongodb]# rm -fr data/db27218/*
[root@bash mongodb]# rm -fr data/db27219/*
[root@bash mongodb]# rm -fr log/mongod27217.log/*
[root@bash mongodb]# rm -fr log/mongod27218.log/*
[root@bash mongodb]# rm -fr log/mongod27219.log/*

启动三个节点

[root@bash mongodb]# mongod --config /etc/mongod27217.conf
about to fork child process, waiting until server is ready for connections.
forked process: 14124
child process started successfully, parent exiting
[root@bash mongodb]# mongod --config /etc/mongod27218.conf
about to fork child process, waiting until server is ready for connections.
forked process: 14162
child process started successfully, parent exiting
[root@bash mongodb]# mongod --config /etc/mongod27219.conf
about to fork child process, waiting until server is ready for connections.
forked process: 14200
child process started successfully, parent exiting
[root@bash mongodb]# netstat -ntulp|grep 2721
tcp        0      0 0.0.0.0:27217           0.0.0.0:*               LISTEN      14124/mongod        
tcp        0      0 0.0.0.0:27218           0.0.0.0:*               LISTEN      14162/mongod        
tcp        0      0 0.0.0.0:27219           0.0.0.0:*               LISTEN      14200/mongod

初始化集群

登录到node6,执行初始化命令

[root@bash mongodb]# mongo 192.168.200.77:27217
MongoDB shell version v4.2.8
> rs.initiate({"_id":"rs0",members:[{"_id":1,"host":"192.168.200.77:27217"},{"_id":2,"host":"192.168.200.77:27218"},{"_id":3,"host":"192.168.200.77:27219" }]})
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594869862, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594869862, 1)
}
rs0:SECONDARY>

查看状态

发现有一个主节点,两个从节点

rs0:PRIMARY> rs.status()
{
	"set" : "rs0",
	"date" : ISODate("2020-07-16T03:25:46.333Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncingTo" : "",
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 2,
	"writeMajorityCount" : 2,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1594869942, 1),
			"t" : NumberLong(1)
		},
		"lastCommittedWallTime" : ISODate("2020-07-16T03:25:42.956Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1594869942, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityWallTime" : ISODate("2020-07-16T03:25:42.956Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1594869942, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1594869942, 1),
			"t" : NumberLong(1)
		},
		"lastAppliedWallTime" : ISODate("2020-07-16T03:25:42.956Z"),
		"lastDurableWallTime" : ISODate("2020-07-16T03:25:42.956Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1594869932, 1),
	"lastStableCheckpointTimestamp" : Timestamp(1594869932, 1),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-07-16T03:24:32.943Z"),
		"electionTerm" : NumberLong(1),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(0, 0),
			"t" : NumberLong(-1)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1594869862, 1),
			"t" : NumberLong(-1)
		},
		"numVotesNeeded" : 2,
		"priorityAtElection" : 1,
		"electionTimeoutMillis" : NumberLong(10000),
		"numCatchUpOps" : NumberLong(0),
		"newTermStartDate" : ISODate("2020-07-16T03:24:32.954Z"),
		"wMajorityWriteAvailabilityDate" : ISODate("2020-07-16T03:24:33.232Z")
	},
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27217",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 533,
			"optime" : {
				"ts" : Timestamp(1594869942, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-07-16T03:25:42Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "could not find member to sync from",
			"electionTime" : Timestamp(1594869872, 1),
			"electionDate" : ISODate("2020-07-16T03:24:32Z"),
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27218",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 83,
			"optime" : {
				"ts" : Timestamp(1594869942, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594869942, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-07-16T03:25:42Z"),
			"optimeDurableDate" : ISODate("2020-07-16T03:25:42Z"),
			"lastHeartbeat" : ISODate("2020-07-16T03:25:44.946Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T03:25:45.712Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27217",
			"syncSourceHost" : "192.168.200.77:27217",
			"syncSourceId" : 1,
			"infoMessage" : "",
			"configVersion" : 1
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27219",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 83,
			"optime" : {
				"ts" : Timestamp(1594869942, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594869942, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-07-16T03:25:42Z"),
			"optimeDurableDate" : ISODate("2020-07-16T03:25:42Z"),
			"lastHeartbeat" : ISODate("2020-07-16T03:25:44.947Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T03:25:45.716Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27217",
			"syncSourceHost" : "192.168.200.77:27217",
			"syncSourceId" : 1,
			"infoMessage" : "",
			"configVersion" : 1
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594869942, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594869942, 1)
}

模拟服务宕机

kill 掉node6,即端口 27217

[root@bash mongodb]# netstat -ntulp|grep 27217
tcp        0      0 0.0.0.0:27217           0.0.0.0:*               LISTEN      14124/mongod        
[root@bash mongodb]# kill -9 14127

连接到node7上:mongo 192.168.200.77:27218,查看状态,发现node7为从节点,node8为主节点了,原来的node6 不可达、不健康的

[root@bash mongodb]# mongo 192.168.200.77:27218
MongoDB shell version v4.2.8
rs0:SECONDARY> rs.status()
......
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27217",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2020-07-16T03:36:29.058Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T03:35:38.952Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "Error connecting to 192.168.200.77:27217 :: caused by :: Connection refused",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : -1
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27218",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 1172,
			"optime" : {
				"ts" : Timestamp(1594870588, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T03:36:28Z"),
			"syncingTo" : "192.168.200.77:27219",
			"syncSourceHost" : "192.168.200.77:27219",
			"syncSourceId" : 3,
			"infoMessage" : "",
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27219",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 100,
			"optime" : {
				"ts" : Timestamp(1594870588, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594870588, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T03:36:28Z"),
			"optimeDurableDate" : ISODate("2020-07-16T03:36:28Z"),
			"lastHeartbeat" : ISODate("2020-07-16T03:36:29.549Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T03:36:30.061Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1594870548, 1),
			"electionDate" : ISODate("2020-07-16T03:35:48Z"),
			"configVersion" : 1
		}
	],

重新启动node6

[root@bash mongodb]# mongod --config /etc/mongod27217.conf
about to fork child process, waiting until server is ready for connections.
forked process: 14545
child process started successfully, parent exiting

连接node7,查看状态
原来的node6 变为了 从节点

[root@bash mongodb]# mongo 192.168.200.77:27218
MongoDB shell version v4.2.8
connecting to: mongodb://192.168.200.77:27218/test?compressors=disabled&gssapiServiceName=mongodb
rs0:SECONDARY> rs.status()
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27217",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 670,
			"optime" : {
				"ts" : Timestamp(1594871318, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594871318, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T03:48:38Z"),
			"optimeDurableDate" : ISODate("2020-07-16T03:48:38Z"),
			"lastHeartbeat" : ISODate("2020-07-16T03:48:45.077Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T03:48:45.574Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27219",
			"syncSourceHost" : "192.168.200.77:27219",
			"syncSourceId" : 3,
			"infoMessage" : "",
			"configVersion" : 1
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27218",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 1907,
			"optime" : {
				"ts" : Timestamp(1594871318, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T03:48:38Z"),
			"syncingTo" : "192.168.200.77:27219",
			"syncSourceHost" : "192.168.200.77:27219",
			"syncSourceId" : 3,
			"infoMessage" : "",
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27219",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 835,
			"optime" : {
				"ts" : Timestamp(1594871318, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594871318, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T03:48:38Z"),
			"optimeDurableDate" : ISODate("2020-07-16T03:48:38Z"),
			"lastHeartbeat" : ISODate("2020-07-16T03:48:45.575Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T03:48:44.088Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1594870548, 1),
			"electionDate" : ISODate("2020-07-16T03:35:48Z"),
			"configVersion" : 1
		}
	],

增加、删除节点

拷贝node8到node10

修改node10的datapath、logpath的port,并将port 改为 27220,启动 node10

#拷贝相应配置文件
[root@bash mongodb]# cp -r log/mongod27219.log log/mongod27220.log
[root@bash mongodb]# cp -r data/db27219 data/db27220
[root@bash mongodb]# cp /etc/mongod27219.conf /etc/mongod27220.conf
[root@bash mongodb]# rm -fr data/db27220/*
[root@bash mongodb]# rm -fr log/mongod27220.log/*

#修改相应路径
[root@bash mongodb]# vim /etc/mongod27220.conf
...

#启动修改相应路径
[root@bash mongodb]# mongod --config /etc/mongod27220.conf
about to fork child process, waiting until server is ready for connections.
forked process: 14863
child process started successfully, parent exiting
[root@bash mongodb]# netstat -ntulp|grep 27220
tcp        0      0 0.0.0.0:27220           0.0.0.0:*               LISTEN      14863/mongod

增加节点

进入到主节点中,一定要在主节点中进行操:rs.add(“192.168.200.77:27220”)

[root@bash mongodb]# mongo 192.168.200.77:27219
MongoDB shell version v4.2.8
connecting to: mongodb://192.168.200.77:27219/test?compressors=disabled&gssapiServiceName=mongodb
rs0:PRIMARY> rs.add("192.168.200.77:27220")
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594876914, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594876914, 1)
}

查看状态

新增加的节点 为从节点,即 SECONDARY

rs0:PRIMARY> rs.status()
 	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.200.77:27217",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 6275,
			"optime" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T05:22:08Z"),
			"optimeDurableDate" : ISODate("2020-07-16T05:22:08Z"),
			"lastHeartbeat" : ISODate("2020-07-16T05:22:10.910Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T05:22:10.917Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27219",
			"syncSourceHost" : "192.168.200.77:27219",
			"syncSourceId" : 3,
			"infoMessage" : "",
			"configVersion" : 4
		},
		{
			"_id" : 2,
			"name" : "192.168.200.77:27218",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 6443,
			"optime" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T05:22:08Z"),
			"optimeDurableDate" : ISODate("2020-07-16T05:22:08Z"),
			"lastHeartbeat" : ISODate("2020-07-16T05:22:10.911Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T05:22:10.917Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27219",
			"syncSourceHost" : "192.168.200.77:27219",
			"syncSourceId" : 3,
			"infoMessage" : "",
			"configVersion" : 4
		},
		{
			"_id" : 3,
			"name" : "192.168.200.77:27219",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 6444,
			"optime" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T05:22:08Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1594870548, 1),
			"electionDate" : ISODate("2020-07-16T03:35:48Z"),
			"configVersion" : 4,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 4,
			"name" : "192.168.200.77:27220",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 16,
			"optime" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1594876928, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2020-07-16T05:22:08Z"),
			"optimeDurableDate" : ISODate("2020-07-16T05:22:08Z"),
			"lastHeartbeat" : ISODate("2020-07-16T05:22:10.912Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-16T05:22:11.109Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.200.77:27219",
			"syncSourceHost" : "192.168.200.77:27219",
			"syncSourceId" : 3,
			"infoMessage" : "",
			"configVersion" : 4
		}
	],

删除节点

rs.remove("192.168.200.77:27210")

rs0:PRIMARY> rs.remove("192.168.200.77:27220")
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1594876905, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1594876905, 1)
}

查看状态,发现 端口为27210的节点没有了