引言
在上一篇关于《MongoDB入门》的文章中,咱们把单机版的MongoDB
讲了个大概,但很多情况下,单节点服务往往并不能满足系统需求,毕竟单节点部署的方式有很多隐患:
-
①没有灾备能力,在单节点宕机的情况下,服务不可用会拖垮整个系统;
-
②吞吐量不够:系统并发较高、访问量过大时,单节点无法承载流量;
-
③拓展性不足:只能通过升级单节点的硬件配置,无法横向拓展;
-
④数据安全风险:在极端情况下,数据损坏或出现丢失,无法有效恢复。
而上述提到的这一系列问题,在采用集群方案部署的情况下迎刃而解,所以本文一起来聊聊MongoDB
集群,顺带以MongoDB
集群为起点,共同探讨一下分布式存储的发展趋势~
一、MongoDB副本集群
MongoDB
副本集群,也被称之为复制集群,其实和Redis、MySQL
中的主从集群概念类似,只不过叫法上有所差异,就好比MQ
中,称之为镜像集群,名词千变万化,理念殊途同归,内在含义都是:一个主节点拥有读写能力,一或多个从节点全量拷贝主节点的数据,对外提供读的能力。
只不过这里要注意:**MongoDB
副本集群和传统的主从集群不太一样**!无论是Redis
,还是MySQL
,它们只提供主从复制功能,即自动将主节点上写入的新数据,完整的同步给从节点。但它们并不提供故障迁移的功能!好比在Redis
中,当主节点出现故障时,往往需要依靠外力来完成主从切换,因此通常会搭建“一主两从三哨兵”的架构,由哨兵来完成故障迁移的功能。
而MongoDB
副本集群,则无需任何外力介入,在主节点发生故障的情况下,无需任何外力介入,能自动完成主从切换,从而对外实现真正意义上的7*24h
高可用,并且从节点还可以处理读请求,从而保障MongoDB
服务的高性能。
总的来说,MongoDB
副本集群源自于主从集群,但在主从的基础上做了很大拓展,其中总共有三种节点角色:
-
Primary
主节点:拥有读写能力,为集群内的副本节点,提供数据拷贝的支持; -
Replicate
副本节点:拥有读能力,数据完全拷贝自主节点,即主从概念中的从节点; -
Arbiter
仲裁节点:不具备读写能力,用于故障恢复,提供故障检测、选举投票能力。
MongoDB
副本集群中,出现了一个新概念:仲裁节点,其实作用等同于哨兵节点,但它并不是副本集群必须存在的节点,因为主节点、副本节点都拥有投票能力,它的存在只是为了维护集群内的平衡,如集群节点为偶数时,可以添加一个仲裁节点,让集群保持奇数特性,确保每轮选举一次就能推出新主,避免多轮无效竞选的现象出现(不了解选举机制的后面会说原理)。
好了,理论暂且说到这里,咱们先来搭建一个副本集群玩一玩,简单的实战一把。
1.1、副本集群实战
因为目前只是简单学习,这里选择搭建成本最低的“一主、一副本、一仲裁”集群,并且也不采用三台机器构建,而是基于“伪集群”的思想:
-
单机模式:一台机器对外提供服务;
-
集群模式:多台机器对外提供同一服务;
-
伪集群模式:单台机器上启动多个实例,模拟多机器场景对外提供服务。
当然,如果你会Docker、K8S
这些容器化技术,使用它们来构建的速度会更快,但咱们现在追求原汁原味,就一步步手动配置搭建出整个集群,整个集群的节点关系如下:
其中主节点、副本节点、仲裁节点的端口分别为:27018、27019、27020
。
①为每个节点创建存放数据、配置文件、日志的目录:
[root@~]# mkdir /soft/mongodb/data/replication-cluster &&
mkdir /soft/mongodb/log/replication-cluster &&
mkdir /soft/mongodb/conf/replication-cluster &&
mkdir /soft/mongodb/data/replication-cluster/27018 &&
mkdir /soft/mongodb/data/replication-cluster/27019 &&
mkdir /soft/mongodb/data/replication-cluster/27020 &&
mkdir /soft/mongodb/log/replication-cluster/27018 &&
mkdir /soft/mongodb/log/replication-cluster/27019 &&
mkdir /soft/mongodb/log/replication-cluster/27020
②编写主节点的配置文件:
[root@~]# vi /soft/mongodb/conf/replication-cluster/27018.conf
# MongoDB日志存储相关配置
systemLog:
# 将所有日志写到指定文件中
destination: file
# 记录所有日志信息的文件路径
path: "/soft/mongodb/log/replication-cluster/27018/mongo.log"
# 当服务重启时,将新日志以追加形式写到现有日志尾部
logAppend: true
storage:
# 指定MongoDB存储数据的目录
dbPath: "/soft/mongodb/data/replication-cluster/27018"
processManagement:
# 以后台进程方式运行MongoDB服务
fork: true
# 指定保存mongo进程ID的文件位置
pidFilePath: "/soft/mongodb/conf/replication-cluster/27018.pid"
net:
# 绑定服务实例的IP,默认是localhost,这里换成本机IP
bindIp: 192.168.229.135
#绑定的端口,默认是27017
port: 27018
replication:
# 指定副本集群的名称
replSetName: zhuzi
将上述配置信息复制、并根据自己的环境修改后,接着按下esc
,输入:wq
保存并退出。
③启动主节点服务(依旧使用之前bin
目录下的文件,只是换掉配置文件即可):
[root@~]# /soft/mongodb/bin/mongod -f /soft/mongodb/conf/replication-cluster/27018.conf
④编写副本(从)节点的配置文件,由于和主节点的配置完全相同,因此直接copy
一份,接着将相关目录、端口,批量替换成规划中的27019
即可:
[root@~]# cd /soft/mongodb/conf/replication-cluster/
[root@~]# cp 27018.conf 27019.conf
[root@~]# vi /soft/mongodb/conf/replication-cluster/27019.conf
接着不要按insert
键,直接输入:%s/27018/27019/g
,完成批量替换(记得保存再退出)。
⑤启动副本节点服务:
[root@~]# /soft/mongodb/bin/mongod -f /soft/mongodb/conf/replication-cluster/27019.conf
⑥编写仲裁节点的配置文件,这里依旧拷贝27018.conf
文件进行批量替换:
[root@~]# cp 27018.conf 27020.conf
[root@~]# vi /soft/mongodb/conf/replication-cluster/27020.conf
输入:%s/27018/27020/g
,完成批量替换,不要忘记保存。
⑦启动仲裁节点服务:
[root@~]# /soft/mongodb/bin/mongod -f /soft/mongodb/conf/replication-cluster/27020.conf
⑧通过mongosh
客户端工具,连接27018
主节点,初始化副本集群:
[root@~]# /soft/mongodb/bin/mongosh 192.168.229.135:27018
test> rs.initiate();
执行上述初始化命令,只要看到ok:1
这个字段值,说明初始化成功,接着稍等片刻,MongoDB
会自动将当前连接的节点,设置为集群的主节点。当然,这个初始化方法也可以指定参数,比如这样:
test> config = {
_id : "zhuzi",
members : [
{_id: 0, host: "192.168.229.135:27018"},
{_id: 1, host: "192.168.229.135:27021"},
{_id: 2, host: "192.168.229.135:27020", arbiterOnly: true}
]
};
test> rs.initiate(config);
这是先指定集群节点,然后再初始化,后面咱们会依次添加集群节点,所以这种方式感兴趣的也可以自己试试。
⑨通过初始化的主节点,将其他节点加入到集群中,命令如下:
rs.add(host, arbiterOnly);
该方法有两个参数,前者是其他节点的IP:port
,后者则是仅仲裁权力(可选参数),如果置为true
,当前添加的节点则只有选举权力;如果为false
,则拥有数据复制、选举的权力。
添加仲裁节点还有另外一个专门的方法,如下:
rs.addArb(host);
通过该方法添加的仲裁节点,只会拥有选举权力,并不参与副本集群中的数据维护工作。
通过上面的方法,将副本节点加入到集群中:
zhuzi [direct: primary] test> rs.add("192.168.229.135: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"
}
});
执行上述命令后,再执行添加仲裁节点的命令,
zhuzi [direct: primary] test> rs.addArb("192.168.229.135:27020");
添加完成后,可以通过下述两个命令查看集群的节点配置、状态:
rs.conf();
rs.status();
其实所有副本集群相关的信息&#