MongoDB——MongoDB复制集

MongoDB复制集概述

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

复制集的优势:

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

复制集工作原理

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

  • 主节点记录所有变化到oplog日志,从节点复制主节点的oplog并将这些日志在从节点重做,各个节点之间会定期发送心跳信息,一旦主机宕机,则触发选举出一个新的主节点,剩余从节点指向新的主节点
  • 集群存活节点小于等于二分之一时集群不可写,只可读,是否能选举出新的主节点,是由当前复制集成员存活数量来决定的
  • 三类节点
    • 标准(host)节点:存储数据,可能被选为活跃(primary)节点,有选举权
    • 被动(passive)节点:被动节点有完整副本,不可能成为活跃节点,有选举权
    • 仲裁(arbiter)节点:负责选举,不存储数据,不能充当主从节点

复制集特点:

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

MongoDB复制集部署

配置复制集

准备工作 创建数据文件和日志文件存储路径
并且更改不同实例的配置文件
因为工作重复度高 因此写一个脚本

#!/bin/bash
CONF=/usr/local/mongodb/bin
DATA=/data
LOGS=/data/logs/mongodb
NUM1=27017
echo 'export PATH=$PATH:/usr/local/mongodb/bin' >> /etc/profile
source /etc/profile

mkdir -p $DATA &>/dev/null
mkdir -p $LOGS &>/dev/null

menu() {
cat <<-EOF
        #########################
        #    1.创建实例         #
        #    2.开启所有实例     #
        #    3.关闭所有实例     #
        #########################
        EOF
}
menu
read -p '想创建几个实例:' NUM2
read -p '请输入Mongodb服务器的ip地址:' IP
NUM=$[ $NUM1 + $NUM2 ]
for ((i=$NUM1;i<$NUM;i++))
do
        mkdir -p $DATA/mongodb-$i
        touch $LOGS/mongodb-$i.log
        chmod -R 777 $LOGS/mongodb-$i.log
        cat /etc/mongod.conf |grep -v '^#' |grep -v '^$' > $CONF/mongod-$i.conf
        sleep 1
        sed -ri "/path/c \  path: $LOGS/mongodb-$i.log" $CONF/mongod-$i.conf &>/dev/null
        sed -ri "/dbPath/c \  dbPath: $DATA/mongodb-$i" $CONF/mongod-$i.conf &>/dev/null
        sed -ri "/port:/c \  port: $i" $CONF/mongod-$i.conf &>/dev/null
        sed -ri "/bindIp:/c \  bindIp: $IP" $CONF/mongod-$i.conf &>/dev/null
        
done    
}

kai() {
        read -p '开启几个实例:' NUM2
        NUM=$[ $NUM1 + $NUM2 ]
        for ((i=$NUM1;i<=$NUM;i++))
        do
                mongod -f $CONF/mongod-$i.conf
        done
        ss -ntl
}

guan() {
        read -p '关闭几个实例:' NUM2
        NUM=$[ $NUM1 + $NUM2 ]
        for ((i=$NUM1;i<=$NUM;i++))
        do
                mongod -f $CONF/mongod-$i.conf --shutdown
        done
        ss -ntl
}

while :
do

read -p '请输入你想执行的功能(h返回菜单,q退出):' action
case $action in
1)
        shili
        ;;
2)
        kai
        ;;
3)
        guan
        ;;
h)
        menu
        ;;
q)
        break
        ;;
*)
        echo '请选择正确选项!'
esac
done

在四个节点的配置文件里添加

replication:
  oplogSizeMB: 2048			带宽
  replSetName: maomao		复制集的名字

进入主节点进行复制集的配置

重启mongod之后 进入
mongo --host 192.168.188.101 --port 27017

> show dbs;		# 报错:说明复制集还未配置
2021-04-20T01:56:01.317-0400 E QUERY    [thread1] Error: listDatabases failed:{
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:814:19
shellHelper@src/mongo/shell/utils.js:704:15
@(shellhelp2):1:1

查看复制集的状态
> 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"
}

