1、mongo集群分类
MongoDB集群有4种类型,分别是主从复制、副本集、分片集群和混合集群。
- MongoDB的主从复制是指在一个MongoDB集群中,一个节点(主节点)将数据写入并同步到其他节点(从节点)。主从复制提供了数据的冗余备份,并且可以实现高可用性和故障恢复。
-
副本集(Replica Set):副本集由一个主节点和多个从节点组成。主节点负责处理写入操作和数据同步,从节点负责处理读取操作。主节点的写入操作会异步地传播到所有从节点,保证数据的冗余和可用性。如果主节点不可用,从节点可以选举出一个新的主节点,实现自动故障转移。
-
分片集群(Sharded Cluster):分片集群将数据库分成多个分片,每个分片在不同的服务器上存储一部分数据。每个分片都是一个独立的MongoDB实例,负责存储和处理一部分数据。分片集群通过路由器将客户端的请求路由到正确的分片上。分片集群可以实现水平扩展,提高数据库的吞吐量和性能。
-
混合集群(Mixed Cluster):混合集群是复制集群和分片集群的结合。在混合集群中,每个分片都是一个复制集群,由主节点和从节点组成。这样在每个分片上可以实现故障转移和数据冗余的功能,同时通过分片集群的方式实现水平扩展。
每种类型的集群都有其适用场景和优势,选择合适的集群类型需要根据具体的业务需求和数据库规模来决定。下面演示如何使用docker部署副本集。
2、docker部署mongo副本集
2.1、配置mongo容器
新建容器卷目录
mkdir mongo01 && cd mongo01
mkdir -p conf data logs
cd conf
touch mongod.conf
编辑mongod.conf文本内容:
##设置数据存储目录
dbpath=/data/db
##设置日志存储文件
##logpath=data/log/mongod.log
##日志追加模式
logappend=true
##允许客户端任意ip连接
bind_ip=0.0.0.0
##绑定端口
port=27017
##副本集名称(非常重要)
replSet=rs
批量创建4个节点,挂载卷目录及端口映射
#!/bin/bash
docker run -d --name mongo01 -p 27018:27017 --privileged=true -v ./mongo01/data:/data/db -v ./mongo01/conf:/data/configdb -v ./mongo01/logs:/data/log/ mongo -f /data/configdb/mongod.conf
docker run -d --name mongo02 -p 27019:27017 --privileged=true -v ./mongo02/data:/data/db -v ./mongo02/conf:/data/configdb -v ./mongo02/logs:/data/log/ mongo -f /data/configdb/mongod.conf
docker run -d --name mongo03 -p 27020:27017 --privileged=true -v ./mongo03/data:/data/db -v ./mongo03/conf:/data/configdb -v ./mongo03/logs:/data/log/ mongo -f /data/configdb/mongod.conf
docker run -d --name mongo04 -p 27021:27017 --privileged=true -v ./mongo04/data:/data/db -v ./mongo04/conf:/data/configdb -v ./mongo04/logs:/data/log/ mongo -f /data/configdb/mongod.conf
通过docker exec进入第一个容器内部
docker exec -it mongo01 mongo
2.2、副本集操作命令
在 MongoDB 中,副本集(Replica Set)使用一系列特定的命令来进行管理和操作。以下是一些常用的 MongoDB 副本集命令
rs.add() | 添加成员到复制集 |
rs.addArb() | 添加仲裁节点 |
rs.conf() | 查看复制集配置 |
rs.freeze() | 阻止当前节点进行选举和接受写操作 |
rs.help() | 用户帮助手册 |
rs.initiate() | 初始化副本集 |
rs.reconfig() | 修改副本集的配置 |
rs.remove() | remove("hostname:port") - 从副本集中移除指定的成员 |
rs.secondaryOk() | 允许连接到副本集的 secondary 成员 |
rs.status() | 查看副本集状态 |
rs.stepDown() | 强制当前主节点成为 secondary 节点 |
2.3、关于主节点的选举
副本集在选取主节点的时候,需要由大多数决定,主节点只有在得到大多数支持才能继续作为主节点。这里的大多数定义为“副本集一半以上的成员”,如下表所示:
副本集中的成员总数 | 副本集中的大多数 |
1 | 1 |
2 | 2 |
3 | 2 |
4 | 3 |
5 | 3 |
6 | 4 |
7 | 4 |
注意:副本集中的大多数是基于副本集的配置来计算的。即使副本集中有些成员停止运行或者不可用时,不改变副本集的成员总数。
从上表可以看出,MongoDB副本集最少需要3个节点才能正常处理节点宕机的情况。一个副本集包含一个主节点(Primary)和若干个从节点(Secondary),以及一个仲裁节点(Arbiter)。主节点负责处理所有的写操作,并将数据同步到从节点上。从节点则负责复制主节点的数据,并可以处理读请求。仲裁节点用于在选举新的主节点时进行投票。
如下图所示,假如有一个包含5个成员的副本集,其中db1到db3不可用,db4,db5可以正常工作。这2个成员不能达到副本集的大多数成员规则(至少需要3个成员),因此无法选举出主节点。即使这2个成员其中一个之前是主节点,那么当它注意到无法得到大多数成员支持时,就会从主节点上退位。最终结果是,副本集包含2个从节点和3个无法访问的成员了。
那为什么剩下的2个成员不能选择出主节点呢?问题在于,db1到db3可能没有宕机,而只是因为网络故障不可达(地理隔离)。在这种情况下,左侧的3个成员将选举出一个主节点。我们不希望因为地理隔离而导致两边网络各自选择出一个主节点,因为那样副本集就拥有两个主节点,2个主节点都可以写入数据的话,整个副本集的数据便混乱了。只有得到“大多数成员支持”的情况才能选举和维持主节点,这是避免出现多个主节点的有效方式。
2.4、配置副本集
本文设置3个节点,1个仲裁节点。
rs.initiate({_id:"rs",members:[{_id:0,host:"192.168.0.121:27018"},{_id:1,host:"192.168.0.121:27019"},{_id:2,host:"192.168.0.121:27020"},{_id:3,host:"192.168.0.121:27021",arbiterOnly:true}]})
关于仲裁节点:
MongoDB副本集中只能有一个仲裁节点。仲裁节点是在副本集中用于投票和选举新主节点的节点。它不存储任何数据,只提供投票的功能。
2.5、navicat连接mongo副本集
专业版的navicat客户端不仅可以操作关系型数据库,也可以连接mongo,如下所示:
3、副本集测试案例
3.1、主节点进行写操作
进入主节点,插入测试数据
use test;
db.game.insert({"name":"LuckyDefense"})
3.2、从节点无法写数据,默认也无法读数据
exit退出容器,进入第二个节点(从节点)
docker exec -it mongo02 bash
执行命令
show databases;
从节点可能会因为延迟而缺少最新的写入数据,所以默认从节点不允许读取,以防止应用程序意外读取过期数据。如果期望在从节点进行查询操作,可以执行以下命令,即可。
rs.secondaryOk()
然而,在从节点尝试执行写入数据,会出现以下报错
报错显示,从节点不接受写操作。从节点只能通过复制功能写入数据,不接受客户端的写操作。
3.3、模拟节点宕机
当其中一个节点崩溃,服务对外仍可工作。模拟节点宕机情况,执行
docker stop mongo01
从navicat可以检测到副本集的状态(总共4个节点,剩余3个节点,可以重新选择新主节点),如下:
继续删除一个节点
docker stop mongo02
发现集群已经不可用。