搭建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…
二. 開始動手搭建
副本集的目的是實現能夠持續性提供服務以及資料的異地安全備份,一般每個例項節點會存放在一個伺服器節點上,這裡沒有那麼多伺服器,便在同一伺服器上進行搭建,使用不同的埠建立例項。
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```
複製程式碼
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()`
複製程式碼
大功告成,此時我們在主節點新增資料時,在secondary節點就可以同步顯示出來,27019節點延時60秒,這裡不再做演示。ok,為什麼貼這麼多命令呢而沒有太多的講解呢,直觀(懶)嘛,跟著命令搞一遍自然就懂了,具體細節看起來就容易了。