配置复制集
 config={_id:"maomao",members[
 {_id:0,host:"192.168.188.101:27017"},
 {_id:1,host:"192.168.188.101:27018"},
 {_id:2,host:"192.168.188.101:27019"}]} 

{
	"_id" : "maomao",
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.188.101:27017"
		},
		{
			"_id" : 1,
			"host" : "192.168.188.101:27018"
		},
		{
			"_id" : 2,
			"host" : "192.168.188.101:27019"
		}
	]
}

初始化复制集
注意:初始化之前 必须清空所有的数据库 不然会失败
删除对应的Mongodb文件数据目录里面的所有东西就行了
rs.initiate(config)
{ "ok" : 1 }

验证

初始化完成后的服务器会拥有other状态,这代表着他们正在进行投票
maomao:OTHER>

当投票完成后,默认会选举初始化的这台数据库变为主库

maomao:PRIMARY> 

另外两个节点
mongo --host 192.168.188.101 --port 27018
maomao:SECONDARY>

再次通过rs.status()查看复制集完整信息
maomao:PRIMARY> rs.status()

其中health 1为健康,0代表宕机
state为1 表示主节点,2为从节点
...
			"_id" : 1,
			"name" : "192.168.188.101:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
...

增加和删除节点

配置启动复制集后,还可以通过rs.add()rs.remove()命令方便地添加或删除节点

maomao:PRIMARY> rs.remove("192.168.188.101:27020")
{ "ok" : 1 }

maomao:PRIMARY> rs.status()
可以查看到新添加节点的信息

maomao:PRIMARY> rs.remove("192.168.188.101:27020")
{ "ok" : 1 }

MongoDB 复制集切换

MongoDB 复制集可以实现集群的高可用,当其中主节点出现故障时,会自动切换到其他节点。管理员也可以手动进行复制集的主从切换

故障自动切换

我们将主节点关闭
[root@mongodb bin]# mongod -f mongod-27017.conf --shutdown
killing process with pid: 3097
[root@mongodb bin]# ss -ntl
State       Recv-Q Send-Q                 Local Address:Port                                Peer Address:Port              
LISTEN      0      128                  192.168.188.101:27018                                          *:*                  
LISTEN      0      128                  192.168.188.101:27019                                          *:*                  
LISTEN      0      128                  192.168.188.101:27020                                          *:*   

发现20718节点成为主节点
查看状态
maomao:PRIMARY> rs.status()

可以发现原"_id"为0的主节点出现故障之后,主节点自动切换到"_id"为1的节点上了

然后将之前的主节点恢复 结果发现旧的主节点成为了从节点
[root@mongodb bin]# mongod -f mongod-27017.conf

maomao:SECONDARY>

手动主从切换

原理是进入到主数据库使得数据库进行短暂的休眠,并且主动交出主节点位置

暂停30s不参加竞选
maomao:PRIMARY> rs.freeze(30)
{
	"ok" : 0,
	"errmsg" : "cannot freeze node when primary or running for election. state: Primary",
	"code" : 95,
	"codeName" : "NotSecondary"
}

交出主节点位置,维持从节点状态不少于60s,同时等待30s,使主节点和从节点日志同步

maomao:PRIMARY> rs.stepDown(60,30)
2021-04-20T02:38:16.098-0400 E QUERY    [thread1] Error: error doing query: failed: network error while att
empting to run command 'replSetStepDown' on host '192.168.188.101:27018'  :DB.prototype.runCommand@src/mongo/shell/db.js:132:1
DB.prototype.adminCommand@src/mongo/shell/db.js:150:16
rs.stepDown@src/mongo/shell/utils.js:1351:12
@(shell):1:1
2021-04-20T02:38:16.101-0400 I NETWORK  [thread1] trying reconnect to 192.168.188.101:27018 (192.168.188.10
1) failed2021-04-20T02:38:16.101-0400 I NETWORK  [thread1] reconnect 192.168.188.101:27018 (192.168.188.101) ok

然后发现27018成为了从节点
maomao:SECONDARY> 

27019成为了主节点
maomao:SECONDARY> 
maomao:PRIMARY> 

