前言
上一篇「使用 Docker 构筑不同 MongoDB 架构 (二) - Standalone」,我们介绍了 docker-compose 的基本操作,这次我们要来构筑 Replica Set。在 Sharded Cluster 中 shard 和 config servers 就是用Replica Set 构筑。
为了专注构筑 Replica Set,我们先不引入安全性的设定,可以参考 Security Checklist。
本系列文的专案放在:https://github.com/eugenechen0514/demo_mongo_cluster
架构
一个最基本的 Replica Set 至少要三个 member,一个 Primary、二个 Secondary,如下图
Primary/Secondary 都是有实际存资料的 member,若在硬体不够的情况下,Mongo 提供 Arbiter 这种形态的 member,它只参与投票,本身不存资料也不能成为 Primary,如下图
若使用 Primary-Second-Arbiter 三个节点,有件事需要注意。当存有资料的节点(Primary/Second)死掉且使用 "majority" read concern 时会导致 cache pressure。见:Read Concern majority and Three-Member PSA
接下来,我们使用 docker-compose 构筑 Primary-Secondary-Secondary 的 Replica Set。
Docker Compose
我们的 Replica Set 名称叫 RS
,所以要用到 --replSet RS
。一共建立三个 container (rs1/rs2/rs3),port 分别为 27041/27042/27043。另外,为了使 Replica Set 的网路设定更有弹性,我们使用 extra_hosts
设定容器 DNS,而不是写死 IP。
因为
network_mode
是host
,所以资料库就如同架设在本机端,rs1.local
/rs2.local
/rs3.local
都会对应到127.0.0.1
。
接下来,就可以
$ docker-compose -f docker-compose-replica-set.yml up
建立执行容器。
docker-compose-replica-set.yml
version: '3'services: rs1: image: mongo:4.2 container_name: rs1 network_mode: host command: mongod --replSet RS --port 27041 --dbpath /data/db --config /resource/mongod.yml volumes: - ./replica/config/mongod.yml:/resource/mongod.yml - ./replica/data/rs1:/data/db extra_hosts: - "rs1.local:127.0.0.1" - "rs2.local:127.0.0.1" - "rs3.local:127.0.0.1" rs2: image: mongo:4.2 container_name: rs2 network_mode: host command: mongod --replSet RS --port 27042 --dbpath /data/db --config /resource/mongod.yml volumes: - ./replica/config/mongod.yml:/resource/mongod.yml - ./replica/data/rs2:/data/db extra_hosts: - "rs1.local:127.0.0.1" - "rs2.local:127.0.0.1" - "rs3.local:127.0.0.1" rs3: image: mongo:4.2 container_name: rs3 network_mode: host command: mongod --replSet RS --port 27043 --dbpath /data/db --config /resource/mongod.yml volumes: - ./replica/config/mongod.yml:/resource/mongod.yml - ./replica/data/rs3:/data/db extra_hosts: - "rs1.local:127.0.0.1" - "rs2.local:127.0.0.1" - "rs3.local:127.0.0.1"
这里注意到所有容器都要能解析域名 rs1.local
/ rs2.local
/ rs3.local
,因此都要设定 extra_hosts
。
replica/config/mongod.yml
net: bindIpAll: truestorage: engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 0.1
Replica Set 设定
1. 确认资料库连线
连入 rs1 container,确认能不能用域名(domain)连线到 rs1/rs2/rs3 资料库。
# 进入(执行 bash) rs1 container$ docker-compose -f docker-compose-replica-set.yml exec rs1 bash
若不特别说明,之后的操作是指在 rs1 container 中。
确认资料库连线
$ mongo rs1.local:27041 --eval "print('ok')"$ mongo rs2.local:27042 --eval "print('ok')"$ mongo rs3.local:27043 --eval "print('ok')"
确认是否都可以印出 ok,接下来开始设定 Replica Set。
2. 设定 Replica Set
随便选一个 member, 连入资料库
$ mongo rs1.local:27041
设定 Replica Set 组态
cfg = { "_id": "RS", "members": [{ "_id": 0, "host": "rs1.local:27041" }, { "_id": 1, "host": "rs2.local:27042" }, { "_id": 2, "host": "rs3.local:27043" } ]};rs.initiate(cfg);
印出 ok: 1
就设定完成。
3. 测试连线
连入 Replica Set
$ mongo --host RS/rs1.local:27041,rs2.local:27042,rs3.local:27043
我们使用
rs1.local
/rs2.local
/rs3.local
域名连线,所以执行mongo shell
的主机要确认可以解析成资料库所在的 IP。
随便写入资料
db.col.insertOne({text: 'hi'})
印出
{ "acknowledged" : true, "insertedId" : ObjectId("5dff2ea59b9f4570f9214660")}
以上就完成了 Replica Set 的架设。接下来,列出一些在管理 Replica Set 时,常使用的指令。
确认 Replica Set 状态
当我们要增加/减少 member 或是检查 member 是否有连线时,常常需要确认 member 状态。rs 有三个常用的指令 rs.status()
, rs.printReplicationInfo()
, rs.printSlaveReplicationInfo()
。
rs.status()
:查看 members 状态 (PRIMARY/SECONDARY/RECOVERING/DOWN...)。如:rs.status().members.forEach(m => print(`${m.name} => ${m.stateStr}`))
印出rs1.local:27041 => PRIMARYrs2.local:27042 => SECONDARYrs3.local:27043 => SECONDARY
rs.printSlaveReplicationInfo()
:members 的同步状态source: rs2.local:27042 syncedTo: Sun Dec 22 2019 07:55:10 GMT+0000 (UTC) 0 secs (0 hrs) behind the primary source: rs3.local:27043 syncedTo: Sun Dec 22 2019 07:55:10 GMT+0000 (UTC) 0 secs (0 hrs) behind the primary
rs.printReplicationInfo()
:members 的 oplog 状态configured oplog size: 1354.0509757995605MBlog length start to end: 183secs (0.05hrs)oplog first event time: Sun Dec 22 2019 07:52:18 GMT+0000 (UTC)oplog last event time: Sun Dec 22 2019 07:55:21 GMT+0000 (UTC)now: Sun Dec 22 2019 07:55:27 GMT+0000 (UTC)
总结
本篇我们介绍了如何使用 docker-compose 构筑 Replica Set,以及提到三个确认 Replica Set 状态的指令。此外,我们还刻意使用域名设定 Replica Set 组态,为了使资料库主机的移动可以增加一些弹性。
附录:连线常见问题
防火墙 (firewall)
架设资料库的主机需要设定防火墙才能让别人连入
firewall-cmd --add-port=27041/tcpfirewall-cmd --add-port=27041/tcp --permanentfirewall-cmd --add-port=27042/tcpfirewall-cmd --add-port=27042/tcp --permanentfirewall-cmd --add-port=27043/tcpfirewall-cmd --add-port=27043/tcp --permanent
域名解析设定/DNS 设定
因为执行 mongo shell
的主机要确认可以解析成资料库所在的 IP,你可能需要修改 hosts
,让执行 mongo shell
的主机可以正确的解析 IP。
假设我们的执行 mongo shell
的主机和资料库都架设在本机端。因此修改 hosts
$ vi /etc/hosts
在下面加入域名解析的IP,
127.0.0.1 rs1.local127.0.0.1 rs2.local127.0.0.1 rs3.local
若是 mongo shell
是在容器中执行,可以用 extra_hosts
设定 hosts
,或修改容器里的 /etc/hosts