MongoDB集群介绍:
MongoDB 副本集是由多个MongoDB实例组成的集群,其中包含一个主节点(Primary)和多个从节点(Secondary),用于提供数据冗余和高可用性。以下是搭建 MongoDB 副本集的详细步骤,以在 Linux 系统(假设为 Ubuntu)上为例,可以根据实际情况进行调整。
1、MongoDB集群部署的两种方法的原理及优缺点
MongoDB 的副本集(Replica Set)和分片集(Sharded Cluster)是两种重要的集群架构,它们的原理、优缺点如下:
1.1、副本集原理
- 原理:副本集由多个 MongoDB 实例组成,其中有一个主节点(Primary)和多个从节点(Secondary)。主节点负责处理所有的写操作,并将这些操作记录在操作日志(oplog)中。从节点通过复制主节点的 oplog 来保持与主节点的数据同步。当主节点出现故障时,副本集通过选举机制(通常基于 Bully 算法的变体)从从节点中选出一个新的主节点,以保证服务的连续性。
- 优点:
- 高可用性:主节点故障时,从节点能快速被选举为新主节点,继续提供服务,减少停机时间。
- 数据冗余:多个节点存储相同数据,防止因单个节点硬件故障导致数据丢失。
- 读扩展性:可以将读请求分发到从节点,减轻主节点压力,提高整体读性能。适合读多写少的场景。
- 数据一致性:通过 oplog 复制,能保证副本集内节点数据的最终一致性。
- 缺点:
- 写性能瓶颈:所有写操作都集中在主节点,当写操作量较大时,主节点可能成为性能瓶颈。
- 存储限制:所有节点都存储完整数据,对于数据量非常大的情况,存储成本较高,且扩展存储容量较困难。
- 选举延迟:主节点故障时,选举新主节点需要一定时间,期间可能影响服务可用性。
1.2、分片集
- 原理:分片集由多个组件构成,包括分片(Shard)、配置服务器(Config Server)和路由服务器(MongoS)。数据被分割成多个数据块(Chunk),分布在不同的分片上。配置服务器存储着集群的元数据,如数据块的分布信息等。路由服务器负责接收客户端的请求,并根据元数据将请求转发到相应的分片上。当数据量增加或负载不均衡时,系统会自动进行数据块的迁移和平衡,以保持集群的性能和可用性。
- 优点:
- 可扩展性:通过添加更多的分片,可以轻松扩展集群的存储容量和处理能力,应对不断增长的数据量和负载。
- 性能提升:读写操作被分散到多个分片上,减少了单个节点的负载,提高了整体性能,尤其适合大数据量和高并发的场景。
- 负载均衡:自动的数据块迁移机制可以确保各个分片之间的负载均衡,避免出现某个分片负载过高的情况。
- 缺点:
- 架构复杂:涉及多个组件(分片、配置服务器、路由服务器等),部署、管理和维护的难度较大,需要较高的技术水平。
- 数据一致性挑战:由于数据分布在多个分片上,跨分片的事务处理相对复杂,可能会出现数据一致性问题,虽然 MongoDB 提供了一定的事务支持,但与传统关系型数据库相比仍有局限。
- 元数据管理风险:配置服务器存储关键的元数据,一旦配置服务器出现故障或元数据损坏,可能导致整个集群无法正常工作,需要采取额外的备份和恢复措施。
副本集适用于对高可用性和数据冗余有要求,且数据量和写操作不是特别大的场景;而分片集则更适合处理大规模数据和高并发读写的应用,尽管它在管理上更为复杂。
MongoDB 集群主要通过副本集和分片集群两种方式实现,不同集群模式下的节点选取原理有所不同,以下为你详细介绍:
2、集群故障选取原理
2.1、副本集的节点选取原理
副本集是由多个 MongoDB 实例组成,包含一个主节点(Primary)和多个从节点(Secondary),其节点选取主要涉及主节点选举。
- 选举触发条件:当副本集启动、主节点发生故障(如网络故障、进程崩溃等)或手动进行重新配置时,会触发主节点选举。
- 选举算法:MongoDB 使用改进的 Bully 算法来进行主节点选举。在该算法中,每个节点都有一个优先级(Priority),取值范围是 0 到 100,默认值为 1。优先级为 0 的节点不能成为主节点,只能作为从节点。
- 选举过程:
- 具有最高优先级且可用的节点将被优先选为候选主节点。如果多个节点优先级相同,则具有最新
oplog
(操作日志)的节点将更有可能被选为候选主节点。 - 节点之间通过心跳机制(使用
ping
操作)来检测彼此的状态。当一个节点认为主节点不可用时,它会发起选举。 - 候选主节点会向其他节点发送选举请求(
ELECTION
消息)。其他节点收到请求后,会根据一定的规则进行响应。如果候选主节点收到大多数节点(超过副本集节点总数一半的节点)的支持投票,它将成为新的主节点。 - 新的主节点选举成功后,会向其他节点发送确认消息,从节点会开始与主节点进行数据同步。
- 具有最高优先级且可用的节点将被优先选为候选主节点。如果多个节点优先级相同,则具有最新
2.2、分片集群的节点选取原理
分片集群由多个组件组成,包括分片(Shard)、配置服务器(Config Server)和路由服务器(MongoS),节点选取涉及客户端请求的路由和数据的定位。
- 客户端请求路由:客户端应用程序连接到路由服务器(MongoS),MongoS 负责接收客户端的请求,并将其路由到正确的分片上。MongoS 维护着一份来自配置服务器的元数据,这些元数据记录了数据的分布情况(即哪些数据存储在哪个分片上)。
- 数据定位:当客户端发送一个读写请求时,MongoS 首先检查请求的数据库和集合,然后根据元数据确定数据所在的分片。例如,如果请求是读取某个文档,MongoS 会查找元数据中关于该文档所在分片的信息,并将请求转发到相应的分片上。
- 分片内部的操作:在分片内部,每个分片本身可以是一个副本集。当分片接收到请求后,副本集中的主节点会处理读和写操作。如果是读请求,主节点可以直接返回数据;如果是写请求,主节点会将操作记录到
oplog
中,并将数据同步到从节点。 - 配置服务器的作用:配置服务器存储着整个分片集群的元数据,包括分片的信息、数据块(Chunk)的分布等。MongoS 会定期从配置服务器获取最新的元数据,以确保路由的准确性。当集群的配置发生变化(如添加或删除分片、重新平衡数据等)时,配置服务器会更新元数据,并通知相关的 MongoS。
MongoDB 通过上述原理实现了副本集和分片集群的节点选取和请求处理,以提供高可用性、可扩展性和数据分布的能力。
背景:
在本次搭建中根据生产的机器的磁盘空间来规划,因为客户机器资源有限只有两台机器作为数据存储节点,但要求要有数据备份以满足容灾需求,所以我们选择采用副本集的形式来进行部署。
结合实际情况考虑:采用一主、一从、一仲裁节点来部署MongoDB副本集;因为仲裁节点不存放数据所以满足生产场景需求(如果资源充裕也可以根据业务需要部署一主多从或者有性能上的需求也可以部署分片集)。
一、环境准备
主机名 | IP | 角色 | 备注 |
master | 192.168.47.162 | PRIMARY | mongo主节点优先级指数为:2 |
agent1 | 192.168.47.163 | SECONDARY | 副本节点(同步主节点的数据,优先级指数为1) |
agent2 | 192.168.47.164 | ARBITER | 仲裁节点不存储数据,在故障时参与选举PRIMARY节点 |
二、安装MongoDB服务
1、解压安装包
cd /opt/sumscope && tar -zxvf mongodb-5.0.4.tar.gz
2、修改配置文件
fork = true
bind_ip = 0.0.0.0
port = 27017
dbpath = /opt/sumscope/mongodb/data
logpath = /opt/sumscope/mongodb/logs/mongodb.log
auth = true
keyFile = /opt/sumscope/mongodb/config/mongo.keyfile
replSet = rs0
3、修改环境变量
# 在文件最后一行加入
[root@server111 local]# vim /etc/profile
PATH=$PATH:/opt/sumsscope/mongodb/bin
export PATH
[root@server111 local]# source /etc/profile
4、开启用户认证
openssl rand -base64 753 > /opt/sumscope/mongodb/config/mongo.keyfile
chmod 600 /opt/sumscope/mongodb/config/mongo.keyfile
scp -rp /opt/sumscope/mongodb/config/mongo.keyfile root@agent1:/opt/sumscope/mongodb/config
scp -rp /opt/sumscope/mongodb/config/mongo.keyfile root@agent2:/opt/sumscope/mongodb/config
5、将mongo配置成系统服务
注意:mongodb.service得自己编写
cd /opt/sumscope/mongodb/scripts
#注意:如果部署路径不一致将mongodb.service的启停命令进行修改
cp mongodb.service /lib/systemd/system
chmod +755 /lib/systemd/system/mongodb.service
systemctl daemon-reload
三、初始化MongoDB集群节点
1、在主机点上进行初始化操作
use admin
rs.initiate({_id:"rs0", members:[{_id:0, host:"192.168.47.162:27017"}, {_id:1,host:"192.168.47.163:27017"}]})
2、加入仲裁节点
先执行如下命令,不然加入仲裁执行会很慢
db.adminCommand({
"setDefaultRWConcern" : 1,
"defaultWriteConcern" : {
"w" : 2
}
})
再执行
rs.addArb("192.168.47.164:27017")
3、创建root用户所属库为admin
db.createUser({ "user":"root","pwd":"ppp","roles":[ { role: "readWriteAnyDatabase", db: "admin" },{ role: "root", db: "admin" },"readWrite"]})
4、创建tbook数据库,所属用户stc
use admin
db.auth('root','ppp')
use tbook
db.createUser({user:"stc",pwd:"ppp",roles:[{role:'dbOwner',db:'tbook'}]})
5、写入数据验证
use tbook
db.auth('stc','ppp')
#插入数据
db.ttab.insert({name:'test2-1',url:'https://www.test2-1.cn'})
四、节点优先级设置
1、优先级设置背景
- PRIMARY:1
- SECONDARY: 1
- ARBITER:0
- PRIMARY:2 (master 主机)
- SECONDARY: 1 (agent1 主机)
- ARBITER:0 (agent2 主机)
2、节点优先级设置命令
/opt/sumscope/mongodb/bin/mongo
#进入admin库进入
rs0:PRIMARY> use admin
rs0:PRIMARY> db.auth('root','passwd')
#查看副本集信息
rs0:PRIMARY> rs.status();
#查看副本的优先级
rs0:PRIMARY> rs.config();
########修改优先级###########
#使用如下命令获取到副本集中的配置信息,并赋值给变量(后面将通过这个变量修改配置)
rs0:PRIMARY> cfg = rs.conf()
#修改主节点的优先级为2(主节点、副本节点、仲裁节点的索引分别为:0、1、2)
rs0:PRIMARY> cfg.members[0].priority=2
#更新副本集的配置
rs0:PRIMARY> rs.reconfig(cfg)
注:以上priority优先级改完之后会立即生效,priority最高的将成为主节点
修改之后
五、群集故障测试
1、副本节点故障(关闭副本)
预期:
- 不会触发选举,此时给主节点插入数据,
- 再次启动副本节点(agent1),会发现主节点(master)写入的数据,会自动同步给副本节点(agent1)节点。
步骤一:关闭agent1上的MongoDB服务
步骤二:在master上查看状态(主节点)
步骤三:在master主节点上写入数据
步骤四: 故障恢复 (开启agent1上的MongoDB服务)
在agent1上查看故障时master写入的数据是否同步成功
结论:
- 从节点发生故障集群不会触发选举,此时给主节点插入数据,
- 再次启动副本节点(agent1),会发现主节点(master)写入的数据,会自动同步给副本节点(agent1)节点。
2、 主节点故障(关闭主节点的MongoDB)
预期:
- 触发选举,副本节(agent1)点当主节点
- 再次启动主节点发现优先级原因,主节点再次回到master上
步骤一:关闭master上的mongo服务
步骤二:查看到agent1上的mongo变成主节点
步骤三:在agent1上写入数据
步骤四:恢复master上的MongoDB
由于优先级的原因master变成了主节点、agent1变成了副本节点
步骤五:查看master故障时,agent1后写入的数据是否同步到master节点上。
结论:
- 当主节点故障时集群触发选举,副本节(agent1)点当选为主节点
- 再次启动主节点因为优先级原因,主节点再次回到master上。
3、仲裁节点和主节点故障
预期:
- 副本集是只读状态,不在进行选举,因为票数没有超过半数
步骤一:关闭master和agent2上的mongo服务

步骤二:查看agent1上的mongo服务读写情况


4、仲裁节点和副本节点故障
预期:
- 副本集是只读状态,不可写入数据了。
步骤一:关闭agent1(副本节点)和agent2(仲裁节点)上的MongoDB服务

步骤二:查看master(主节点)由PRIMARY 变为 SECONDARY


步骤三:主机点上进行读写验证

