背景

公司需要安装mongdb副本集,保证和阿里云的生产环境一样,版本还是4.2,说实话我们根本用不到副本集事务和高可用的备份。还是乖乖听领导的话部署吧

Monodb副本集介绍

  • 副本集在mongodb中是是一组 mongod保持相同的数据集过程,副本集提供冗余和高可用性,并且是所有生产部署的基础。
  • 复制提供冗余并增加数据可用性,在不用数据库服务器上具有多个数据副本是,复制可以提供一个级别的单一数据库服务器丢失的容错能力。
  • 副本集可以支撑更高的读操作,因为客户端可以向不同的服务器发送读取操作,可以配置在不同的数据中心用作遭难恢复或者报告,备份。
  • 副本集成员最多50个,只有7个成员可以参与选举投票,多中心容灾能力,自动恢复,滚动式升级服务

部署Mongodb

阿里云的生产环境Mongodb部署模式为一主一从一仲裁,线下保持一致。

服务器信息

三台机器一样配置8核32G内存 存储盘500G

"host" : "172.31.28.23:27020"   主
"host" : "172.31.28.24:27020"   从
"host" : "172.31.28.25:27020"   仲裁

安装Mongodb

进入主节点机器172.31.28.23

修改配置文件

[root@VM-28-23 ~]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.8.tgz
[root@VM-28-23 ~]# tar -zxvf mongodb-linux-x86_64-rhel70-4.2.8.tgz -C /data/
[root@VM-28-23 ~]# mkdir /data/mongodb/{data,logs,pid,conf} -p
[root@VM-28-23 ~]# vim /data/mongodb/conf/mongodb.conf

systemLog:
  destination: file
  logAppend: true
  path: /data/mongodb/logs/mongod.log

storage:
  dbPath: /data/mongodb/data
  journal:
    enabled: true
  directoryPerDB: true
  wiredTiger:
     engineConfig:
        cacheSizeGB: 24   #如果一台机器启动一个实例这个可以注释选择默认,如果一台机器启动多个实例,需要设置内存大小,避免互相抢占内存
        directoryForIndexes: true

processManagement:
  fork: true
  pidFilePath: /data/mongodb/pid/mongod.pid

net:
  port: 27020
  bindIp: 172.31.28.23     #修改为本机IP地址
  maxIncomingConnections: 5000

#security:
  #keyFile: /data/mongodb/conf/keyfile
  #authorization: enabled
replication: #副本集用到的配置
   oplogSizeMB: 1024   #复制操作日志的大小
   replSetName: rs02  #副本集名称,同一个副本集的所有主机必须设置相同的名称

将配置复制到其他机器

[root@VM-28-23 ~]# scp -r /data/ root@172.31.28.24:/data/
[root@VM-28-23 ~]# scp -r /data/ root@172.31.28.25:/data/

将/data/mongodb/conf/mongodb.conf文件中的bindIp修改成各自机器的IP

启动Mongodb

下面操作需要在每台机器上执行

[root@VM-28-23 ~]# groupadd mongod
[root@VM-28-23 ~]# useradd -g mongod mongod
[root@VM-28-23 ~]# yum install -y libcurl openssl glibc
[root@VM-28-23 ~]# cd /data
[root@VM-28-23 ~]# ln -s mongodb-linux-x86_64-rhel70-4.2.8 mongodb-4.2
[root@VM-28-23 ~]# chown -R mongod.mongod /data
[root@VM-28-23 ~]# sudo -u mongod /data/mongodb-4.2/bin/mongod -f /data/mongodb/conf/mongodb.conf

初始化集群

准备一个config

config = { _id:“rs02”, members:[
… … {_id:0,host:“172.31.28.23:27020”,priority:90},
… … {_id:1,host:“172.31.28.24:27020”,priority:90},
… … {_id:2,host:“172.31.28.25:27020”,arbiterOnly:true}
… … ]
… … }

[root@VM-28-23 ~] #cd /data/mongodb-4.2/bin
[root@VM-28-23 bin]# ./mongo 172.31.28.23:27020
> use admin
switched to db admin
> config = { _id:"rs02", members:[
... ...                      {_id:0,host:"172.31.28.23:27020",priority:90},
... ...                      {_id:1,host:"172.31.28.24:27020",priority:90},
... ...                      {_id:2,host:"172.31.28.25:27020",arbiterOnly:true}
... ...               ]
... ... }
{
	"_id" : "rs02",
	"members" : [
		{
			"_id" : 0,
			"host" : "172.31.28.23:27020",
			"priority" : 90
		},
		{
			"_id" : 1,
			"host" : "172.31.28.24:27020",
			"priority" : 90
		},
		{
			"_id" : 2,
			"host" : "172.31.28.25:27020",
			"arbiterOnly" : true
		}
	]
}
> rs.initiate(config);
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1595209506, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1595209506, 1)
}

查看节点状态

