mongodb的多服務器配置,master-slave模式,不能自動實現故障轉移和恢復。爲了實現多服務器的高可用,咱們能夠使用mongodb的replica set。replica set相似於heartbeat的功能,實現高可用。redis
複製集是一個帶有故障轉移的主從集羣。是從現有的主從模式演變而來,增長了自動故障轉移和節點成員自動恢復。複製集模式中沒有固定的主結點,在啓動後,多個服務節點間將自動選舉產生一個主結點。該主結點被稱爲primary,一個或多個從結點被稱爲secondaries。primary結點基本上就是master結點,不一樣之處在於primary結點在不一樣時間多是不一樣的服務器。若是當前的主結點失效了,複製集中的其他結點將會試圖選出一個新的主結點。複製集模式的好處是,一切自動化。首先,複製集模式自己作了大量的管理工做,自動管理從節點,確保數據不會不一致。其次,主節點掛掉後,會自動判斷集羣中的服務器並進行故障轉移,推舉新的主節點。 一個複製集集羣支持1-7臺服務器,在一個複製集中各個服務器數據保持徹底一致。mongodb
在一個複製集集羣中,各個服務器有如下幾種狀態:shell
Primary 主節點:一個複製集有且僅有一臺服務器處於Primary狀態,只有主節點纔對外提供讀寫服務。若是主節點掛掉,複製集將會投票選出一個備用節點成爲新的主節點。數據庫
Secondary 備用節點:複製集容許有多臺Secondary,每一個備用節點的數據與主節點的數據是徹底同步的。centos
Recovering 恢復中:當複製集中某臺服務器掛掉或者掉線後數據沒法同步,從新恢復服務後從其餘成員複製數據,這時就處於恢復過程,數據同步後,該節點又回到備用狀態。服務器
Arbiter 仲裁節點:該類節點能夠不用單獨存在,若是配置爲仲裁節點,就主要負責在複本集中監控其餘節點狀態,投票選出主節點。該節點將不會用於存放數據。若是沒有仲裁節點,那麼投票工做將由全部節點共同進行。網絡
Down 無效節點:當服務器掛掉或掉線時就會處於該狀態。app
複製集的從節點讀請求,也是在各個Driver層設置slaveOk的值來實現的。ssh
MongoDB(M)表示主節點,Mongodb(S)表示備節點,Mongodb(A)表示仲裁節點。主備節點存儲數據,仲裁節點不存儲數據。客戶端同時鏈接主節點與備節點,不鏈接仲裁節點。ide
默認設置下,主節點提供全部增刪查改服務,備節點不提供任何服務。可是能夠經過設置使備節點提供查詢服務,這樣就能夠減小主節點的壓力,當客戶端進行數據查詢時,請求自動轉到備節點上。這個設置叫作Read Preference Modes,同時Java客戶端提供了簡單的配置方式,能夠沒必要直接對數據庫進行操做。
仲裁節點是一種特殊的節點,它自己並不存儲數據,主要的做用是決定哪個備節點在主節點掛掉以後提高爲主節點,因此客戶端不須要鏈接此節點。這裏雖然只有一個備節點,可是仍然須要一個仲裁節點來提高備節點級別。我開始也不相信必需要有仲裁節點,可是本身也試過沒仲裁節點的話,主節點掛了備節點仍是備節點,因此我們仍是須要它的。
1、主機環境狀況:
系統:centos6.5---mongdb3.4
mongodb master:192.168.0.248
mongodb slave : 192.168.0.8 192.168.0.9
mongodb arbiter : 192.168.0.247
2、mongodb的安裝配置
添加yum源和安裝mongodb
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/
[root@7cest ~]# cat /etc/yum.repos.d/MongoDB.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
[mongodb-org-2.6]
name=MongoDB 2.6 Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1
[root@7cest ~]# yum clean all
[root@7cest ~]# yum makecache
直接yum安裝以下:(mongodb爲2.x版本,mongodb-org爲3.x版本)
[root@7cest ~]# yum install -y mongodb
[root@7cest ~]# yum install -y mongodb-org
3、配置mongodb
#/etc/ansible/hosts
[redis]
192.168.0.247 ansible_ssh_pass=centos
192.168.0.248 ansible_ssh_pass=centos
[mongo]
192.168.0.9 ansible_ssh_pass=centos
192.168.0.8 ansible_ssh_pass=centos
[M3:children]
redis
mongo
一、建立節點數據目錄
創建data文件夾、logs文件夾、conf文件夾:
#ansible M3 -m shell -a 'mkdir -p /mongodb/data/{master,slaver,arbiter}'
#ansible M3 -m shell -a 'mkdir -p /mongodb/{logs,conf}'
建立相關的文件:
#ansible M3 -m shell -a 'touch /mongodb/data/{master.pid,slaver.pid,arbiter.pid}'
#ansible M3 -m shell -a 'touch /mongodb/logs/{master.log,slave.log,arbiter.log}'
二、準備相應節點的配置文件:
[root@202-test repSet-conf]# pwd
/bak/ansiblesoft/mongoDB/repSet-conf
[root@202-test repSet-conf]# ls
mongodb-arbiter.conf mongodb-master.conf mongodb-slaver8.conf mongodb-slaver9.conf
具體狀況:
192.168.0.248主節點:mongodb-master.conf
# cat mongodb-master.conf
#mongodb-master.conf
dbpath=/mongodb/data/master
logpath=/mongodb/logs/master.log
pidfilepath=/mongodb/data/master.pid
directoryperdb=true
logappend=true
replSet=xcprs
bind_ip=192.168.0.248
port=27017
oplogSize=1000
fork=true
noprealloc=true
192.168.0.8和192.168.0.9從節點:
# cat mongodb-slaver8.conf
#mongodb-slaver8.conf
dbpath=/mongodb/data/slaver
logpath=/mongodb/logs/slaver.log
pidfilepath=/mongodb/data/slaver.pid
directoryperdb=true
logappend=true
replSet=xcprs
bind_ip=192.168.0.8
port=27017
oplogSize=1000
fork=true
noprealloc=true
smallfiles=true
# cat mongodb-slaver9.conf
#mongodb-slaver9.conf
dbpath=/mongodb/data/slaver
logpath=/mongodb/logs/slaver.log
pidfilepath=/mongodb/data/slaver.pid
directoryperdb=true
logappend=true
replSet=xcprs
bind_ip=192.168.0.9
port=27017
oplogSize=1000
fork=true
noprealloc=true
smallfiles=true
192.168.0.247仲裁節點:
# cat mongodb-arbiter.conf
#mongodb-arbiter.conf
dbpath=/mongodb/data/arbiter
logpath=/mongodb/logs/arbiter.log
pidfilepath=/mongodb/data/arbiter.pid
directoryperdb=true
logappend=true
replSet=xcprs
bind_ip=192.168.0.247
port=27017
oplogSize=1000
fork=true
noprealloc=true
smallfiles=true
參數解釋:
dbpath:數據存放目錄
logpath:日誌存放路徑
pidfilepath:進程文件,方便中止mongodb
directoryperdb:爲每個數據庫按照數據庫名創建文件夾存放
logappend:以追加的方式記錄日誌
replSet:replica set的名字
bind_ip:mongodb所綁定的ip地址
port:mongodb進程所使用的端口號,默認爲27017
oplogSize:mongodb操做日誌文件的最大大小。單位爲Mb,默認爲硬盤剩餘空間的5%
fork:之後臺方式運行進程
noprealloc:不預先分配存儲
copy文件到指定節點的目錄:
# ansible M3 -m copy -a 'src=/bak/ansiblesoft/mongoDB/repSet-conf/mongodb-master.conf dest=/mongodb/conf/mongodb-master.conf backup=yes' --limit=192.168.0.248
# ansible M3 -m copy -a 'src=/bak/ansiblesoft/mongoDB/repSet-conf/mongodb-arbiter.conf dest=/mongodb/conf/mongodb-arbiter.conf backup=yes' --limit=192.168.0.247
# ansible M3 -m copy -a 'src=/bak/ansiblesoft/mongoDB/repSet-conf/mongodb-slaver8.conf dest=/mongodb/conf/mongodb-slaver.conf backup=yes' --limit=192.168.0.8
# ansible M3 -m copy -a 'src=/bak/ansiblesoft/mongoDB/repSet-conf/mongodb-slaver9.conf dest=/mongodb/conf/mongodb-slaver.conf backup=yes' --limit=192.168.0.9
4、啓動服務
若是mongodb設置了開機自動啓動,請取消開機自動啓動
# ansible M3 -m shell -a 'chkconfig mongod off'
# ansible M3 -m shell -a 'chkconfig --list mongod'
根據配置每一個節點的配置文件,啓動相應的服務:
主節點:
# ansible M3 -m shell -a 'echo "/usr/bin/mongod -f /mongodb/conf/mongodb-master.conf" >>/etc/rc.local' --limit=192.168.0.248
從節點:
# ansible M3 -m shell -a 'echo "/usr/bin/mongod -f /mongodb/conf/mongodb-slaver.conf" >>/etc/rc.local' --limit=192.168.0.8
# ansible M3 -m shell -a 'echo "/usr/bin/mongod -f /mongodb/conf/mongodb-slaver.conf" >>/etc/rc.local' --limit=192.168.0.9
仲裁節點:
# ansible M3 -m shell -a 'echo "/usr/bin/mongod -f /mongodb/conf/mongodb-arbiter.conf" >>/etc/rc.local' --limit=192.168.0.247
重啓測試並檢測:
# ansible M3 -m shell -a "reboot"
# ansible M3 -m shell -a "lsof -i -P -n | grep mongod"
192.168.0.248 | SUCCESS | rc=0 >>
mongod 1089 root 7u IPv4 10866 0t0 TCP 192.168.0.248:27017 (LISTEN)
mongod 1089 root 29u IPv4 13873 0t0 TCP 192.168.0.248:27017->192.168.0.9:54846 (ESTABLISHED)
mongod 1089 root 30u IPv4 11057 0t0 TCP 192.168.0.248:27017->192.168.0.247:35553 (ESTABLISHED)
mongod 1089 root 31u IPv4 13350 0t0 TCP 192.168.0.248:27017->192.168.0.8:34084 (ESTABLISHED)
mongod 1089 root 32u IPv4 13353 0t0 TCP 192.168.0.248:37493->192.168.0.8:27017 (ESTABLISHED)
mongod 1089 root 33u IPv4 13875 0t0 TCP 192.168.0.248:60433->192.168.0.9:27017 (ESTABLISHED)
mongod 1089 root 34u IPv4 13371 0t0 TCP 192.168.0.248:49951->192.168.0.247:27017 (ESTABLISHED)
mongod 1089 root 35u IPv4 13390 0t0 TCP 192.168.0.248:27017->192.168.0.8:34095 (ESTABLISHED)
mongod 1089 root 37u IPv4 13391 0t0 TCP 192.168.0.248:27017->192.168.0.8:34096 (ESTABLISHED)
若是重啓沒有生效請手動重啓:
# /usr/bin/mongod -f /mongodb/conf/mongodb-slaver.conf
5、配置主、備、仲裁節點(Replica Set集羣)
能夠經過客戶端鏈接mongodb,也能夠直接在三個節點中選擇一個鏈接mongodb
[root@redis248 conf]# mongo 192.168.0.248:27017
MongoDB shell version v3.4.0
connecting to: mongodb://192.168.0.248:27017
MongoDB server version: 3.4.0
Server has startup warnings:
2017-01-13T11:39:12.722+0800 I STORAGE [initandlisten]
2017-01-13T11:39:13.510+0800 I CONTROL [initandlisten]
2017-01-13T11:39:13.510+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-01-13T11:39:13.510+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2017-01-13T11:39:13.510+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2017-01-13T11:39:13.510+0800 I CONTROL [initandlisten]
> cfg={_id:"xcprs",members:[{_id:0,host:'192.168.0.248:27017',priority:3},{_id:1,host:'192.168.0.8:27017',priority:2},{_id:2,host:'192.168.0.9:27017',priority:1},{_id:3,host:'192.168.0.247:27017',arbiterOnly:true}]};
{
"_id" : "xcprs",
"members" : [
{
"_id" : 0,
"host" : "192.168.0.248:27017",
"priority" : 3
},
{
"_id" : 1,
"host" : "192.168.0.8:27017",
"priority" : 2
},
{
"_id" : 2,
"host" : "192.168.0.9:27017",
"priority" : 1
},
{
"_id" : 3,
"host" : "192.168.0.247:27017",
"arbiterOnly" : true
}
]
}
> rs.initiate(cfg)
{ "ok" : 1 }
cfg是能夠任意的名字,固然最好不要是mongodb的關鍵字,conf,config均可以。最外層的_id表示replica set的名字,members裏包含的是全部節點的地址以及優先級。優先級最高的即成爲主節點,即這裏的192.168.0.248:27017。特別注意的是,對於仲裁節點,須要有個特別的配置——arbiterOnly:true。這個千萬不能少了,否則主備模式就不能生效。配置的生效時間根據不一樣的機器配置會有長有短,配置不錯的話基本上十幾秒內就能生效,有的配置須要一兩分鐘。若是生效了,執行rs.status()命令會看到以下信息:
xcprs:OTHER> rs.status();
{
"set" : "xcprs",
"date" : ISODate("2017-01-13T03:44:18.672Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.0.248:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 306,
"optime" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-01-13T03:44:09Z"),
"electionTime" : Timestamp(1484278888, 1),
"electionDate" : ISODate("2017-01-13T03:41:28Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.0.8:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 180,
"optime" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-01-13T03:44:09Z"),
"optimeDurableDate" : ISODate("2017-01-13T03:44:09Z"),
"lastHeartbeat" : ISODate("2017-01-13T03:44:17.086Z"),
"lastHeartbeatRecv" : ISODate("2017-01-13T03:44:17.358Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.0.9:27017",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.0.9:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 180,
"optime" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1484279049, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-01-13T03:44:09Z"),
"optimeDurableDate" : ISODate("2017-01-13T03:44:09Z"),
"lastHeartbeat" : ISODate("2017-01-13T03:44:17.086Z"),
"lastHeartbeatRecv" : ISODate("2017-01-13T03:44:17.969Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.0.248:27017",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "192.168.0.247:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 180,
"lastHeartbeat" : ISODate("2017-01-13T03:44:17.086Z"),
"lastHeartbeatRecv" : ISODate("2017-01-13T03:44:14.898Z"),
"pingMs" : NumberLong(0),
"configVersion" : 1
}
],
"ok" : 1
}
xcprs:PRIMARY>
若是配置正在生效,其中會包含以下信息:
"stateStr" : "RECOVERING"
同時能夠查看對應節點的日誌,發現正在等待別的節點生效或者正在分配數據文件。
6、測試
一、往主節點插入數據,能從備節點查到以前插入的數據
PRIMARY> use test;
switched to db test
PRIMARY> db.user.insert({name:'jack',age:80});
PRIMARY> db.user.find();
{ "_id" : ObjectId("55069502bcdd8c8031522ddb"), "name" : "jack", "age" : 80 }
二、停掉主節點,備節點能變成主節點提供服務
能夠直接重啓或端口網絡便可:
此時,咱們能夠發現主節點是不可用的
三、恢復主節點,備節點也能恢復其備的角色,而不是繼續充當主的角色
主節點192.168.0.248:27017又獲取PRIMARY
注意:
當咱們在 replica set 進行檢索操做時,默認的路由會選擇 master 機器,當咱們需 要針對任意的從機進行查詢的時候,咱們須要開啓 slaveOk 選項。當咱們在沒有 開啓 salveOk 選項的時候,若是進行此操做會報以下錯:
*** not master and slaveok=false 因此咱們要進行以下操做:
rs.slaveOk(); // enable querying a secondary
db.user.find(...)