MongoDB副本集群数据同步及主从复制

1、副本集群是什么

  MongoDB副本集群,也被称之为复制集群,其实和Redis、MySQL中的主从集群概念类似,只不过叫法上有所差异,就好比MQ中,称之为镜像集群,名词千变万化,理念殊途同归,内在含义都是:一个主节点拥有读写能力,一或多个从节点全量拷贝主节点的数据,对外提供读的能力。

    只不过这里要注意:MongoDB副本集群和传统的主从集群不太一样!无论是Redis,还是MySQL,它们只提供主从复制功能,即自动将主节点上写入的新数据,完整的同步给从节点。但它们并不提供故障迁移的功能!好比在Redis中,当主节点出现故障时,往往需要依靠外力来完成主从切换,因此通常会搭建“一主两从三哨兵”的架构,由哨兵来完成故障迁移的功能。

  而MongoDB副本集群,则无需任何外力介入,在主节点发生故障的情况下,无需任何外力介入,能自动完成主从切换,从而对外实现真正意义上的7*24h高可用,并且从节点还可以处理读请求,从而保障MongoDB服务的高性能。

  总的来说,MongoDB副本集群源自于主从集群,但在主从的基础上做了很大拓展,其中总共有三种节点角色:

  • Primary主节点:拥有读写能力,为集群内的副本节点,提供数据拷贝的支持;
  • Replicate副本节点:拥有读能力,数据完全拷贝自主节点,即主从概念中的从节点;
  • Arbiter仲裁节点:不具备读写能力,用于故障恢复,提供故障检测、选举投票能力。

  MongoDB副本集群中,出现了一个新概念:仲裁节点,其实作用等同于哨兵节点,但它并不是副本集群必须存在的节点,因为主节点、副本节点都拥有投票能力,它的存在只是为了维护集群内的平衡,如集群节点为偶数时,可以添加一个仲裁节点,让集群保持奇数特性,确保每轮选举一次就能推出新主,避免多轮无效竞选的现象出现(不了解选举机制的后面会说原理)。
好了,理论暂且说到这里,咱们先来搭建一个副本集群玩一玩,简单的实战一把。

2、副本集群实战

因为目前只是简单学习,这里选择搭建成本最低的“一主、一副本、一仲裁”集群,并且也不采用三台机器构建,而是基于“伪集群”的思想:

  • 单机模式:一台机器对外提供服务;
  • 集群模式:多台机器对外提供同一服务;
  • 伪集群模式:单台机器上启动多个实例,模拟多机器场景对外提供服务。

整个集群的节点关系如下:
在这里插入图片描述
其中主节点、副本节点、仲裁节点的端口分别为:27018、27019、27020
为每个节点创建存放数据、配置文件、日志的目录:

mkdir /app/mongodb/data/replication-cluster && 
mkdir /app/mongodb/log/replication-cluster && 
mkdir /app/mongodb/conf/replication-cluster && 
mkdir /app/mongodb/data/replication-cluster/27018 && 
mkdir /app/mongodb/data/replication-cluster/27019 && 
mkdir /app/mongodb/data/replication-cluster/27020 && 
mkdir /app/mongodb/log/replication-cluster/27018 && 
mkdir /app/mongodb/log/replication-cluster/27019 && 
mkdir /app/mongodb/log/replication-cluster/27020

编写主节点的配置文件:

vi /app/mongodb/conf/replication-cluster/27018.conf

MongoDB日志存储相关配置

systemLog:
    # 将所有日志写到指定文件中
    destination: file
    # 记录所有日志信息的文件路径
    path: "/app/mongodb/log/replication-cluster/27018/mongo.log"
    # 当服务重启时,将新日志以追加形式写到现有日志尾部
    logAppend: true
storage:
    # 指定MongoDB存储数据的目录
    dbPath: "/app/mongodb/data/replication-cluster/27018"
processManagement:
    # 以后台进程方式运行MongoDB服务
    fork: true
    # 指定保存mongo进程ID的文件位置
    pidFilePath: "/app/mongodb/conf/replication-cluster/27018.pid"
net:
    # 绑定服务实例的IP,默认是localhost,这里换成本机IP
    bindIp: 192.168.43.5
    #绑定的端口,默认是27017
    port: 27018
replication:
    # 指定副本集群的名称
    replSetName: panda

将上述配置信息复制、并根据自己的环境修改后,接着按下esc,输入:wq保存并退出。

启动主节点服务(依旧使用之前bin目录下的文件,只是换掉配置文件即可):

/app/mongodb/bin/mongod -f /app/mongodb/conf/replication-cluster/27018.conf

编写副本(从)节点的配置文件,由于和主节点的配置完全相同,因此直接copy一份,接着将相关目录、端口,批量替换成规划中的27019即可:

cd /app/mongodb/conf/replication-cluster/
cp 27018.conf 27019.conf
vi /app/mongodb/conf/replication-cluster/27019.conf

接着不要按insert键,直接输入:%s/27018/27019/g,完成批量替换(记得保存再退出)。

启动副本节点服务:

/app/mongodb/bin/mongod -f /app/mongodb/conf/replication-cluster/27019.conf

编写仲裁节点的配置文件,这里依旧拷贝27018.conf文件进行批量替换:

cp 27018.conf 27020.conf
vi /app/mongodb/conf/replication-cluster/27020.conf

输入:%s/27018/27020/g,完成批量替换,不要忘记保存。

启动仲裁节点服务:

