詳解MongoDB復制集(主從復制)
復制集(Replica Sets)是額外的數據副本,是跨多個服務器同步數據的過程,復制集提供了冗余並增加了數據可用性,通過復制集可以對硬件故障和中斷的服務進行恢復
復制集的優勢
- 讓數據更安全
- 高數據可用性(24*7)
- 災難恢復
- 無停機維護(如備份、索引重建、故障轉移)
- 讀縮放(額外的副本讀取)
- 副本集對應程序是透明的
復制集的特點
- N個節點的群集
- 任何節點可作為主節點
- 所有寫入操作都在主節點上
- 自動故障轉移
- 自動恢復
復制集工作原理
1.MongoDB的復制集至少需要兩個節點。其中一個是主節點(Primary),負責處理客戶端的請求,其余的都是從節點(Secondary),負責復制主節點上的數據。
2.MongoDB各個節點常見的搭配方式為:一主一從或一主多從。主節點記錄其上的所有操作到oplog中,從節點定期輪詢主節點獲取的這些操作,然後對自己的數據副本執行這些操作,從而保證從節點的數據與主節點一致
3.如上圖可以看出,客戶端在主節點寫入數據,才從節點讀取數據,主節點與從節點進行數據交互保障數據的一致性。如果其中一個節點出現故障,其他節點馬上會將業務接過來而無需停機操作
一、安裝MongoDB
1、自定義yum源文件
[root@redhat7_6 ~]# cd /etc/yum.repos.d/
[root@redhat7_6 yum.repos.d]# mkdir bak
[root@redhat7_6 yum.repos.d]# mv CentOS-* bak/
[mongodb-org]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc
2、安裝MongoDB
[root@redhat7_6 ~]# yum -y install mongodb-org
[root@redhat7_6 ~]# yum clean all #清除yum緩存
二、配置復制集
1、創建實例相關文件
[root@redhat7_6 ~]# mkdir -p /data/mongodb/mongodb{1,2,3,4} #創建數據目錄
[root@redhat7_6 ~]# mkdir -p /data/logs/mongodb #創建日誌目錄
[root@redhat7_6 ~]# cd /data/logs/mongodb/
[root@redhat7_6 mongodb]# touch mongodb{1,2,3,4}.log #創建日誌文件
[root@redhat7_6 mongodb]# chmod 777 *.log #修改目錄權限
2、編輯實例1配置文件
[root@redhat7_6 ~]# cp -p /etc/mongod.conf /etc/mongod1.conf
[root@redhat7_6 ~]# vim /etc/mongod1.conf #修改配置文件
path: /data/logs/mongodb/mongodb1.log #約第10行,編輯日誌文件路徑,對應其他的實例依次往下……
dbPath: /data/mongodb/mongodb1/ #編輯數據目錄文件路徑,也是一樣對應其他的實例依次往下……
net: #約28行,指定網絡接口
port: 27017 #編輯端口號,實例1為27017,實例2為27018,依次往下排……
bindIp: 0.0.0.0
replication: #約37行,打開復制選項註釋,四臺實例都要添加
replSetName: kgcrs #指定復制集名稱
3、編輯其他實例配置文件
[root@redhat7_6 ~]# cp -p /etc/mongod1.conf /etc/mongod2.conf #創建其他三個MongoDB實例配置文件
[root@redhat7_6 ~]# cp -p /etc/mongod1.conf /etc/mongod3.conf
[root@redhat7_6 ~]# cp -p /etc/mongod1.conf /etc/mongod4.conf
[root@redhat7_6 ~]# rm -rf /etc/mongod.conf
4、編寫啟動腳本
[root@redhat7_6 ~]# vim /etc/init.d/mongodb
#!/bin/bash
# descript:Mongodb Server Control Script
# Author: GuiHaiYiDao TEL:139741741741
# date:long long ago
instance=$1
action=$2
case "$action" in
‘start‘)
/usr/bin/mongod -f /etc/"$instance".conf
;;
‘stop‘)
/usr/bin/mongod -f /etc/"$instance".conf --shutdown
;;
‘restart‘)
/usr/bin/mongod -f /etc/"$instance".conf --shutdown
/usr/bin/mongod -f /etc/"$instance".conf
;;
esac
[root@redhat7_6 ~]# chmod +x /etc/init.d/mongodb
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod1 start
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod2 start
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod3 start
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod4 start
[root@redhat7_6 ~]# netstat -anpt | grep ‘mongod‘
5、初始化配置復制集
[root@redhat7_6 ~]# mongo --port 27017 #進入第一個實例
> rs.status() #查看復制集的狀態信息
{
"info" : "run rs.initiate(...) if not yet done for the set",
"ok" : 0,
"errmsg" : "no replset config has been received", #此參數指定沒有接收到復制集配置
"code" : 94,
"codeName" : "NotYetInitialized"
}
> cfg={"_id":"kgcrs","members":[{"_id":0,"host":"192.168.100.76:27017"},{"_id":1,"host":"192.168.100.76:27018"},{"_id":2,"host":"192.168.100.76:27019"}]} #cfg定義變量作為初始化參數;kgcrs定義復制集名稱;members定義節點成員
{
"_id" : "kgcrs",
"members" : [
{
"_id" : 0,
"host" : "192.168.100.71:27017"
},
{
"_id" : 1,
"host" : "192.168.100.72:27018"
},
{
"_id" : 2,
"host" : "192.168.100.73:27019"
}
]
}
> rs.initiate(cfg) #初始化復制集
{
"ok" : 1,
"operationTime" : Timestamp(1536499691, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1536499691, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
kgcrs:SECONDARY> rs.status() #再次查看復制集狀態信息
{
"set" : "kgcrs", #復制集群集名稱
"date" : ISODate("2018-09-09T13:29:34.203Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.100.76:27017", #復制集成ip以及端口號
"health" : 1, #健康狀況,1代表健康;0代表宕機
"state" : 1, #1代表主節點;2代表從節點
"stateStr" : "PRIMARY", #PRIMARY代表主節點;SECONDARY代表從節點
"uptime" : 172,
"optime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-09-09T13:29:24Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1536499703, 1),
"electionDate" : ISODate("2018-09-09T13:28:23Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "192.168.100.76:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 82,
"optime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-09-09T13:29:24Z"),
"optimeDurableDate" : ISODate("2018-09-09T13:29:24Z"),
"lastHeartbeat" : ISODate("2018-09-09T13:29:33.324Z"),
"lastHeartbeatRecv" : ISODate("2018-09-09T13:29:32.404Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.100.76:27017",
"syncSourceHost" : "192.168.100.76:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.100.76:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 82,
"optime" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1536499764, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-09-09T13:29:24Z"),
"optimeDurableDate" : ISODate("2018-09-09T13:29:24Z"),
"lastHeartbeat" : ISODate("2018-09-09T13:29:33.324Z"),
"lastHeartbeatRecv" : ISODate("2018-09-09T13:29:32.383Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.100.76:27017",
"syncSourceHost" : "192.168.100.76:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1536499764, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1536499764, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
6、增加節點
kgcrs:PRIMARY> rs.add("192.168.100.76:27020") #增加節點
{
"ok" : 1,
"operationTime" : Timestamp(1536500454, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1536500454, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
kgcrs:PRIMARY> rs.status() #再次查看復制集狀態信息
7、刪除節點
kgcrs:PRIMARY> rs.remove("192.168.100.76:27020") #刪除節點
kgcrs:PRIMARY> rs.status() #再次查看
kgcrs:PRIMARY> exit
三、復制集切換
1、模擬故障自動轉移
[root@redhat7_6 ~]# ps aux | grep mongod | grep -v grep
[root@redhat7_6 ~]# kill -9 10706
[root@redhat7_6 ~]# mongo --port 27018
kgcrs:PRIMARY> rs.status() #查看復制狀態
2、手動進行主從切換
kgcrs:PRIMARY> exit
[root@redhat7_6 ~]# /etc/init.d/mongodb mongod1 start #再次啟動實例1
[root@redhat7_6 ~]# mongo --port 27018 #此時主節點是在第二臺實例中
kgcrs:PRIMARY> rs.status()
kgcrs:PRIMARY> rs.freeze(30) #暫停30秒不參加選舉
kgcrs:PRIMARY> rs.stepDown(60,30) #告知主節點交出主節點位置,然後維持從節點狀態不少於60秒,同時等待30秒以使主節點和從節點日誌同步
kgcrs:SECONDARY> rs.status()
四、測試復制集同步
1、主節點添加測試數據
[root@redhat7_6 ~]# mongo --port 27017
kgcrs:PRIMARY> use supermarket
kgcrs:PRIMARY> for(var i=0;i<=100;i++)db.product.insert({"id":1,"pname":"Audi"+i})
2、手動進行主從切換
kgcrs:PRIMARY> rs.freeze(30)
kgcrs:PRIMARY> rs.stepDown(60,30)
kgcrs:SECONDARY> rs.status()
3、登錄第二個實例服務器
[root@redhat7_6 ~]# mongo --port 27017
kgcrs:PRIMARY> use supermarket
kgcrs:PRIMARY> db.product.find()
詳解MongoDB復制集(主從復制)