MongoDB在單節點中也能夠作複製集,可是僅限於測試實驗,最大的好處就是部署方便快速,能夠隨便添加新節點,節省資源。在這裏我使用的是MongoDB 3.2版本進行復制集實驗(但MongoDB配置文件使用的是老版本格式),一共使用三個節點,一個是主節點(PRIMARY),一個是從節點(SECONDARY),一個是投票節點(ARBITER)。以下圖:node
1、實驗環境linux
1)節點信息:192.168.60.10mongodb
3)節點確保iptables和selinux已關閉shell
1
2
|
[root@node1 ~]# iptables -F
[root@node1 ~]# setenforce 0
|
2、安裝MongoDB 3.2數據庫
1
2
3
4
5
|
mongodb-org-3.2.0-1.el6.x86_64.rpm
mongodb-org-mongos-3.2.0-1.el6.x86_64.rpm
mongodb-org-server-3.2.0-1.el6.x86_64.rpm
mongodb-org-shell-3.2.0-1.el6.x86_64.rpm
mongodb-org-tools-3.2.0-1.el6.x86_64.rpm
|
PS:須要的軟件包能夠去https://repo.mongodb.org/yum/redhat/下載,MongoDB的安裝很簡單,怎麼安裝都成。數組
3、配置單點複製集(啓動三個套接字)架構
1)建立所須要的目錄app
1
2
3
4
5
6
|
$ mkdir -p /data/mongodb/{conf,log,pid,data}
$ mkdir -p /data/mongodb/conf/{conf27017,conf27018,conf27019}
$ mkdir -p /data/mongodb/log/{log27017,log27018,log27019}
$ mkdir -p /data/mongodb/pid/{pid27017,pid27018,pid27019}
$ mkdir -p /data/mongodb/data/{data27017,data27018,data27019}
$ chown -R mongod.mongod /data/mongodb/data/{data27017,data27018,data27019}
|
2)建立三個配置文件tcp
192.168.60.10:27017ide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
$ cat /data/mongodb/conf/conf27017/mongod.conf
# 開啓日誌文件;
logpath = /data/mongodb/log/log27017/mongod.log
# 開啓日誌追加;
logappend = true
# 指定數據目錄;
dbpath = /data/mongodb/data/data27017
# 實例端口;
port = 27017
# 綁定地址;
bind_ip = 0.0.0.0
# 守護進程模式開啓;
fork = true
# 進程號文件;
pidfilepath = /data/mongodb/pid/pid27017/mongod.pid
# 日誌迴轉;
logRotate = rename
# 日誌時間格式;
timeStampFormat = ctime
# 日誌刷盤間隔(默認100毫秒);
journalCommitInterval = 100
# 數據刷盤間隔(默認60秒);
syncdelay = 60
# 最大鏈接數(默認65536);
maxConns = 65536
###Replica Set
# Oplog大小(單位MB);
oplogSize = 1024
# 複製集名稱;
replSet = ywnds
|
192.168.60.10:27018
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
$ cat /data/mongodb/conf/conf27018/mongod.conf
logpath = /data/mongodb/log/log27018/mongod.log
logappend = true
dbpath = /data/mongodb/data/data27018
port = 27018
bind_ip = 0.0.0.0
fork = true
pidfilepath = /data/mongodb/pid/pid27018/mongod.pid
logRotate = rename
timeStampFormat = ctime
journalCommitInterval = 100
syncdelay = 60
maxConns = 65536
###Replica Set
oplogSize = 1024
replSet = ywnds
|
192.168.60.10:27019
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
$ cat /data/mongodb/conf/conf27019/mongod.conf
logpath = /data/mongodb/log/log27019/mongod.log
logappend = true
dbpath = /data/mongodb/data/data27019
port = 27019
bind_ip = 0.0.0.0
fork = true
pidfilepath = /data/mongodb/pid/pid27019/mongod.pid
logRotate = rename
timeStampFormat = ctime
journalCommitInterval = 100
syncdelay = 60
maxConns = 65536
###Replica Set
oplogSize = 1024
replSet = ywnds
|
PS:更多具體參數詳細含義請看《MongoDB命令行選項介紹》
3)啓動集羣(全部節點)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
$ killall mongod
$ mongod -f /data/mongodb/conf/conf27019/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 35554
child process started successfully, parent exiting
$ mongod -f /data/mongodb/conf/conf27018/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 35601
child process started successfully, parent exiting
$ mongod -f /data/mongodb/conf/conf27017/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 35648
child process started successfully, parent exiting
|
查看進程三個節點都啓動
1
2
3
4
|
$ netstat -anplt | grep mongod
tcp 0 0 0.0.0.0:27019 0.0.0.0:* LISTEN 35554/mongod
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 35648/mongod
tcp 0 0 0.0.0.0:27018 0.0.0.0:* LISTEN 35601/mongod
|
4)選擇一個節點作主節點(能夠隨意選擇一個,這裏我使用21017)
1
2
3
4
|
$ mongo 192.168.60.10:27017/admin
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27017/admin
>
|
5)初始化27017節點
5.1.爲複製集初始化創建配置文檔
1
2
3
4
5
6
7
|
> config = {
_id:"ywnds",
members:[
{_id:0,host:"192.168.60.10:27017"},
{_id:1,host:"192.168.60.10:27018"},
{_id:2,host:"192.168.60.10:27019"}
]}
|
5.2.更新配置文檔參數,設置27019爲arbiterOnly(投票節點)
1
|
> config.members[2] = {"_id":2,"host":"192.168.60.10:27019","arbiterOnly":true}
|
PS:上面是把複製集初始化配置文檔賦值給config變量,這裏是經過membes數組的索引來修改節點屬性,數組索引從0開始。
具體的配置文檔說明請看《MongoDB複製集配置文檔介紹》
5.3.使用rs.initiate(cfg)初始化集羣
1
2
3
4
5
|
> rs.initiate(config)
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
|
這裏使用rs.initiate(config)初始化集羣,config文件爲咱們上面定義的。這裏的ok返回值爲1表示命令執行成功,若是爲0則表示沒有執行成功。跟Linux中的狀態值恰好相反。如今可使用rs.conf()方法返回配置文件內容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
ywnds:PRIMARY> rs.conf()
{
"_id" : "ywnds",
"version" : 2,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "192.168.60.10:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "192.168.60.10:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.60.10:27019",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
}
}
}
|
在Mongodb3.2版本中,相比以前的版本rs.conf返回配置文件的信息更加詳細了。把」arbiterOnly」、」buildIndexes」、」hidden」、」priority」、」tags」、」slaveDelay」、」votes」的默認值都給真是出來了,具體的含義看《MongoDB複製集配置文檔介紹》。
5.4.查看集羣狀態
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
ywnds:PRIMARY> rs.status()
{
"set" : "ywnds",
"date" : ISODate("2016-02-03T01:56:49Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "192.168.60.10:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1043,
"optime" : Timestamp(1454464583, 1),
"optimeDate" : ISODate("2016-02-03T01:56:23Z"),
"electionTime" : Timestamp(1454464592, 1),
"electionDate" : ISODate("2016-02-03T01:56:32Z"),
"self" : true
},
{
"_id" : 1,
"name" : "192.168.60.10:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 25,
"optime" : Timestamp(1454464583, 1),
"optimeDate" : ISODate("2016-02-03T01:56:23Z"),
"lastHeartbeat" : ISODate("2016-02-03T01:56:48Z"),
"lastHeartbeatRecv" : ISODate("2016-02-03T01:56:47Z"),
"pingMs" : 2,
"syncingTo" : "192.168.60.10:27017"
},
{
"_id" : 2,
"name" : "192.168.60.10:27019",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 25,
"lastHeartbeat" : ISODate("2016-02-03T01:56:48Z"),
"lastHeartbeatRecv" : ISODate("2016-02-03T01:56:47Z"),
"pingMs" : 0
}
],
"ok" : 1
}
|
咱們的集羣中有三個節點,由狀態返回值能夠看出27017爲PRIMARY節點,而27018爲SECONDARY節點,而27019爲咱們設置的ARBITER節點。這裏咱們發現mongodb的角標已經變了,變成了複製集名稱加上當前節點的狀態。一樣若是登錄27018和27019會發現都發生了變化。
5.5.查看主節點local庫
1
2
3
4
5
6
7
8
9
10
|
ywnds:PRIMARY> use local
switched to db local
ywnds:PRIMARY> show tables
me
oplog.rs
replset.minvalid
slaves
startup_log
system.indexes
system.replset
|
這裏咱們看一下本地的local庫,每個mongod實例都有本身的local數據庫,其中存儲了複製進程所用的數據和其餘實例單獨的信息,local數據庫對於複製時不可見的,local數據庫將不會被複制。
進入到local庫能夠看到一些集合和索引文件,其中startup_log 是一個固定集合,該集合主要是用來診斷的(每一個mongod 實例向 startup_log 插入一條有關mongod實例自身和host信息的診斷信息);system.replset保存了複製集的配置文檔信息(就是咱們上面定義的config),跟rs.conf()返回的信息同樣;oplog.rs是一個存儲了oplog的固定集合,大小爲咱們在配置文件中設置的大小;replset.minvalid包含了複製集內部定位複製集狀態信息;slaves包含了複製集每一個節點和與其通信的最後時間戳。若是該集合過期了,咱們能夠經過刪除該節點來讓複製集自動刷新生成。
6)驗證複製集
192.168.60.10:27017插入數據
1
2
3
4
5
6
7
|
$ mongo 192.168.60.10:27017
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27017/test
ywnds:PRIMARY> use ywnds
switched to db ywnds
ywnds:PRIMARY> db.ywnds.insert({name:"ywnds",age:"20",gender:"B"})
WriteResult({ "nInserted" : 1 })
|
而後咱們來看一下主節點的數據目錄(WiredTiger存儲引擎爲例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
$ ll -h /data/mongodb/data/data27017/
總用量
400K
-rw-r--r--. 1 root root 16K 1月 18 03:29 collection-0--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 03:29 collection-2--3354265032980496329.wt
-rw-r--r--. 1 root root 36K 1月 18 04:26 collection-4--3354265032980496329.wt
-rw-r--r--. 1 root root 32K 1月 18 03:39 collection-5--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 03:32 collection-7--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 04:26 collection-9--3354265032980496329.wt
drwxr-xr-x. 2 root root 4.0K 1月 18 04:33 diagnostic.data
-rw-r--r--. 1 root root 16K 1月 18 04:26 index-10--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 03:29 index-1--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 03:29 index-3--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 03:32 index-6--3354265032980496329.wt
-rw-r--r--. 1 root root 16K 1月 18 03:32 index-8--3354265032980496329.wt
drwxr-xr-x. 2 root root 4.0K 1月 18 03:28 journal
-rw-r--r--. 1 root root 36K 1月 18 04:26 _mdb_catalog.wt
-rw-r--r--. 1 root root 6 1月 18 03:28 mongod.lock
-rw-r--r--. 1 root root 36K 1月 18 04:26 sizeStorer.wt
-rw-r--r--. 1 root root 95 1月 18 03:28 storage.bson
-rw-r--r--. 1 root root 49 1月 18 03:28 WiredTiger
-rw-r--r--. 1 root root 4.0K 1月 18 03:28 WiredTigerLAS.wt
-rw-r--r--. 1 root root 21 1月 18 03:28 WiredTiger.lock
-rw-r--r--. 1 root root 920 1月 18 04:26 WiredTiger.turtle
-rw-r--r--. 1 root root 64K 1月 18 04:26 WiredTiger.wt
|
這裏咱們能夠看到,因爲使用了WiredTiger存儲引擎,數據存儲格式都跟MongoDB 2.6(使用MMAPV1存儲引擎)不一樣了。
192.168.60.10:27018同步數據
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
$ mongo 192.168.60.10:27018
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27018/test
ywnds:SECONDARY> rs.slaveOk()
ywnds:SECONDARY> show dbs
local 0.000GB
ywnds 0.000GB
ywnds:SECONDARY> use ywnds
switched to db ywnds
ywnds:SECONDARY> show tables
2016-02-03T11:34:24.505+0800 error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
ywnds:SECONDARY> db.ywnds.insert({name:"eric",age:20})
WriteResult({ "writeError" : { "code" : undefined, "errmsg" : "not master" } })
ywnds:SECONDARY> rs.slaveOk(true)
ywnds:SECONDARY> show tables
ywnds
ywnds:SECONDARY> db.ywnds.find()
{ "_id" : ObjectId("569bf8b9a0c81df2ebc0d75d"), "name" : "ywnds", "age" : 20, "gender" : "B" }
|
咱們看到數據已經同步過來了,可是若是咱們不是經過驅動鏈接從節點的話,咱們查看數據時會報錯,說咱們不是master節點,且slaveOK=false,因此查看不了。MongoDB在數據一致性上確實下了很大的功夫啊。那麼也就是說若是從節點想查看數據就須要開啓slaveOK,而且在從節點上是沒法進行寫入操做的。而後咱們開啓rs.slaveOk(1)立馬就能夠查看同步的數據了。
192.168.60.10:27019投票節點
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$ mongo 192.168.60.10:27019
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27019/test
ywnds:ARBITER> show dbs
admin (empty)
local 0.078GB
ywnds:ARBITER> use local
switched to db local
ywnds:ARBITER> show tables
me
startup_log
system.indexes
system.replset
|
鏈接到投票節點,咱們能夠看到PRIMARY上的數據沒有同步到投票節點上來,沒有ywnds這個庫。可是這裏須要說明的是,咱們能夠看到arbiter雖然不一樣步數據可是local庫卻有system.indexes和system.replset這兩個文件。另外咱們能夠發現local數據的大小爲0.078GB(80M),庫物理文件的第一個文件默認大小爲64M,而命名空間文件爲16M。
4、按照功能來區分複製集成員
從上面的分析能夠看出三個節點的不一樣之處,也能夠這麼說,上面咱們是按照數據來區分不一樣的複製集節點,那麼下面咱們按照功能上來區分各個節點。先來簡單說一下各個節點狀態的不一樣所能提供的功能有哪些?
主節點(PRIMARY):默認提供讀寫服務的節點。
從節點(SECONDARY):提供讀服務的節點,但能夠提供多樣性服務,如能夠轉爲「隱藏節點」對程序不可見、轉爲「延時節點」延時複製節點、轉爲「投票節點」具備投票權但不是arbiter。
投票節點(ARBITER):ARBITER節點,無數據,僅做選舉和充當複製集節點、也稱它爲選舉節點。
5、複製集自動容災
Mongodb複製集最大的特色就是能夠自動容災,這個特性是從主從複製的架構上改變而來,簡單來講就是當複製集(3節點)中若是PRIMARY發生故障,其餘節點沒法探測到它的心跳信息時,複製集就會產生重新投票選出一個新的PRIAMRY提供服務。下面咱們來模擬一下MongoDB的自動故障轉移功能。
咱們鏈接到27017主機上,此時的27017是PRIMARY
1
2
3
4
|
$ mongo 192.168.60.10:27017
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27017/test
ywnds:PRIMARY>
|
咱們鏈接到27018主機上,此時的27018是SECONDARY
1
2
3
4
|
$ mongo 192.168.60.10:27018
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27018/test
ywnds:SECONDARY>
|
咱們鏈接到27019主機上,此時的27019是ARBITER
1
2
3
4
|
$ mongo 192.168.60.10:27019
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27019/test
ywnds:ARBITER>
|
模擬主節點宕機,kill掉27017的進程。
1
2
3
4
5
6
|
$ cat /mongodb/pid/pid27017/mongod.pid
125484
$ kill -2 125484
$ ps aux | grep mongod
root 125581 0.5 7.9 5266620 48252 ? Sl 04:07 0:00 mongod -f /data/mongodb/conf/conf27018/mongod.conf
root 125670 0.5 5.1 849056 31440 ? Sl 04:07 0:00 mongod -f /data/mongodb/conf/conf27019/mongod.conf
|
而後登陸27018主機上,看看此時的SECONDARY已經轉爲PRIMARY了,可是這個過程會有短暫的斷開。
1
2
3
4
|
$ mongo 192.168.60.10:27018
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27018/test
ywnds:PRIMARY>
|
而27019主機上ARBITER仍是ARBITER節點。
1
2
3
4
|
$ mongo 192.168.60.10:27019
MongoDB shell version: 3.2.0
connecting to: 192.168.60.10:27019/test
ywnds:ARBITER>
|
有興趣能夠經過show log rs命令查看複製集的日誌信息,看看這個過程是怎麼進行的。這就是MongoDB三節點(一主一從一投票或一主二從)複製集的故障轉移功能,是否是很強大。固然除了複製集內部自動選舉以外,咱們也能夠進行人工干預,使用rs.stepdown()方法能夠手動切換。