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



二. 開始動手搭建
副本集的目的是實現能夠持續性提供服務以及資料的異地安全備份,一般每個例項節點會存放在一個伺服器節點上,這裡沒有那麼多伺服器,便在同一伺服器上進行搭建,使用不同的埠建立例項。
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" : "59.110.11.138: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" : "59.110.11.138: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" : "59.110.11.138: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,為什麼貼這麼多命令呢而沒有太多的講解呢,直觀(懶)嘛,跟著命令搞一遍自然就懂了,具體細節看起來就容易了。