MongoDB 复制选举原理

MongoDB在副本集中,会自动进行主节点的选举,主节点选举的触发条件:

  1. 主节点故障
  2. 主节点网络不可达(默认心跳信息为10秒)
  3. 人工干预(rs.stepDown(600))

一旦触发选举,就要根据一定规则来选主节点。

选举规则是根据票数来决定谁获胜:

  • 票数最高,且获得了“大多数”成员的投票支持的节点获胜

    • “大多数”的定义为:假设复制集内投票成员数量为N,则大多数为 N/2 + 1。例如:3个投票成员,
      则大多数的值是2。当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,
      复制集将无法提供写服务,处于只读状态。
  • 若票数相同,且都获得了“大多数”成员的投票支持的,数据新的节点获胜

  • 数据的新旧是通过操作日志oplog来对比的。

在获得票数的时候,优先级(priority)参数影响重大

可以通过设置优先级(priority)来设置额外票数。优先级即权重,取值为0-1000,相当于可额外增加
0-1000的票数,优先级的值越大,就越可能获得多数成员的投票(votes)数。指定较高的值可使成员更有资格成为主要成员,更低的值可使成员更不符合条件

默认情况下,优先级的值是1

查看oplog日志

maomao:PRIMARY> db.oplog.rs.find()

其中每个文档都代表主节点上执行的一个操作,oplog会包含所有对数据有修改的操作(查询操作不会记录)

配置复制集的优先级

  • 三类节点
    • 标准(host)节点:存储数据,只有标准节点才可能被选为活跃(primary)节点,有选举权
    • 被动(passive)节点:被动节点有完整副本,不可能成为活跃节点,有选举权
    • 仲裁(arbiter)节点:负责选举,不存储数据,不能充当主从节点

重新配置4个节点的MongoDB 复制集,设置两个标准节点,一个被动节点和一个仲裁节点