/app/mongodb/bin/mongod -f /app/mongodb/conf/replication-cluster/27020.conf

通过mongosh客户端工具,连接27018主节点,初始化副本集群:

/app/mongodb/bin/mongosh 192.168.43.5:27018
rs.initiate();

执行上述初始化命令,只要看到ok:1这个字段值,说明初始化成功,接着稍等片刻,MongoDB会自动将当前连接的节点,设置为集群的主节点。

通过初始化的主节点,将其他节点加入到集群中,命令如下:

rs.add(host, arbiterOnly);

该方法有两个参数,前者是其他节点的IP:port,后者则是仅仲裁权力(可选参数),如果置为true,当前添加的节点则只有选举权力;如果为false,则拥有数据复制、选举的权力。
添加仲裁节点还有另外一个专门的方法,如下:

rs.addArb(host);

通过该方法添加的仲裁节点,只会拥有选举权力,并不参与副本集群中的数据维护工作。
通过上面的方法,将副本节点加入到集群中:

rs.add("192.168.43.5:27019");

上面添加副本节点没问题,当大家添加仲裁节点之前,需要更改一下默认的“写关注”级别,否则会报如下错误:

MongoServerError: Reconfig attempted to install a config that would change the 
    implicit default write concern. Use the setDefaultRWConcern command to set 
    a cluster-wide write concern and try the reconfig again.

这是因为MongoDB5.x以上的版本,集群内的写关注级别(数据同步模式),会根据节点数量而发生变化,当集群内添加新节点时,就会重新配置“写关注级别”,而仲裁节点并不参与数据同步,添加时就会出毛病,这时需要手动设置一下写关注级别:

db.adminCommand({
  "setDefaultRWConcern" : 1,
  "defaultWriteConcern" : {
    "w" : "majority"
  }
});

执行上述命令后,再执行添加仲裁节点的命令,

panda [direct: primary] test> rs.addArb("192.168.43.5:27020");

添加完成后,可以通过下述两个命令查看集群的节点配置、状态:

rs.conf();
rs.status();

其实所有副本集群相关的信息,都保存在local库的system.replset集合中,可以直接去查询这个集合。至此,副本集群的环境就搭建完毕,接着来看看节点之间的数据同步效果。

3、副本集群数据同步

在主节点上进行读写数据测试:

panda [direct: primary] test> use panda;
panda [direct: primary] panda> db.test.insert({_id:1});
panda [direct: primary] panda> db.test.find({_id:1});

此时主节点没有任何异样,读写数据操作都能正常执行。

新开另一个shell窗口,连接副本节点进行读写数据测试:

/app/mongodb/bin/mongosh 192.168.43.5:27019
panda [direct: secondary] test> use panda;
panda [direct: secondary] panda> db.test.find({_id:1});

报错MongoServerError: not primary and secondaryOk=false .....

此时执行数据读取命令时,又会出现新的报错,说咱们没有权限读取数据,这里需要开启一下权限:

panda [direct: secondary] test> rs.secondaryOk();

如果是4.0以下的版本,则是rs.slaveOk()方法,执行该方法后,再执行find就能正常读取数据。不过需要注意,该方法只针对当前shell有效,当重启shell或打开新的shell会话,需要再次执行该方法来允许读操作。
接着再重新执行读取命令,这时会发现,从节点会将主节点上写入的数据,自动同步过来:

panda [direct: secondary] panda> db.test.find({_id:1});
[ { _id: 1 } ]

同时,在副本节点上执行写操作时,会出现相关报错,提示当前并非主节点,不允许写入数据:

panda [direct: secondary] panda> db.test.insert({_id:2});

报错MongoBulkWriteError: not primary

再来连接仲裁节点看看情况:

/soft/mongodb/bin/mongosh 192.168.229.135:27020
panda [direct: secondary] test> rs.secondaryOk();
panda [direct: secondary] test> use zhuzi;
panda [direct: secondary] panda> db.test.find({_id:1});

在仲裁节点上执行任何读写操作时,都会出现这个错误:
MongoServerError: node is not in primary or recovering state
提示当前节点,既不是主节点,也不是从节点,所以无法执行相应命令。

到这里关于数据同步就操作完毕了,不过为了后续外部可以连接,可以顺便开放一下端口:

firewall-cmd --zone=public --add-port=27018/tcp --permanent
firewall-cmd --zone=public --add-port=27019/tcp --permanent
firewall-cmd --zone=public --add-port=27020/tcp --permanent
firewall-cmd --reload

下面来看看MongoDB副本集群中的故障自动切主功能。

4、副本集群主从切换

先通过ps命令查询所有mongodb的进程:

ps aux | grep mongodb

通过kill命令强杀27018主节点,模拟主节点宕机下线:

kill -9 42969

大概等待几秒钟左右,再去27019节点(原本的从)查看集群状态:

rs.status();

此时会发现,没有任何外力介入,副本集群自动完成了主从切换!

再次重启27018节点(旧主),观察集群的变化:

/app/mongodb/bin/mongod -f /app/mongodb/conf/replication-cluster/27018.conf

结果很显然,虽然“旧主复燃”,但它却没有夺回“老大”的身份,而是变成了“新主”的从节点。

将27018、27019节点,即主、从节点都干掉,再在仲裁节点上观察集群的状态:

kill -9 43032 47881

主、从节点已经失去心跳,整个集群处于不可工作状态,因为仲裁节点上没有数据,无法继续对外提供服务。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值