新聞中心
?期內(nèi)容:MongoDB 復(fù)制集的介紹及搭建

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名申請(qǐng)、網(wǎng)頁(yè)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、和布克賽爾蒙古網(wǎng)站維護(hù)、網(wǎng)站推廣。
復(fù)制集架構(gòu)概覽
復(fù)制集是一組 mongod? 進(jìn)程一起維護(hù)相同的數(shù)據(jù)集。復(fù)制集提供了冗余及高可用。下面的幾幅圖是 MongoDB 復(fù)制集的工作原理:
Diagram of default routing of reads and writes to the primary.
Diagram of a 3 member replica set that consists of a primary and two secondaries.
Diagram of a replica set that consists of a primary, a secondary, and an arbiter.
主服務(wù)器是唯一可以隨時(shí)寫入的節(jié)點(diǎn)。從節(jié)點(diǎn)處于熱待機(jī)狀態(tài),如果主節(jié)點(diǎn)發(fā)生故障,從節(jié)點(diǎn)可以接管主節(jié)點(diǎn)。一旦主節(jié)點(diǎn)失敗,從節(jié)點(diǎn)將會(huì)競(jìng)選主節(jié)點(diǎn)角色。
我們也可以有仲裁節(jié)點(diǎn)。仲裁員節(jié)點(diǎn)不保存任何數(shù)據(jù),其唯一目的是參與選舉過(guò)程。
我們的復(fù)制集集群必須始終有奇數(shù)節(jié)點(diǎn)(包括仲裁節(jié)點(diǎn))。三、五和七個(gè)節(jié)點(diǎn)是推薦的數(shù)量,所以如果初選(或更多服務(wù)器)失敗,我們?cè)谶x舉過(guò)程中擁有多數(shù)選票。
當(dāng)復(fù)制集的其他節(jié)點(diǎn)在超過(guò) 10 秒(可配置)內(nèi)沒(méi)有收到主節(jié)點(diǎn)的消息時(shí),符合條件的從節(jié)點(diǎn)將開始進(jìn)行投票選舉。第一個(gè)選舉并贏得多票數(shù)的節(jié)點(diǎn)將成為新的主節(jié)點(diǎn)。所有剩余的服務(wù)器現(xiàn)在都將從新的主節(jié)點(diǎn)復(fù)制,保持其作為從節(jié)點(diǎn)的角色,繼續(xù)從新的主節(jié)點(diǎn)同步。
從 MongoDB 3.6 開始,如果客戶端驅(qū)動(dòng)程序檢測(cè)到主操作已關(guān)閉,則可以一次重試寫操作。復(fù)制集最多可以有 50 名節(jié)點(diǎn),但其中最多只能有 7 名節(jié)點(diǎn)可以在選舉過(guò)程中投票。
復(fù)制集是如何選舉的
復(fù)制集中的所有服務(wù)器都通過(guò)心跳與所有其他節(jié)點(diǎn)保持定期通信。心跳是一個(gè)小包,會(huì)定期進(jìn)行發(fā)送,以驗(yàn)證所有節(jié)點(diǎn)是否正常運(yùn)行。
從節(jié)點(diǎn)與主節(jié)點(diǎn)通信,以從 oplog 獲取最新的變更(增、刪、改),并將其應(yīng)用于自己的數(shù)據(jù)庫(kù)中。
當(dāng)主節(jié)點(diǎn)不可用時(shí),所有從節(jié)點(diǎn)都會(huì)丟失心跳。其余節(jié)點(diǎn)將等到設(shè)置 electionTimeoutMillis 時(shí)間(默認(rèn)時(shí)間為 10 秒)后,然后從節(jié)點(diǎn)將開始一輪或多輪選舉,以選舉產(chǎn)生新的主節(jié)點(diǎn)。
要從從節(jié)點(diǎn)中選擇為主節(jié)點(diǎn),它必須具有如下兩個(gè)屬性:
- 屬于擁有 50%+1 選票
- 成為這個(gè)組中最新的從節(jié)點(diǎn)
在三個(gè)服務(wù)器各一票的簡(jiǎn)單例子中,一旦主節(jié)點(diǎn)不可用,其他兩臺(tái)服務(wù)器將各有一票(總共三分之二),那么誰(shuí)擁有最新 oplog 的服務(wù)器將被選為主節(jié)點(diǎn)。
數(shù)據(jù)是如何復(fù)制的
- 當(dāng)一個(gè)修改操作(增、刪、改)到達(dá)主節(jié)點(diǎn)時(shí),主節(jié)點(diǎn)對(duì)數(shù)據(jù)的操作將會(huì)記錄下來(lái),這些操作記錄稱之為 oplog
- 從節(jié)點(diǎn)通過(guò)在主節(jié)點(diǎn)上打開一個(gè) tailable 游標(biāo)不斷獲取新進(jìn)入主節(jié)點(diǎn)的 oplog,并在自己的數(shù)據(jù)上回放,以此保持跟主節(jié)點(diǎn)的數(shù)據(jù)一致
通過(guò)選舉完成故障恢復(fù):
- 具有投票的節(jié)點(diǎn)之間的兩兩互相發(fā)送心跳
- 當(dāng) 5 次心跳未收到時(shí),判斷為節(jié)點(diǎn)失聯(lián)
- 如果失聯(lián)的主節(jié)點(diǎn),從節(jié)點(diǎn)會(huì)發(fā)起選舉,選出新的節(jié)點(diǎn)
- 如果失聯(lián)的從節(jié)點(diǎn),則不會(huì)產(chǎn)生新的選舉
- 選舉基于 RAFT一致性算法實(shí)現(xiàn),選舉成功的必要條件是大多數(shù)投票節(jié)點(diǎn)存活
- 復(fù)制集中最多可以有 50 個(gè)節(jié)點(diǎn),但具有投票權(quán)的節(jié)點(diǎn)最多 7 個(gè)
復(fù)制集的優(yōu)勢(shì)
MongoDB 復(fù)制集的大部分優(yōu)勢(shì),其中一些列出如下:
- 提供數(shù)據(jù)冗余,供恢復(fù)時(shí)使用
- 讀擴(kuò)展,客戶端可以從多個(gè)從節(jié)點(diǎn)進(jìn)行數(shù)據(jù)的讀取
- 災(zāi)難恢復(fù)
- 避免停機(jī)維護(hù)
介紹了復(fù)制集的優(yōu)勢(shì),那么有沒(méi)其他缺憾呢?答案是肯定有的,因?yàn)橥昝朗遣淮嬖诘摹?/p>
在上述優(yōu)勢(shì)的列表中缺少的最值得注意的是寫擴(kuò)展。這是因?yàn)椋?MongoDB 中,我們只能有一個(gè)主節(jié)點(diǎn),只有這個(gè)主節(jié)點(diǎn)負(fù)責(zé)數(shù)據(jù)的寫入。
當(dāng)我們想擴(kuò)展寫入性能時(shí),我們通常會(huì)設(shè)計(jì)和使用分片集群,這是下一章要分享的話題,敬請(qǐng)期待。
配置復(fù)制集
演示環(huán)境:
|
主機(jī)名 |
IP |
角色 |
|
mongo01.tyun.cn |
10.20.20.19 |
Primary |
|
mongo02.tyun.cn |
10.20.20.11 |
slave1 |
|
mongo03.tyun.cn |
10.20.20.41 |
slave2 |
準(zhǔn)備工作
由于我們啟用了認(rèn)證,所以需要為每個(gè)節(jié)點(diǎn)使用 Keyfile(當(dāng)然還有其他方式):
[root@mongo01 ~]# openssl rand -base64 756 > /etc/mongod.keyfile
[root@mongo01 ~]# cat /etc/mongod.keyfile
k+iOUxLSaYYGlclb379Ehb/AvsIGt8GaALW48IQ6QZFzT4DaFVn/T3tuiOXREgza
3EyjxqW31ReXcPhFeePRsjADw00DrEqD3iO+pHW6ZVMMQHcrIPdm4wkUKkWY7jkh
611NtKHfZKHY0QXfsrCKAn5uQXyswg6gmmssXzfsz2TEBr1R5z5n0GFz7GogOr9y
j1vYRE5NaikVLQxMSrJa2yJVGK28y/s2FJ0FB5R/z9OEeKG7LET/hqgRidztiLaD
ZEEaQU+xUPpsoUW3qF7oNlkYH4u9YBSRq8xu37GdfIgZjyQXol0TckXfFBNkn/F0
zyXRIiwtMk2ehc2kQV/n9xXMkd3vemLMTZN+aSoEPxvE4jojU5BHMS0c1Hjnpc68
D+A3NpqvXlC6u9D5XWoBJgdcVsEHgwTpOwCsk621hMDNs2/vMDnEDhjI4fat/F5x
G2ECUmL1yNQ4ls5O3BtSJwbuxqU7uXfC1wVWwAcBaeKbGOQQOvCxvx2jNIGk0zLH
XdoaXbiiGJyaIbEqstsZyYjX9rI7Br4K1KuLbKoxLhl5xJRDNFe0LAHGwXHf6YkR
9QTZwpLrbl6HbTq0MkiGsc643BfGgHgbm28ECwKe1HGABnmnrqbmo7QzFvxwHI8E
wWud2WbC/GKexSLLM50HSAU7FTbjiYjS2afIbBxVV1raKoDpbnPkRgbpXBORIP+b
1f38CAI17vGbLllaoPrB2p6bR/jR+GZhCTK4zjq1g5ssxRCbYnuH7M6x/owTIp4s
zpli6rhnpcWJGwvmpMUyeQBrrIevRZjjwSNaGACdPg52xqapx9ZMyKip0ALmOEHl
g4h4cDyiiPepbh8dz2hj/3/9RtdhyfFrMebBWImxZehVghtQR9Tp2znTBtn73TQa
ElcYK49kMn3lrMw2uqCGXBWKGQvStPR9YnRwHaQ40FjVx6YR1kv3T6kzwlKdlNZA
iMyi5u9TBCLbO+ziUKQiNX+ErJS0Qujtw0G1REBOVcqP9Wl0
密鑰的長(zhǎng)度必須在 6 到 1024 個(gè)字符之間,并且只能包含 base64 集中的字符。
設(shè)置合適的權(quán)限:
[root@mongo01 ~]# chmod 400 /etc/mongod.keyfile
[root@mongo01 ~]# chown mongod. /etc/mongod.keyfile
把 keyfile 復(fù)制到剩余的兩個(gè)節(jié)點(diǎn)上:
[root@mongo01 ~]# scp /etc/mongod.keyfile mongo02.tyun.cn:/etc/
[root@mongo01 ~]# scp /etc/mongod.keyfile mongo03.tyun.cn:/etc/
[root@mongo01 ~]# ssh mongo02.tyun.cn -- chmod 400 /etc/mongod.keyfile
[root@mongo01 ~]# ssh mongo03.tyun.cn -- chmod 400 /etc/mongod.keyfile
[root@mongo01 ~]# ssh mongo02.tyun.cn -- chown mongod. /etc/mongod.keyfile
[root@mongo01 ~]# ssh mongo03.tyun.cn -- chown mongod. /etc/mongod.keyfile
[root@mongo01 ~]# ssh mongo02.tyun.cn -- ls -l /etc/mongod.keyfile
-r-------- 1 mongod mongod 1024 Aug 2 07:51 /etc/mongod.keyfile
[root@mongo01 ~]# ssh mongo03.tyun.cn -- ls -l /etc/mongod.keyfile
-r-------- 1 mongod mongod 1024 Aug 2 07:50 /etc/mongod.keyfile
我們使用默認(rèn)的數(shù)據(jù)目錄:/var/lib/mongo?。確保三臺(tái)機(jī)器的配置一樣,只有 bind_ip? 不一樣。配置分別如下(僅以第一臺(tái)配置為例,其他節(jié)點(diǎn)的配置需要按需修改 bindIp 配置參數(shù)):
[root@mongo01 ~]# egrep -v "(^#|^$)" /etc/mongod.conf
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27017
bindIp: 127.0.0.1,10.20.20.19
security:
authorization: enabled
keyFile: /etc/mongod.keyfile
replication:
replSetName: rs0
接下來(lái)分別啟動(dòng)三個(gè)節(jié)點(diǎn)上的服務(wù):
[root@mongo01 ~]# systemctl start mongod
[root@mongo02 ~]# systemctl start mongod
[root@mongo03 ~]# systemctl start mongod
接下來(lái)配置 Primary、slave 及 arbiter 節(jié)點(diǎn)。客戶端連接到 Primary:
[root@mongo01 ~]# mongo --authenticationDatabase "admin" -u "root" -p
MongoDB shell version v4.4.15
Enter password: xxxxxxxx # 在此輸
> rs.initiate({
_id: "rs0",
members: [{
_id: 0,
host: "mongo01.tyun.cn:27017"
},{
_id: 1,
host: "mongo02.tyun.cn:27017"
},{
_id: 2,
host: "mongo03.tyun.cn:27017"
}]
})
{ "ok" : 1 }
# 注意觀察提示符已經(jīng)發(fā)生了變化
rs0:SECONDARY>
rs0:SECONDARY>
......
rs0:SECONDARY>
rs0:SECONDARY>
rs0:PRIMARY>
配置之前的提示符是 ">?",進(jìn)行了復(fù)制集的初始化后,提示變成了 rs0:SECONDARY?,這個(gè)時(shí)候所有的節(jié)點(diǎn)都是從節(jié)點(diǎn)角色,因?yàn)橐M(jìn)行一輪或多輪的投票選舉。過(guò)了一段時(shí)間,有一個(gè)節(jié)點(diǎn)(mongo01)經(jīng)過(guò)投票選舉被選為了主節(jié)點(diǎn),所以它的提示符變成了 rs0:PRIMARY。
查看復(fù)制集的狀態(tài)信息:
rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2022-08-02T08:04:34.878Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"votingMembersCount" : 3,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"readConcernMajorityWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"appliedOpTime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"lastDurableWallTime" : ISODate("2022-08-02T08:04:29.498Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1659427439, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2022-08-02T07:59:59.469Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1659427188, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2022-08-02T07:59:59.486Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2022-08-02T08:00:00.622Z")
},
"members" : [
{
"_id" : 0,
"name" : "mongo01.tyun.cn:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1701,
"optime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-08-02T08:04:29Z"),
"lastAppliedWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"lastDurableWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1659427199, 1),
"electionDate" : ISODate("2022-08-02T07:59:59Z"),
"configVersion" : 1,
"configTerm" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "mongo02.tyun.cn:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 286,
"optime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-08-02T08:04:29Z"),
"optimeDurableDate" : ISODate("2022-08-02T08:04:29Z"),
"lastAppliedWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"lastDurableWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"lastHeartbeat" : ISODate("2022-08-02T08:04:33.506Z"),
"lastHeartbeatRecv" : ISODate("2022-08-02T08:04:33.006Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "mongo01.tyun.cn:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
},
{
"_id" : 2,
"name" : "mongo03.tyun.cn:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 286,
"optime" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1659427469, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-08-02T08:04:29Z"),
"optimeDurableDate" : ISODate("2022-08-02T08:04:29Z"),
"lastAppliedWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"lastDurableWallTime" : ISODate("2022-08-02T08:04:29.498Z"),
"lastHeartbeat" : ISODate("2022-08-02T08:04:33.507Z"),
"lastHeartbeatRecv" : ISODate("2022-08-02T08:04:33.006Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "mongo01.tyun.cn:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1659427469, 1),
"signature" : {
"hash" : BinData(0,"MUcQYY28dUYGQB+XmqfVO7kUMVU="),
"keyId" : NumberLong("7127185549797883908")
}
},
"operationTime" : Timestamp(1659427469, 1)
}
我們看一下 members 信息:
rs0:PRIMARY> var members = rs.status().members
rs0:PRIMARY> for (i = 0; i < members.length; i++) {
if (members[i].stateStr === "PRIMARY") { continue }
print("Secondary:", members[i].name, "SyncSource:", members[i].syncSourceHost)
}
Secondary: mongo02.tyun.cn:27017 SyncSource: mongo01.tyun.cn:27017
Secondary: mongo03.tyun.cn:27017 SyncSource: mongo01.tyun.cn:27017
通過(guò)輸出我們可以看到兩個(gè)從節(jié)點(diǎn) mongo02.tyun.cn:27017? 及 mongo03.tyun.cn:27017? 分別從主節(jié)點(diǎn) mongo01.tyun.cn:27017 上進(jìn)行數(shù)據(jù)的同步。
至此,我們的復(fù)制集已經(jīng)設(shè)置完成。雖然復(fù)制集已經(jīng)創(chuàng)建完成,但是我們的工作才剛剛開始。
讀選擇項(xiàng)
默認(rèn)情況下,所有寫入和讀取都來(lái)自主節(jié)點(diǎn)。從節(jié)點(diǎn)復(fù)制數(shù)據(jù),但不用于查詢。MongoDB 官方驅(qū)動(dòng)程序支持五個(gè)級(jí)別的數(shù)據(jù)讀選擇項(xiàng):
|
讀選擇項(xiàng)的模式 |
描述 |
|
primary |
這是默認(rèn)的模式,從主節(jié)點(diǎn)讀 |
|
primaryPreferred |
在這種模式下,應(yīng)用也是從主節(jié)點(diǎn)讀數(shù)據(jù),但是當(dāng)主節(jié)點(diǎn)不可用時(shí),會(huì)從從節(jié)點(diǎn)讀取數(shù)據(jù) |
|
secondary |
完全從從節(jié)點(diǎn)讀取數(shù)據(jù) |
|
secondaryPreferred |
優(yōu)先從從節(jié)點(diǎn)讀取數(shù)據(jù)。當(dāng)從節(jié)點(diǎn)不可用時(shí),從主節(jié)點(diǎn)讀取數(shù)據(jù) |
|
nearest |
應(yīng)用程序?qū)墓?jié)點(diǎn)中就近讀取數(shù)據(jù),而不考慮節(jié)點(diǎn)的類型 |
通過(guò)上述提供的選項(xiàng),可以很方便地配置讀寫分離、就近讀取等策略,細(xì)分控制讀取策略。上述的這些選項(xiàng)該怎么用呢?
- 鏈接字符串的形式:mongodb://db0.cdxwcx.com,db1.cdxwcx.com,db2.cdxwcx.com/?replicaSet=myRepl&readPreference=secondary
- Mongo shell 的形式:db.collection.find().readPref("secondary")
連接復(fù)制集
復(fù)制集搭建完成后,該怎么連接使用呢?
連接復(fù)制集與連接單個(gè)節(jié)點(diǎn)是沒(méi)有什么區(qū)別的。
配置完成就可以做數(shù)據(jù)同步的測(cè)試了,在 Primary 上創(chuàng)建數(shù)據(jù),然后查看數(shù)據(jù),然后登錄其他從節(jié)點(diǎn)查看數(shù)據(jù)。操作如下:
[root@mongo01 ~]# mongo --authenticationDatabase "admin" -u "tyun" -p
MongoDB shell version v4.4.15
Enter password: xxxxxx # 在此輸入
connecting to: mongodb://127.0.0.1:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("d325d424-b594-4e5d-903f-407e185ad3f6") }
MongoDB server version: 4.4.15
rs0:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
order 0.000GB
test 0.000GB
rs0:PRIMARY> use test
switched to db test
rs0:PRIMARY> show tables
customer
inventory
oscars
我們?cè)俅蝿?chuàng)建一個(gè)新的測(cè)試表:
rs0:PRIMARY> db.books.insert({name: "云遷移專家", price: 100})
WriteResult({ "nInserted" : 1 })這時(shí)登錄到從節(jié)點(diǎn):
[root@mongo01 ~]# mongo --host 10.20.20.11:27017 --authenticationDatabase "admin" -u "tyun" -p
MongoDB shell version v4.4.15
Enter password: xxxxx # 在此輸入
connecting to: mongodb://10.20.20.11:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f958dbce-8de4-41b7-a037-22565ff0f914") }
MongoDB server version: 4.4.15
rs0:SECONDARY>
rs0:SECONDARY> show dbs
uncaught exception: Error: listDatabases failed:{
"topologyVersion" : {
"processId" : ObjectId("62e8d7f431935e1af2ac1825"),
"counter" : NumberLong(4)
},
"operationTime" : Timestamp(1659428959, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotPrimaryNoSecondaryOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1659428959, 1),
"signature" : {
"hash" : BinData(0,"9x5C9QDI8H8S8dvEekvyCn7DS10="),
"keyId" : NumberLong("7127185549797883908")
}
}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
當(dāng)我們執(zhí)行命令的時(shí)候,報(bào)錯(cuò)了。主要是因?yàn)樵O(shè)置了從節(jié)點(diǎn)不能進(jìn)行讀操作,只需簡(jiǎn)單設(shè)置下即可:
rs0:SECONDARY> rs.secondaryOk() # 這是設(shè)置命令,之前的命令是 rs.slaveOk()
rs0:SECONDARY> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
order 0.000GB
test 0.000GB
# 查看 books 表中的數(shù)據(jù)
rs0:SECONDARY> db.books.find()
{ "_id" : ObjectId("62e8e024229630850e8feb36"), "name" : "云遷移專家", "price" : 100 }
rs0:SECONDARY> db.books.find().pretty()
{
"_id" : ObjectId("62e8e024229630850e8feb36"),
"name" : "云遷移專家",
"price" : 100
}
再次插入一條數(shù)據(jù):
rs0:PRIMARY> db.books.insert({name: "云遷移最佳實(shí)踐", price: 999})
WriteResult({ "nInserted" : 1 })
# 從節(jié)點(diǎn)進(jìn)行查看
rs0:SECONDARY> db.books.find().pretty()
{
"_id" : ObjectId("62e8e024229630850e8feb36"),
"name" : "云遷移專家",
"price" : 100
}
{
"_id" : ObjectId("62e8e1aa229630850e8feb37"),
"name" : "云遷移最佳實(shí)踐",
"price" : 999
}
復(fù)制集的日常操作
復(fù)制集的管理可能比單服務(wù)器部署所需的要復(fù)雜得多。在本節(jié)中,我們將重點(diǎn)關(guān)注復(fù)制集中一些最常見(jiàn)的管理及維護(hù)性的操作。
節(jié)點(diǎn)優(yōu)先級(jí)設(shè)置
MongoDB 允許我們?yōu)槊總€(gè)節(jié)點(diǎn)設(shè)置不同的優(yōu)先級(jí),設(shè)置如下:
var conf = rs.conf()
// 將 0 號(hào)節(jié)點(diǎn)的優(yōu)先級(jí)調(diào)整為 10
conf.members[0].priority = 10;
// 將 1 號(hào)節(jié)點(diǎn)調(diào)整為 hidden 節(jié)點(diǎn)
conf.members[1].hidden = true;
// hidden 節(jié)點(diǎn)必須配置{priority: 0}
conf.members[1].priority = 0;
// 應(yīng)用以上調(diào)整
rs.reconfig(conf);
當(dāng)要對(duì)復(fù)制集中的節(jié)點(diǎn)進(jìn)行維護(hù)時(shí),優(yōu)先級(jí)的設(shè)置就派上用場(chǎng)了。
要在設(shè)置集群后更改優(yōu)先級(jí),我們必須使用 mongo shell 連接到主服務(wù)器并獲取配置對(duì)象:
> cfg = rs.conf()
然后,我們可以將節(jié)點(diǎn)優(yōu)先級(jí)屬性更改為我們想要的值:
> cfg.members[0].priority = 0.778
> cfg.members[1].priority = 999.9999
每個(gè)節(jié)點(diǎn)的默認(rèn)優(yōu)先級(jí)為1。數(shù)值是浮點(diǎn)精度,優(yōu)先級(jí)可以從 0(永遠(yuǎn)不會(huì)成為主)到 1000。
當(dāng)主節(jié)點(diǎn)宕機(jī)并再次發(fā)生選舉時(shí),這些高優(yōu)先級(jí)的節(jié)點(diǎn)將會(huì)進(jìn)行選舉,也是最有可能贏得選舉的節(jié)點(diǎn)。
設(shè)置 0 優(yōu)先級(jí)的復(fù)制集節(jié)點(diǎn)
在某些情況下(例如,如果我們有多個(gè)數(shù)據(jù)中心),我們希望一些節(jié)點(diǎn)永遠(yuǎn)無(wú)法成為主服務(wù)器。
在具有多個(gè)數(shù)據(jù)中心復(fù)制的場(chǎng)景中,我們的主數(shù)據(jù)中心(位于英國(guó))可能有一個(gè)主節(jié)點(diǎn)和一個(gè)從節(jié)點(diǎn),以及一臺(tái)節(jié)點(diǎn)位于俄羅斯。在這種情況下,我們不希望我們位于俄羅斯的服務(wù)器成為主節(jié)點(diǎn),因?yàn)樗鼤?huì)給位于英國(guó)的應(yīng)用程序服務(wù)器產(chǎn)生延遲。在這種情況下,我們將設(shè)置位于俄羅斯的服務(wù)器的優(yōu)先級(jí)為 0。
> var conf = rs.conf()
// 將 0 號(hào)節(jié)點(diǎn)的優(yōu)先級(jí)調(diào)整為 10
> conf.members[0].priority = 10;
// 應(yīng)用以上調(diào)整
> rs.reconfig(conf);
確保每個(gè)節(jié)點(diǎn)都運(yùn)行相同版本的 MongoDB,否則可能會(huì)出現(xiàn)意外行為。避免在業(yè)務(wù)高峰期重新配置復(fù)制集集群。重新配置復(fù)制集可能會(huì)迫使選舉新的主節(jié)點(diǎn),這將關(guān)閉所有活躍的連接,并可能導(dǎo)致 10-30 秒的停機(jī)時(shí)間。嘗試確定最低流量時(shí)間窗口,以運(yùn)行重新配置等維護(hù)操作,并
新聞標(biāo)題:自建MongoDB實(shí)踐:MongoDB復(fù)制集
網(wǎng)站路徑:http://fisionsoft.com.cn/article/cojjcpo.html


咨詢
建站咨詢