rs02:SECONDARY> rs.status()
{
	"set" : "rs02",
	"date" : ISODate("2020-07-20T01:45:29.117Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncingTo" : "",
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 2,
	"writeMajorityCount" : 2,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1595209518, 1),
			"t" : NumberLong(1)
		},
		"lastCommittedWallTime" : ISODate("2020-07-20T01:45:18.603Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1595209518, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityWallTime" : ISODate("2020-07-20T01:45:18.603Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1595209518, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1595209518, 1),
			"t" : NumberLong(1)
		},
		"lastAppliedWallTime" : ISODate("2020-07-20T01:45:18.603Z"),
		"lastDurableWallTime" : ISODate("2020-07-20T01:45:18.603Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1595209517, 3),
	"lastStableCheckpointTimestamp" : Timestamp(1595209517, 3),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-07-20T01:45:17.641Z"),
		"electionTerm" : NumberLong(1),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(0, 0),
			"t" : NumberLong(-1)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1595209506, 1),
			"t" : NumberLong(-1)
		},
		"numVotesNeeded" : 2,
		"priorityAtElection" : 90,
		"electionTimeoutMillis" : NumberLong(10000),
		"numCatchUpOps" : NumberLong(0),
		"newTermStartDate" : ISODate("2020-07-20T01:45:17.693Z"),
		"wMajorityWriteAvailabilityDate" : ISODate("2020-07-20T01:45:18.590Z")
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "172.31.28.23:27020",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 246,
			"optime" : {
				"ts" : Timestamp(1595209518, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-07-20T01:45:18Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "could not find member to sync from",
			"electionTime" : Timestamp(1595209517, 1),
			"electionDate" : ISODate("2020-07-20T01:45:17Z"),
			"configVersion" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 1,
			"name" : "172.31.28.24:27020",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 22,
			"optime" : {
				"ts" : Timestamp(1595209518, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1595209518, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-07-20T01:45:18Z"),
			"optimeDurableDate" : ISODate("2020-07-20T01:45:18Z"),
			"lastHeartbeat" : ISODate("2020-07-20T01:45:27.655Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-20T01:45:28.551Z"),
			"pingMs" : NumberLong(1),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "172.31.28.23:27020",
			"syncSourceHost" : "172.31.28.23:27020",
			"syncSourceId" : 0,
			"infoMessage" : "",
			"configVersion" : 1
		},
		{
			"_id" : 2,
			"name" : "172.31.28.25:27020",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 22,
			"lastHeartbeat" : ISODate("2020-07-20T01:45:27.654Z"),
			"lastHeartbeatRecv" : ISODate("2020-07-20T01:45:27.393Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 1
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1595209518, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1595209518, 1)
}
rs02:PRIMARY>

验证副本集数据复制功能

#主节点
use test
db.createCollection('user')
db.user.insert({'name':'james'})
 
#从节点
use test
show collections
db.user.find()

发现主节点的数据在从节点能读到。

至此Mongodb副本集算是安装完了,如果需要开权限认证,请往后看~

Mongodb权限认证

副本集配置用户和密码,登录主节点,添加admin 用户。

> use admin
switched to db admin
> db.createUser({ user: "admin", pwd: "123456", roles: [{ role: "root", db: "admin" }] })
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}

在主节点生成 keyflie 并复制到其它两个节点

# 生成 keyFile
openssl rand -base64 90 -out /data/mongodb-4.2/keyfile

# 复制到其它两个节点
scp keyfile root@172.31.28.24:/data/mongodb-4.2/
scp keyfile root@172.31.28.25:/data/mongodb-4.2/

# 更改三个节点的 keyFile 文件权限和所有者
chmod 600 /data/mongodb-4.2/keyfile
chown mongod:mongod /data/mongodb-4.2/keyfile

更改三个节点的 mongodb.conf 配置文件

将 security 的参数 authorization 设置为 enabled,并配置
keyFile 的路径。

vim /data/mongodb/conf/mongodb.conf

security:
   authorization: "enabled"
   keyFile: '/data/mongodb-4.2/keyfile'
   clusterAuthMode: "keyFile"
   
然后依次重启mongdb01、02、03

# 关闭
sudo -u mongod /data/mongodb-4.2/bin/mongod --shutdown   --dbpath /data/mongodb/data

# 启动
sudo -u mongod /data/mongodb-4.2/bin/mongod -f /data/mongodb/conf/mongodb.conf

测试权限验证

登陆主节点

> show dbs
> use admin
switched to db admin
> db.auth('admin','123456')
1
> show dbs
admin   0.000GB
config  0.000GB
local   0.002GB
test    0.000GB

权限认证则验证完成

Mongodb常用管理命令

# 副本集初始化
rs.initiate( {
   _id : "rs0",
   members: [
      { _id: 0, host: "mongodb0.example.net:27017" },
      { _id: 1, host: "mongodb1.example.net:27017" },
      { _id: 2, host: "mongodb2.example.net:27017" }
   ]
})
# 副本集添加成员
rs.add('mongodb3.example.net:27017')
# 副本集添加仲裁节点
rs.addArb('mongodb4.example.net:27017')
# 移除节点
rs.remove('hostportstr')
# 查看当前的配置
rs.conf()
# 查看各个节点状态和身份
rs.status()
# 设定某个节点多少秒不可成为主节点
rs.freeze(secs)
# 设置次节点从指定节点同步数据
rs.syncFrom(hostportstr)
# 降低主节点为次节点,只能在主节点上运行
rs.stepDown([stepdownSecs, catchUpSecs])
# 查看帮助
rs.help()
# 次节点执行,表示允许次节点读取数据
rs.slaveOk()
# 判断当前节点是否是主节点
rs.isMaster()
# 查看 Oplog 信息
rs.printReplicationInfo()
#  查看副本集的次节点与主节点延迟
db.printSlaveReplicationInfo()
# 移除原有副本集命令
use local
db.system.replset.remove({})
# 关闭 mongodb进程服务
use admin
db.shutdownServer()

参考资料

Mongodb 4.2版本副本集配置

MongoDB-副本集搭建与管理