maomao:PRIMARY> config={_id:"maomao",members:[{_id:0,host:"192.168.188.101:27017",priority:0},{_id:1,host:"
192.168.188.101:27018",priority:100},{_id:2,host:"192.168.188.101:27019",priority:100},{_id:3,host:"192.168.188.101:27020",arbiterOnly:true}]}

{
	"_id" : "maomao",
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.188.101:27017",
			"priority" : 0
		},
		{
			"_id" : 1,
			"host" : "192.168.188.101:27018",
			"priority" : 100
		},
		{
			"_id" : 2,
			"host" : "192.168.188.101:27019",
			"priority" : 100
		},
		{
			"_id" : 3,
			"host" : "192.168.188.101:27020",
			"arbiterOnly" : true
		}
	]
}

激活
maomao:PRIMARY> rs.reconfig(config)
{ "ok" : 1 }

查看节点信息
maomao:PRIMARY> rs.isMaster()
{
	"hosts" : [
		"192.168.188.101:27018",
		"192.168.188.101:27019"
	],
	"passives" : [
		"192.168.188.101:27017"
	],
	"arbiters" : [
		"192.168.188.101:27020"
	],

其中hosts 包含标准节点
passives 包含被动节点
arbiters 包含仲裁节点

模拟主节点故障

主节点故障 另一个标准节点将会成为新的主节点

mongod -f /usr/local/mongodb/bin/mongod-27019.conf  --shutdown

maomao:PRIMARY> rs.status()
查看信息

当主节点为第一个标准节点出现故障后,MongoDB复制集会选举第二个标准节点为主节点

如果所有标准节点都故障,被动节点也不能成为主节点

MongoDB 复制集管理

配置允许在从节点读取数据

默认MongoDB 复制集的从节点不能读取数据,可以使用rs.slaveOk()命令允许能够在从节点读取数据

进入从节点
mongo --host 192.168.188.101 --port 27017

这时候无法读取数据
maomao:SECONDARY> show dbs
2021-04-20T03:09:14.589-0400 E QUERY    [thread1] Error: listDatabases failed:{
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:814:19
shellHelper@src/mongo/shell/utils.js:704:15
@(shellhelp2):1:1

允许能够在从节点读取数据
maomao:SECONDARY> rs.slaveOk()

maomao:SECONDARY> show dbs
admin  0.000GB
local  0.000GB

查看复制状态信息

可以使用rs.printReplicationInfo()rs.printSlaveReplicationInfo() 命令来查看复制集状态

maomao:SECONDARY> rs.printReplicationInfo()
configured oplog size:   2048MB
log length start to end: 3597secs (1hrs)
oplog first event time:  Tue Apr 20 2021 02:11:44 GMT-0400 (EDT)
oplog last event time:   Tue Apr 20 2021 03:11:41 GMT-0400 (EDT)
now:                     Tue Apr 20 2021 03:11:43 GMT-0400 (EDT)
maomao:SECONDARY> rs.printSlaveReplicationInfo()
source: 192.168.188.101:27017
	syncedTo: Tue Apr 20 2021 03:12:01 GMT-0400 (EDT)
	0 secs (0 hrs) behind the primary 
source: 192.168.188.101:27019
	syncedTo: Tue Apr 20 2021 03:12:01 GMT-0400 (EDT)
	0 secs (0 hrs) behind the primary 

更改oplog大小

  • oplog默认占用实例5%大小,复制过程中,如果oplog不够大,因为同步时间差,可能导致从节点跟不上主节点。因此需要保证主节点oplog足够大

  • 更改命令:

    db.runCommand({"convertToCapped":"oplog.rs","size":102400000})
    
maomao:PRIMARY> use local
switched to db local
maomao:PRIMARY> db.oplog.rs.stats()
{
	"ns" : "local.oplog.rs",
	"size" : 35566,
	"count" : 370,
	"avgObjSize" : 96,
	"storageSize" : 49152,

maomao:PRIMARY> rs.printReplicationInfo()
configured oplog size:   2048MB
log length start to end: 3847secs (1.07hrs)
oplog first event time:  Tue Apr 20 2021 02:11:44 GMT-0400 (EDT)
oplog last event time:   Tue Apr 20 2021 03:15:51 GMT-0400 (EDT)
now:                     Tue Apr 20 2021 03:15:55 GMT-0400 (EDT)

maomao:PRIMARY> db.runCommand({"convertToCapped":"oplog.rs","size":102400000})
{ "ok" : 1 }

部署认证的复制

maomao:PRIMARY> use admin
switched to db admin

maomao:PRIMARY> db.createUser({user:"root",pwd:"123",roles:["root"]})
Successfully added user: { "user" : "root", "roles" : [ "root" ] }

关闭四个节点
killing process with pid: 3492
killing process with pid: 3782
killing process with pid: 3684
killing process with pid: 3620

mkdir /data/user

生成秘钥文件
openssl rand -base64 756  > /data/user/testKeyFile.file

修改权限
chmod 400 /data/user/testKeyFile.file

cp /data/user/testKeyFile.file /data/user/testKeyFile1.file 
cp /data/user/testKeyFile.file /data/user/testKeyFile2.file 
cp /data/user/testKeyFile.file /data/user/testKeyFile3.file

在每个节点配置文件里添加
security:
  keyFile: /data/user/testKeyFile.file
  authorization: enabled

注意:每个节点testKeyFile.file 名字不一样

启动数据库
[root@mongodb ~]# mongo --host 192.168.188.101 --port 27019
MongoDB shell version v3.4.24
connecting to: mongodb://192.168.188.101:27019/
MongoDB server version: 3.4.24

不能读取数据 需要验证用户
maomao:PRIMARY> show dbs
2021-04-20T03:31:58.572-0400 E QUERY    [thread1] Error: listDatabases failed:{
	"ok" : 0,
	"errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
	"code" : 13,
	"codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:814:19
shellHelper@src/mongo/shell/utils.js:704:15
@(shellhelp2):1:1

maomao:PRIMARY> use admin
switched to db admin

maomao:PRIMARY> db.auth("root","123")
1

maomao:PRIMARY> show dbs
admin  0.000GB
local  0.000GB

认证用户成功
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值