1. 程式人生 > >詳解MongoDB復制集(主從復制)

詳解MongoDB復制集(主從復制)

hash ica stat cati i++ $1 inf 交互 tex

簡介

復制集(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/

[root@redhat7_6 yum.repos.d]# vim local.repo

[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緩存

[root@redhat7_6 ~]# yum list #重新加載源

二、配置復制集

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復制集(主從復制)