【注意】最后更新于 June 12, 2020,文中内容可能已过时,请谨慎使用。
场景
起因是因,公司生产环境使用的阿里云提供 Mongodb 云服务(3节点),而在公司实际项目的config/database.php
。
数据库连接配置中确只用了一个主节点,每次因主节点负载过高主从自动切换(Primary 切换为 Secondary)后,而项目配置中确依然是连接的主库(Primary),便导致不能写入(Secondary)后,而项目配置中确依然是连接的主库(Primary),便开始收到一堆不能写入报警(Secondary 只能读不能写)。然后赶紧登陆阿里云手动切换回来(这酸爽)。
为了能做到主从切换后服务依然高可用,测试服使用 Docker 搭建3节点 Mongodb 集群服务,配置项目测试
集群搭建
3节点的 Mongodb 集群,容器名为 mongo-master
作为默认 Primary
,mongo-salve
作为 Secondary
,mongo-arbiter
仅作为选举节点,不做数据副本。
1
2
3
4
5
6
7
8
9
10
11
| # 创建network
docker network new mongo-network
# 启动主节点
docker run -d --rm --net=mongo-network -it --name mongo-master -v /data/mongo/db/:/data/db/ -v /data/mongo/configdb/:/data/configdb -p 27017:27017 mongo --dbpath /data/db --replSet mongoreplset
# 启动从节点
docker run -d --rm --net=mongo-network -it --name mongo-salve -p 27018:27017 mongo --replSet mongoreplset
# 启动选举节点
docker run -d --rm --net=mongo-network -it --name mongo-arbiter -p 27019:27017 mongo --replSet mongoreplset
|
测试节点服务
1
2
3
4
5
| # 启动 mongo-client
docker run --rm -it --name mongo-client --net=mongo-network mongo /bin/bash
# 连接主节点
mongo --host mongo-master
|
配置节点数据同步
查看容器 IP,配置节点数据同步用:
1
| docker inspect mongo-network
|
登录其中一台节点,根据上面的 ip 配置主从节点,
1
2
3
4
5
6
| config = {_id:"mongoreplset", version:1, members:[
{_id:0, host:"192.168.112.2:27017", priority:2},
{_id:1, host:"192.168.112.3:27017", priority:1},
{_id:2, host:"192.168.112.6:27017", priority:1,arbiterOnly:true}
]}
rs.initiate(config)
|
配置后再次登录每个节点,看到节点角色的变化,那说明便是成功了,我的记录如下
登录主节点(主从切换后)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| root@0e645014d20c:/# mongo --host mongo-master
MongoDB shell version v4.2.7
connecting to: mongodb://mongo-master:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("d7846eb2-b4b5-4c33-9cdb-b5f7a0478d60") }
MongoDB server version: 4.2.7
Server has startup warnings:
2020-06-09T15:13:32.051+0000 I STORAGE [initandlisten]
...
...
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
mongoreplset:SECONDARY>
|
登录从节点
1
2
3
4
5
6
7
8
9
10
11
12
13
| root@0e645014d20c:/# mongo --host mongo-salve
MongoDB shell version v4.2.7
connecting to: mongodb://mongo-salve:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("7c55b482-ebb9-48ae-a465-7efe23ae37aa") }
MongoDB server version: 4.2.7
Server has startup warnings:
...
...
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
mongoreplset:PRIMARY>
|
查看配置,命令:rs.status()
如果配置已经添加过,再次添加提示already initialized
,采用如下方式修改:
1
2
3
| rsconf = rs.conf()
rsconf.members = [{_id:0, host:"192.168.112.2:27017", priority:2},{_id:1, host:"192.168.112.3:27017", priority:1},{_id:2, host:"192.168.112.6:27017", priority:1,arbiterOnly:true}]
rs.reconfig(rsconf, {force: true})
|
小结
因为每次销毁容器,再次启动都会导致 IP 的变化,因为容器 IP 直接决定着主从角色,每次配置还得调整这是很麻烦的。着实不太舒服,建议使用docker-compose
编排来做这事
最后自己这么搭建的再使用DSN
连接方式测试时,遇到错误[No suitable servers found (serverselectiontryonce
set): connection error calling ismaster on,至此也不晓得是啥原因,经测试阿里云给出的没这问题,临时测试服先继续使用单节点,生产配置采用 replicaSet
参考文章