一、介绍
MongoDB副本集(Replica set)是一组MongoDB实例,它们都维护着相同的数据集合。MongoDB副本集是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。副本集没有固定的主节点,当主节点发生故障时整个集群会选举一个主节点为系统提供服务以保证系统的高可用。
MongoDB官网关于副本集的文档地址如下:
https://www.mongodb.com/docs/manual/replication/
二、Automatic Failover
自动故障转移机制:当主节点未与集群中的其它成员通信,并超过配置的超时时间(默认为10秒)时,合格的辅助节点将调用选举以将自己提名为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。
三、搭建副本集
提前说明:以下操作都是基于192.168.1.108这台服务器,当前MongoDB的版本为6.0.5。
第一步:在/home目录下执行下述命令,创建三个数据存放目录
mkdir -p mongo/data1
mkdir -p mongo/data2
mkdir -p mongo/data3
第二步:使用下述命令创建三个Mongo实例
docker run -id --name mongo1 -v /home/mongo/data1:/data/db -p 27017:27017 mongo:latest --replSet rs
docker run -id --name mongo2 -v /home/mongo/data2:/data/db -p 27018:27017 mongo:latest --replSet rs
docker run -id --name mongo3 -v /home/mongo/data3:/data/db -p 27019:27017 mongo:latest --replSet rs
上述执行命令中多了一个 --replSet rs 的配置项,“--replSet”表示定义副本集,“rs”表示副本集的名称,这个副本集名称是可以随便取的,但是在三个Mongo的实例中配置需要是一样的。
第三步:登录到Mongo服务中,使用下述命令添加从节点并进行初始化,这个也是官网的一种推荐
rs.initiate(
{
_id:"集群名称",
version:1,
members:[
{_id:0,host:"主节点IP:27017"},
{_id:1,host:"从节点IP:27017"},
{_id:2,host:"从节点IP:27017"}
]
}
)
rs.initiate()这是进行初始化,直接初始化可以直接将当前节点变为主节点。_id这个配置尽量和前面创建容器时定义的名称保持一致,主要是为了避免不必要的一些错误。
下面这个是我在真正执行的初始化命令:
rs.initiate(
{
_id:"rs",
version:1,
members:[
{_id:0,host:"192.168.1.108:27017"},
{_id:1,host:"192.168.1.108:27018"},
{_id:2,host:"192.168.1.108:27019"}
]
}
)
可以看到返回结果为“{ ok: 1 }”,此时操作是没有问题,初始化命令已经执行成功了。大概十秒左右,按回车,可看到变为主节点,如下图所示:
第四步:如果不使用Portainer,我们可以使用下述命令进入到 192.168.1.108:27017 这个Mongo服务中:
docker exec -it mongo1 mongosh --host 127.0.0.1 --port 27017
在Mongo服务中执行rs.status()命令查看状态,如下图所示:
在状态信息中有个members区域,这里我们可以看到当前主从节点的状态信息,如下图所示:
还可以使用rs.isMaster()命令查看是否为主、从节点,如下图所示:
第五步:开启多个窗口,进入两个从节点,可以看到从节点的状态为secondary
如果有新的节点要加入到副本集中,则可以使用rs.add()命令添加,至于怎么去添加这个去官网看看相对应版本的文档说明。
四、副本集操作
4.1 主、从节点数据查询
我们在主节点中创新数据库user:
use user;
再往user库的users集合中插入10条数据:
for(let i=0;i<10;i++){
db.users.insert({_id:i,name:'张三'+i,age:18+i});
}
接着再进入到从节点中,切换到user库,然后查看users这个集合中的数据,这时会报错,如下图所示:
默认情况下从节点中的数据是不能被读取,因此我们可以执行下述命令设置客户端临时可以访问:
rs.secondaryOk()
4.2 主、从节点重新选举
如果停掉了27017这个节点的话,通过 rs.status()这个命令可以看到27018就瞬间成为了主节点:
当前集群中只有两个节点27018和27019,如果这时在将27018这个节点服务给停掉,这时整个副本集中只有27019这一个节点,该节点中的数据如果没有设置rs.secondaryOk(),那么该节点中的数据是不能被读取。
当副本集中只有一个节点时,该副本集对外服务是不可用的。
如果再将27017和27018的节点全部给启动起来,可以看到该副本集又重新选举出了新的主节点:
- 主节点对外提供读写服务,从节点只进行数据同步、不对外提供读写服务
- 副本集解决了高可用的问题,但是无法解决一个节点由于负载过大而产生的负载均衡问题。
五、客户端连接副本集
上面已经配置好了Mongo服务的副本集,当前为一主两从的架构,如果想使用该副本集服务,那么我们在Spring Boot项目的yml文件中其配置需要修改为如下所示:
spring:
data:
mongodb:
uri: mongodb://192.168.1.108:27017,192.168.1.108:27018,192.168.1.108:27019/user?replicaSet=rs
特别提示:在连接串的最后面需要追加加副本集的配置(replicaSet=rs)!!!