启用三个 mongod 建立复制集。
MongoDB 版本选择目前最新的稳定版 3.6.2-jessie
。
docker run --name mongo0 -d mongo:3.6.2-jessie --replSet "rs0" --bind_ip_all
docker run --name mongo1 -d mongo:3.6.2-jessie --replSet "rs0" --bind_ip_all
docker run --name mongo2 -d mongo:3.6.2-jessie --replSet "rs0" --bind_ip_all
通过 docker inspect
找到三个 mongod 实例的 IPAddress
。
比如 docker inspect mongo0 | grep IPAddress
,
又由于端口为 mongod 默认的 27017。所以 mongod 的地址为
- mongo0: 172.17.0.2:27017
- mongo1: 172.17.0.3:27017
- mongo2: 172.17.0.4:27017
初始化复制集
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "172.17.0.2:27017" },
{ _id: 1, host: "172.17.0.3:27017" },
{ _id: 2, host: "172.17.0.4:27017" }
]
})
根据 replica-set-configuration-document,
_id
:复制集的名称。必须与启动 mongod 的--replSet
一致members
:成员配置文件的列表。members[n]._id
:用来识别成员的 idmembers[n].host
:成员对应的host:port
连接字符串为
mongodb://172.17.0.2:27017,172.17.0.3:27017,172.17.0.4:27017/test?replicaSet=rs0
复制特性
在主节点中插入数据后,从节点中也存在。
mongo mongodb://172.17.0.2:27017,172.17.0.3:27017,172.17.0.4:27017/test?replicaSet=rs0
rs0:PRIMARY> db.order.insert({price: 1})
WriteResult({ "nInserted" : 1 })
mongo --host 172.17.0.3
// 允许当前连接对从库进行读操作
rs0:SECONDARY> db.getMongo().setSlaveOk()
rs0:SECONDARY> db.order.find()
{ "_id" : ObjectId("5a7c5473b74e8cf1bb890979"), "price" : 1 }
重新选举
关闭主节点,会重新选举出新的主节点。
当前主节点为 172.17.0.2:27017
> `rs.status()`
"name" : "172.17.0.2:27017",
"health" : 1,
"stateStr" : "PRIMARY",
通过 docker stop mongo0
关闭它之后,可以看到 172.17.0.2
是不健康状态
"name" : "172.17.0.2:27017",
"health" : 0,
"stateStr" : "(not reachable/healthy)",
主节点变为了 172.17.0.3
,期限由 1 变为了 2,表示又经过一次选举,
"term" : NumberLong(2)
...
...
"name" : "172.17.0.3:27017",
"health" : 1,
"stateStr" : "PRIMARY",
docker start mongo0
启动 mongo0 后,172.17.0.2
变为了健康的从节点
"name" : "172.17.0.2:27017",
"health" : 1,
"stateStr" : "SECONDARY",
大部分节点失效
我们关闭两个节点
docker stop mongo0 mongo2
可以看到 172.17.0.2
和 172.17.0.4
都无法连接,而 172.17.0.3
变为了从节点,
整个复制集没有主节点了,无法进行写操作。
"name" : "172.17.0.3:27017",
"health" : 1,
"stateStr" : "SECONDARY",
"name" : "172.17.0.2:27017",
"health" : 0,
"stateStr" : "(not reachable/healthy)",
"name" : "172.17.0.4:27017",
"health" : 0,
"stateStr" : "(not reachable/healthy)",
设置优先级
先启动之前关闭的节点 docker start mongo0 mongo2
根据 adjust-replica-set-member-priority
将第一个节点的 priority 设置为 2。(需要在主节点中输入以下命令)
cfg = rs.conf()
cfg.members[0].priority = 2
rs.reconfig(cfg)
可以看到不久后,主节点变为 _id: 0
了
"_id" : 0,
"stateStr" : "PRIMARY",
用于生产环境的注意事项
- mongod 绑定非 localhost 地址前,考虑开启访问控制或者安全清单上的其他措施
- 复制集成员的关联性应该小,减小同时出问题的几率
参考
https://docs.mongodb.com/manual/tutorial/deploy-replica-set/