一、架構介紹
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(副本節點)
下載mongodb:wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.7.tgz
解壓到:/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
各個服務器查看,都已經啓動:[root@bigdata3 bin]# 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
PS:如果啓動遇到問題,一般是openssl的問題(沒有依賴libcrypto.so.10):
yum install openssl-devel
在三臺機器上任意一臺機器登陸mongodb:/data/program/software/mongodb/bin/mongo
使用admin數據庫
use admin
定義副本集配置變量,這裏的_id:”repset”和上面命令參數--replSet repset保持一致
config = { _id:"repset", members:[{_id:0,host:"10.211.55.7:27017"},{_id:1,host:"10.211.55.8:27017"},{_id:2,host:"10.211.55.9: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
}
三、測試集羣功能
主節點連接到終端:
mongo 127.0.0.1
連接test數據庫:
use test;
往testdb表裏插入數據
db.testdb.insert({"test1":"testval1"})
在副本節點連接查詢:
./mongo 10.211.55.7:27107
使用test數據庫:user test;
查詢表格:show tables;
報錯如下:
mongodb默認是從主節點讀寫數據,副本節點上不允許讀,設置副本節點可讀。
db.getMongo().setSlaveOk();
然後就可以查詢複製過來的數據了
repset:SECONDARY> db.testdb.find();
{ "_id" : ObjectId("59c3cf8bf21850357d5392ba"), "test1" : "testval1" }
測試集羣恢復功能,去停掉主節點:
然後查看節點狀態,發現7和8中有一臺變爲了PRIMARY,然後再啓動主節點觀察狀態。