手把手教你搭建mongodb副本集

傳傳.wang發表於2018-11-08

搭建mongodb副本集

一. 什麼是副本集

副本集(Replica Set)是一組MongoDB例項組成的叢集,由一個主(Primary)伺服器和多個備份(Secondary)伺服器構成。通過Replication,將資料的更新由Primary推送到其他例項上,在一定的延遲之後,每個MongoDB例項維護相同的資料集副本。通過維護冗餘的資料庫副本,能夠實現資料的異地備份,讀寫分離和自動故障轉移。
早期的MongoDB版本使用master-slave,一主一從和MySQL類似,但slave在此架構中為只讀,當主庫當機後,從庫不能自動切換為主。目前已經淘汰master-slave模式,改為副本集,這種模式下有一個主(primary),和多個從(secondary),只讀。支援給它們設定權重,當主宕掉後,權重最高的從切換為主。在此架構中還可以建立一個仲裁(arbiter)的角色,它只負責裁決,而不儲存資料。此架構中讀寫資料都是在主上,要想實現負載均衡的目的需要手動指定讀庫的目標server。 以上內容引自(blog.51cto.com/zero01/2059…

手把手教你搭建mongodb副本集

手把手教你搭建mongodb副本集

手把手教你搭建mongodb副本集

二. 開始動手搭建

副本集的目的是實現能夠持續性提供服務以及資料的異地安全備份,一般每個例項節點會存放在一個伺服器節點上,這裡沒有那麼多伺服器,便在同一伺服器上進行搭建,使用不同的埠建立例項。

1. 依次執行三條命令
```
mongod --dbpath=/home/mongodb/db/testReplPrim   --logpath=/home/mongodb/logs/mongolog_testReplPrim   --logappend --fork --port=27017 --replSet=testRepl  
```

```
mongod --dbpath=/home/mongodb/db/testReplSec1     --logpath=/home/mongodb/logs/mongolog_testReplSec1     --logappend --fork --port=27018 --replSet=testRepl  
```

```
mongod --dbpath=/home/mongodb/db/testReplSec2   --logpath=/home/mongodb/logs/mongolog_testReplSec2   --logappend --fork --port=27019 --replSet=testRepl
```
複製程式碼
2. 選擇一個mongodb例項作為primary節點,這裡我們選擇27017

連線到該例項

```
mongo --port 27017
```

 ```
 use admin
 ```
複製程式碼
3. 在admin下建立使用者
```
db.createUser({
 user:"test01",
 pwd:"abc123",
 roles:[{
 role:"userAdminAnyDatabase",db:"admin"
 },{
 role:"clusterAdmin",db:"admin"
 }]})
 ```

```
db.auth('test01','abc123')
```
複製程式碼
4. 初始化副本集
 ```
rs.initiate({"_id":"testRepl","members":[{"_id":0,"host":"10.10.10.10:27017",priority:3},{"_id":1,"host":"10.10.10.10:27018",priority:2},{"_id":2,"host":"10.10.10.10:27019",priority:0,slaveDelay:86400}]})
```

ip是隨機寫的,此時我們已經初始化好了mongodb副本集,其中27017是primary節點,27018和27019位secondary節點,20179例項會延時60秒同步資料。
複製程式碼
5. 新建一個資料庫
```use testdb```
複製程式碼
6. 建立一個user
```db.createUser({"user":"testdb01","pwd":"abc123",roles:[{role:"readWrite",db:"testdb"}]})```
複製程式碼
7. 新增一個customers集合並加一條文件
```db.customers.insert({"name":"wang"})```

此時,27017例項中,testdb庫下的customer集合會有一條文件,在其他兩個例項中也會有相同的資料
複製程式碼
8. 連線27018例項
 ```mongo --port 27018```

 ```use testdb```

```show collections```
複製程式碼
9. 這時會顯示:
```
2018-11-08T16:50:10.122+0800 E QUERY    [thread1] Error: listCollections failed: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype._getCollectionInfosCommand@src/mongo/shell/db.js:773:1
DB.prototype.getCollectionInfos@src/mongo/shell/db.js:785:19
DB.prototype.getCollectionNames@src/mongo/shell/db.js:796:16
shellHelper.show@src/mongo/shell/utils.js:753:9
shellHelper@src/mongo/shell/utils.js:650:15
@(shellhelp2):1:1
```

由於我們是在secondary節點,需要執行如下命令

```rs.slaveOk()```

```show collections```
複製程式碼

手把手教你搭建mongodb副本集

10. 可以看到,secondary節點已經將資料同步過來了,至此我們已經完成了基本副本集的搭建,不過,不過顯而易見的是,我們在啟動資料庫例項的時候並沒有新增--auth選項,也就是說,我們不需要任何驗證就可以對資料庫進行操作,這在生產環境中是不可行的,所以我們需要新增--auth選項,那我們先把三個服務例項關閉
```
mongod --dbpath=/home/mongodb/db/testReplPrim --logpath=/home/mongodb/logs/mongolog_testReplPrim --logappend --fork --port=27017 --replSet=testRepl   --shutdown
```

```
    mongod --dbpath=/home/mongodb/db/testReplSec1 --logpath=/home/mongodb/logs/mongolog_testReplSec1 --logappend --fork --port=27018 --replSet=testRepl --shutdown
```
    
```
mongod --dbpath=/home/mongodb/db/testReplSec2 --logpath=/home/mongodb/logs/mongolog_testReplSec2 --logappend --fork --port=27019 --replSet=testRepl 
--shutdown
```
複製程式碼
11. 然後分別啟動三個例項
  ```
mongod --dbpath=/home/mongodb/db/testReplPrim --logpath=/home/mongodb/logs/mongolog_testReplPrim --logappend --fork --port=27017 --replSet=testRepl --auth
```

```
    mongod --dbpath=/home/mongodb/db/testReplSec1 --logpath=/home/mongodb/logs/mongolog_testReplSec1 --logappend --fork --port=27018 --replSet=testRepl --auth
    ```
  
  ```
    mongod --dbpath=/home/mongodb/db/testReplSec2 --logpath=/home/mongodb/logs/mongolog_testReplSec2 --logappend --fork --port=27019 --replSet=testRepl 
    --auth
    ```
複製程式碼
12. 連線primary例項節點
  ```mongo --port 27017```

  ```use admin```
  
  ```db.auth('test01','abc123')```
  
  ```rs.status()```
  
 會看到如下狀態
 
  ```
    {
	"set" : "testRepl",
	"date" : ISODate("2018-11-08T10:36:32.750Z"),
	"myState" : 3,
	"term" : NumberLong(6),
	"heartbeatIntervalMillis" : NumberLong(2000),
	"members" : [
		{
			"_id" : 0,
			"name" : "10.10.10.10:25231",
			"health" : 1,
			"state" : 3,
			"stateStr" : "RECOVERING",
			"uptime" : 1002,
			"optime" : {
				"ts" : Timestamp(1541671316, 2),
				"t" : NumberLong(6)
			},
			"optimeDate" : ISODate("2018-11-08T10:01:56Z"),
			"infoMessage" : "could not find member to sync from",
			"configVersion" : 1,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "10.10.10.10:25232",
			"health" : 0,
			"state" : 6,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2018-11-08T10:36:30.447Z"),
			"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
			"pingMs" : NumberLong(0),
			"authenticated" : false,
			"configVersion" : -1
		},
		{
			"_id" : 2,
			"name" : "10.10.10.10:25233",
			"health" : 0,
			"state" : 6,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2018-11-08T10:36:30.452Z"),
			"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
			"pingMs" : NumberLong(0),
			"authenticated" : false,
			"configVersion" : -1
		}
	],
	"ok" : 1
}
```

說明主節點無法建立與其他節點互訪認證,那如何建立互訪認證呢,就需要用到Keyfile
複製程式碼

三. 使用keyfile訪問控制的方式建立各節點間認證機制

1. 生成keyfile
 `openssl rand -base64 100 > /usr/local/keyfile/mongodb_keyfile`
複製程式碼
2. 修改檔案許可權
 `chmod 600 /usr/local/keyfile/mongodb_keyfile`
複製程式碼
3. 將生成的keyfile檔案拷貝到各節點的機器上,注意路徑要和mongodb啟動時指定的keyfile路徑一致
4. 關閉三個服務例項
   `mongod --dbpath=/home/mongodb/db/testReplPrim --logpath=/home/mongodb/logs/mongolog_testReplPrim --logappend --fork --port=27017 --replSet=testRepl --shutdown`

   `mongod --dbpath=/home/mongodb/db/testReplSec1 --logpath=/home/mongodb/logs/mongolog_testReplSec1 --logappend --fork --port=27018 --replSet=testRepl --shutdown`
   
   `mongod --dbpath=/home/mongodb/db/testReplSec2 --logpath=/home/mongodb/logs/mongolog_testReplSec2 --logappend --fork --port=27019 --replSet=testRepl --shutdown`
複製程式碼
5. 重啟三個服務例項
   `mongod --dbpath=/home/mongodb/db/testReplPrim --logpath=/home/mongodb/logs/mongolog_testReplPrim --logappend --fork --port=27017 --replSet=testRepl keyFile=/usr/local/keyfile/mongodb_keyfile --auth`

   `mongod --dbpath=/home/mongodb/db/testReplSec1 --logpath=/home/mongodb/logs/mongolog_testReplSec1 --logappend --fork --port=27018 --replSet=testRepl keyFile=/usr/local/keyfile/mongodb_keyfile --auth`
   
   `mongod --dbpath=/home/mongodb/db/testReplSec2 --logpath=/home/mongodb/logs/mongolog_testReplSec2 --logappend --fork --port=27019 --replSet=testRepl keyFile=/usr/local/keyfile/mongodb_keyfile--auth`
複製程式碼
6. 連線埠為21071例項
   `mongo --port 27017`

   `use admin`
   
   `db.auth('test01','abc123')`
   
   `rs.status()`
複製程式碼

手把手教你搭建mongodb副本集
大功告成,此時我們在主節點新增資料時,在secondary節點就可以同步顯示出來,27019節點延時60秒,這裡不再做演示。ok,為什麼貼這麼多命令呢而沒有太多的講解呢,直觀(懶)嘛,跟著命令搞一遍自然就懂了,具體細節看起來就容易了。

相關文章