後臺服務nosql資料庫mongodb:高可用講解以及安裝
後臺服務nosql資料庫mongodb:高可用講解以及安裝
一、架構介紹
mongodb有幾種部署方式,這裡採用的是副本集架構(Replica Set)。
為了防止單點故障就需要引副本(Replication),當發生硬體故障或者其它原因造成的宕機時,可以使用副本進行恢復,最好能夠自動的故障轉移(failover)。有時引入副本是為了讀寫分離,將讀的請求分流到副本上,減輕主(Primary)的讀壓力。而Mongodb的Replica Set都能滿足這些要求。
Replica Set的一堆mongod的例項集合,它們有著同樣的資料內容。包含三類角色:
主節點(Primary):接收所有的寫請求,然後把修改同步到所有Secondary。一個Replica Set只能有一個Primary節點,當Primary掛掉後,其他Secondary或者Arbiter節點會重新選舉出來一個主節點。預設讀請求也是發到Primary節點處理的,需要轉發到Secondary需要客戶端修改一下連線配置。
副本節點(Secondary):與主節點保持同樣的資料集。當主節點掛掉的時候,參與選主。
仲裁者(Arbiter):不保有資料,不參與選主,只進行選主投票。使用Arbiter可以減輕資料儲存的硬體需求,Arbiter跑起來幾乎沒什麼大的硬體資源需求,但重要的一點是,在生產環境下它和其他資料節點不要部署在同一臺機器上。
注意,一個自動failover的Replica Set節點數必須為奇數,目的是選主投票的時候要有一個大多數才能進行選主決策。
由圖可以看到客戶端連線到整個副本集,不關心具體哪一臺機器是否掛掉。主伺服器負責整個副本集的讀寫,副本集定期同步資料備份,一但主節點掛掉,副本節點就會選舉一個新的主伺服器,這一切對於應用伺服器不需要關心。我們看一下主伺服器掛掉後的架構:
副本集中的副本節點在主節點掛掉後通過心跳機制檢測到後,就會在叢集內發起主節點的選舉機制,自動選舉一位新的主服務器。
二、安裝部署
選擇三臺伺服器:10.211.55.7(主節點) 10.211.55.8(副本節點) 10.211.55.9(副本節點)
192.168.78.129(主節點) 192.168.78.130(副本節點) 192.168.78.131(副本節點)
下載mongodb:wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.7.tgz
如果發現下載不下來,將https改為http
解壓到:/data/program/software
資料夾重新命名為mongodb
進入mongodb目錄:cd /data/program/software/mongodb
新建兩個資料夾:mkdir db
mkdir logs
進入bin目錄cd /data/program/software/mongodb/bin
新建配置檔案:touch mongodb.conf
dbpath=/data/program/software/mongodb/db
logpath=/data/program/software/mongodb/logs/mongodb.log
port=27017
fork=true
nohttpinterface=true
分別三臺伺服器上啟動mongodb:
/data/program/software/mongodb/bin/mongod--replSet repset -f /data/program/software/mongodb/bin/mongodb.conf
各個伺服器檢視,都已經啟動:
[[email protected]]# ps -ef|grep mongodb
root 2574 1 1 22:09 ? 00:00:00 /data/program/software/mongodb/bin/mongod--replSet repset -f /data/program/software/mongodb/bin/mongodb.conf
在三臺機器上任意一臺機器登陸mongodb:
/data/program/software/mongodb/bin/mongo
使用admin資料庫
use admin
定義副本集配置變數,這裡的_id:”repset”和上面命令引數--replSet repset保持一致
config = { _id:"repset", members:[{_id:0,host:"192.168.78.129:27017"},{_id:1,host:" 192.168.78.130:27017"},{_id:2,host:" 192.168.78.131:27017"}]}
初始化副本叢集:rs.initiate(config);
檢視叢集節點的狀態: rs.status(); 如下結果: { "set" : "repset", "date" : ISODate("2017-09-21T14:30:17.190Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) } }, "members" : [ { "_id" : 0, "name" : "10.211.55.7:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 111, "optime" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-09-21T14:30:07Z"), "optimeDurableDate" : ISODate("2017-09-21T14:30:07Z"), "lastHeartbeat" : ISODate("2017-09-21T14:30:16.070Z"), "lastHeartbeatRecv" : ISODate("2017-09-21T14:30:16.887Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.211.55.9:27017", "configVersion" : 1 }, { "_id" : 1, "name" : "10.211.55.8:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 111, "optime" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-09-21T14:30:07Z"), "optimeDurableDate" : ISODate("2017-09-21T14:30:07Z"), "lastHeartbeat" : ISODate("2017-09-21T14:30:16.070Z"), "lastHeartbeatRecv" : ISODate("2017-09-21T14:30:16.877Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.211.55.9:27017", "configVersion" : 1 }, { "_id" : 2, "name" : "10.211.55.9:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 163, "optime" : { "ts" : Timestamp(1506004207, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-09-21T14:30:07Z"), "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1506004115, 1), "electionDate" : ISODate("2017-09-21T14:28:35Z"), "configVersion" : 1, "self" : true } ], "ok" : 1 } |
三、測試叢集功能
主節點連線到終端:
mongo127.0.0.1
連線test資料庫:
use test;
往testdb表裡插入資料
db.testdb.insert({"test1":"testval1"})
在副本節點連線查詢:./mongo 10.211.55.7:27107(如果連線不上的話,我這邊是下載了Robo 3T 1.1.1軟體去檢視資料的https://github.com/woshiceshi/mongodb.githttps://github.com/woshiceshi/mongodb.git)
使用test資料庫:user test;
查詢表格:show tables;
報錯如下:
mongodb預設是從主節點讀寫資料,副本節點上不允許讀,設定副本節點可讀。
db.getMongo().setSlaveOk();
然後就可以查詢複製過來的資料了
repset:SECONDARY>db.testdb.find();
{"_id" : ObjectId("59c3cf8bf21850357d5392ba"),"test1" : "testval1" }
測試叢集恢復功能,去停掉主節點:
然後檢視節點狀態,發現7和8中有一臺變為了PRIMARY,然後再啟動主節點觀察狀態。
Ps –ef | grepmongodb
Kill 埠號
如果出現了:
repset:SECONDARY>show tables
2018-04-09T01:37:41.529-0700E QUERY [thread1] Error:listCollections failed: {
"ok" : 0,
"errmsg" : "not master andslaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/db.js:807:1
[email protected]/mongo/shell/db.js:819:19
[email protected]/mongo/shell/db.js:830:16
[email protected]/mongo/shell/utils.js:762:9
[email protected]/mongo/shell/utils.js:659:15
@(shellhelp2):1:1
這個錯誤 則執行以下rs.slaveOk();