本篇我们要使用 Dcoker compose
方式实作 MongoDB replication,又快速又方便,如果不太熟的可以去参考之前文章 DAY2 安装与使用 MongoDB。
上一篇文章有提到(怎麽又是之前文章啊?这样代表我的文章有连贯性啊) MongoDB replication 至少需要有三个实体。
首先我们建立一个 yml 档案 docker-compose.yml
,开始写我们计划中的设定。
替这次 replication 取个名字叫做 ith2021-rs
三个节点名称与port分别为
再拿之前的范例来修改就完成了!
version: '3'
services:
mongo_node1:
container_name: mongo_node1
image: mongo
ports:
- 27666:27666
command: mongod --port 27666 --bind_ip_all --replSet ith2021-rs
mongo_node2:
container_name: mongo_node2
image: mongo
ports:
- 27667:27667
command: mongod --port 27667 --bind_ip_all --replSet ith2021-rs
mongo_node3:
container_name: mongo_node3
image: mongo
ports:
- 27668:27668
command: mongod --port 27668 --bind_ip_all --replSet ith2021-rs
我们可以看到这次启动的指令多了 --replSet ith2021-rs
,就是指定 replica set 的名称。
透过上面的 yml 启动後确实可以看到三个实体,但它们三个还不认识彼此,这时候就必须进行 replica set 初始化的动作,这时候直接执行会出现...
> rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "17dca5869ff9:27666",
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1631433581, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1631433581, 1)
}
它会告诉你没有任何设定档,所以用预设值来设定。这时候就很麻烦,需手动敲指一个一个节点加进去 replica set。
懒惰如我,我们把这段用指令方式放进 docker compose 的 healthcheck
方式自动执行,这样就可以省掉一个动作了。(注意啊~这是本机方便快速测试用才会这样做,部署到其他环境还是要抽出到正确的职责位置)
完整的 yml
version: '3'
services:
mongo_node1:
container_name: mongo_node1
image: mongo
ports:
- 27666:27666
command: mongod --port 27666 --bind_ip_all --replSet ith2021-rs
mongo_node2:
container_name: mongo_node2
image: mongo
ports:
- 27667:27667
command: mongod --port 27667 --bind_ip_all --replSet ith2021-rs
mongo_node3:
container_name: mongo_node3
image: mongo
ports:
- 27668:27668
command: mongod --port 27668 --bind_ip_all --replSet ith2021-rs
healthcheck:
test: ["CMD","mongo","--host","mongo_node3","--port","27668",
"--eval", 'rs.initiate( { _id : "ith2021-rs", members:
[{ _id: 0, host: "mongo_node1:27666" },
{ _id: 1, host: "mongo_node2:27667" },
{ _id: 2, host: "mongo_node3:27668" }]})']
interval: 10s
启动後随便连入一台 MongoDB 看看,再次输入 rs.initiate()
会出现什麽...
➜ source git:(master) ✗ mongo --host 127.0.0.1 --port 27666
MongoDB shell version v4.0.3
connecting to: mongodb://127.0.0.1:27666/
//中略
ith2021-rs:SECONDARY> rs.initiate()
{
"ok" : 0,
"errmsg" : "already initialized",
"code" : 23,
"codeName" : "AlreadyInitialized",
"$clusterTime" : {
"clusterTime" : Timestamp(1631434164, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1631434164, 1)
}
ith2021-rs:SECONDARY>
会告诉你已经初始化完成了。
要如何验证资料同步呢?最简单方式就是写入一笔资料,确认次节点有没有同步就可以了。还记得我们提到仅有主节点能够执行资料修改内容,於是我们先随便连进一台,接着查看 Primary
节点是哪一台。
指令是 rs.status()
不过内容太多了,我们只需要查看这个 rs 内的会员即可。
rs.status().members
不过内容细节还是很多,我就不在这贴出来占版面,可以使用一点 js 语法来捞出我们要看的内容。
ith2021-rs:SECONDARY> rs.status().members.forEach(x=>print(`${x.name}/${x.stateStr}`))
mongo_node1:27666/SECONDARY
mongo_node2:27667/SECONDARY
mongo_node3:27668/PRIMARY
➜ source git:(master) ✗ mongo --host 127.0.0.1 --port 27668
MongoDB shell version v4.0.3
connecting to: mongodb://127.0.0.1:27668/
// 中略
ith2021-rs:PRIMARY> use testdb
switched to db testdb
ith2021-rs:PRIMARY> db.testcol.insert({field:'iThome 2021 ironman BEST!'})
WriteResult({ "nInserted" : 1 })
ith2021-rs:PRIMARY> exit
bye
刚刚已经在主节点写入资料了,让我们来随便连到一个次节点看看有没有这笔资料罗
➜ source git:(master) ✗ mongo --host 127.0.0.1 --port 27666
MongoDB shell version v4.0.3
connecting to: mongodb://127.0.0.1:27666/
// 中略
ith2021-rs:SECONDARY> use testdb
switched to db testdb
ith2021-rs:SECONDARY> db.testcol.find()
Error: error: {
"topologyVersion" : {
"processId" : ObjectId("613db58d9e315ff6c1c2fe94"),
"counter" : NumberLong(4)
},
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotPrimaryNoSecondaryOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1631434784, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1631434784, 1)
}
ith2021-rs:SECONDARY>
没想到居然跳错误,但是也不用太紧张,这是因为 secondary
预设是关闭查询的,我们只需要打开即可。
ith2021-rs:SECONDARY> rs.slaveOk()
ith2021-rs:SECONDARY> db.testcol.find()
{ "_id" : ObjectId("613db79ea937743f1dc6af82"), "field" : "iThome 2021 ironman BEST!" }
ith2021-rs:SECONDARY>
就看到这笔资料罗~代表资料真的是有自动同步到次节点。
我想说的是这指令 rs.slaveOk().. ok 你个头
其实这指令已经被改为 rs.secondaryOk()
在 MongoDB 里面逐渐把 Master/Slave 改为 Primary/Secondary 了
不知道什麽时候会完全移除这些指令就是了,所以请记得改用 rs.secondaryOk()
建立 replica set 介绍就差不多到这边了,架设测试用的环境不会遇到太大的困难,後面要加入密码和key会稍微麻烦一点,不过不在这次的范围内,也许之後再找时间来发教学文了。
後面开始会讲一点维运的东西,跟 oplog
息息相关。
本系列文章会同步发表於我个人的部落格 Pie Note
<<: JavaScript学习日记 : Day6 - 函数(一)
>>: Day18 Lab 2 - Object storage metadata
接续昨天的部分,今天的登入会依照你的身分进入不同的页面(以会员、管理员为例)。 首先先增加资料表的内...
Azure Sentinel包含功能强大的查询工具,可协助为资安人员找出并隔离公司环境内安全 性威胁...
前言 今天利用之前所建的主页, 建立一个可让使用者互动的原型。 预览 利用Figma的预览功能, 即...
有监於需要学的东西太多,所以做个最懒人的笔记给未来忘记语法的自己看。(大写为内建语法) 1.SELE...
既然 Linux ARM 可以开发网站,那 Windows ARM 可以当日常的网站开发吗? 我们这...