簡介html
mongodb複製(replication)是將數據同步在多個服務器的過程。主節點記錄在其上的全部操做oplog,從節點按期輪詢主節點獲取這些操做,而後對本身的數據副本執行這些操做,從而保證從節點的數據與主節點一致。複製提供了數據的冗餘備份,並在多個服務器上存儲數據副本,提升了數據的可用性,並保證數據的安全性。複製還容許您從硬件故障和服務中斷中恢復數據。linux
而副本集(replica set)是從mongodb 1.6 提供的新功能,比複製功能要強大一些並增長了故障自動切換和自動修復成員節點,各個DB之間數據徹底一致。Replica Sets的結構相似一個集羣,徹底能夠把它當成一個集羣,由於它確實與集羣實現的做用是同樣的,若是其中一個節點出現故障,其餘節點立刻回將業務接管過來而無需停機操做。sql
提示:關於mongodb相關核心理論知識,建議去看對應的文檔以及書籍,我這裏就不作對應的介紹(由於理論的東西寫起來太費勁)。mongodb
安裝shell
提示:本環境爲3臺主機的環境,IP分別爲192.168.58.128(PRIMARY)、192.168.58.129(SECONDARY)、192.168.58.130(ARBITER);數據庫
1、安裝mongodb安全
1.1 安裝mongodbbash
下載:https://www.mongodb.org/dl/linux/x86_64-rhel70;服務器
mkdir /data tar zxf mongodb-linux-x86_64-rhel70-3.2.0.tgz mv mongodb-linux-x86_64-rhel70-3.2.0 /data/mongodb-3.2.0 mkdir /data/mongodb-3.2.0/{data,conf,logs}
1.2 配置mongodbapp
首先關閉透明頁面,自CentOS6版本開始引入了Transparent Huge Pages(THP),從CentOS7版本開始,該特性默認就會啓用。儘管THP的本意是爲提高內存的性能,不過某些數據庫廠商仍是建議直接關閉THP(好比Redis和MongoDB等),不然可能會致使性能出現降低。
# 查看是否啓用
[root@localhost ~]# cat /sys/kernel/mm/transparent_hugepage/defrag [always] madvise never [root@localhost ~]# cat /sys/kernel/mm/transparent_hugepage/enabled [always] madvise never
# 禁用HTP功能
將如下內容加入到"/etc/rc.d/rc.local"文件中,記得執行"chmod +x /etc/rc.d/rc.local"。
# disable THP(Transparent Huge Pages) echo never >> /sys/kernel/mm/transparent_hugepage/enabled echo never >> /sys/kernel/mm/transparent_hugepage/defrag
# 建立keyfile文件
openssl rand -base64 756 > /data/mongodb-3.2.0/conf/mongodb_authkey chmod 600 /data/mongodb-3.2.0/conf/mongodb_authkey scp /data/mongodb-3.2.0/conf/mongodb_authkey 192.168.58.129:/data/mongodb-3.2.0/conf/ scp /data/mongodb-3.2.0/conf/mongodb_authkey 192.168.58.130:/data/mongodb-3.2.0/conf/
提示:
keyfile文件是副本集不可缺乏的,他們之間的通訊依賴於此。不過我在測試yum安裝的時候,彷佛不須要該配置,然而在二進制安裝的時候,若是缺乏keyfile就提示認證失敗。
# 配置mongodb配置文件
[root@localhost ~]# cat /data/mongodb-3.2.0/conf/mongodb.conf bind_ip=192.168.58.128 port=5336 dbpath=/data/mongodb-3.2.0/data logpath=/data/mongodb-3.2.0/logs/mongodb.logs logappend=true replSet=mongodb01 fork=true auth=true directoryperdb=true maxConns=8000 cpu=true oplogSize=8000
提示:建議先關閉"auth=true"參數以及禁用掉keyFile,由於若是開啓該配置項在初次添加副本集的過程當中,須要進行相關認證。可是,此時你並無相關用戶和密碼,致使你沒法經過mongodb認證。若是不由用,就會出現以下錯誤:
> db.createUser({
... user: "admin",
... pwd: "123456",
... roles: [{
... role: "userAdminAnyDatabase",
... db: "admin"
... }]
... })
2017-10-11T17:17:19.247+0800 E QUERY [thread1] Error: couldn't add user: not authorized on admin to execute command { createUser: "admin", pwd: "xxx", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ], digestPassword: false, writeConcern: { w: "majority", wtimeout: 30000.0 } } :
_getErrorWithCode@src/mongo/shell/utils.js:23:13
DB.prototype.createUser@src/mongo/shell/db.js:1225:11
因此先禁止掉該參數並在添加完新用戶以後再開啓認證功能。在其中一臺關閉就行,我這裏選擇在192.168.58.128(PRIMARY)主機上操做。
1.3 啓動mongodb
/data/mongodb-3.2.0/bin/mongod -f /data/mongodb-3.2.0/conf/mongodb.conf
3、配置副本集
3.1 建立一個管理用戶
/data/mongodb-3.2.0/bin/mongo 192.168.58.128:5336 > rs.initiate() { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "192.168.58.128:5336", "ok" : 1 } mongodb01:OTHER> db.createUser( { user: "admin", pwd: "admin@123", roles: [ { role: "root", db: "admin" } ] } ) mongodb01:PRIMARY> exit
3.2 開啓用戶認證並重啓服務
提示:在平常維護過程當中,mongodb關閉建議使用kill -2而不該該使用kill -9。
3.3 配置mongodb副本集
/data/mongodb-3.2.0/bin/mongo 192.168.58.128:5336 -u admin -p --authenticationDatabase admin
# 添加副本集
mongodb01:PRIMARY> show dbs admin 0.000GB local 0.000GB mongodb01:PRIMARY> rs.add("192.168.58.129:5336") mongodb01:PRIMARY> rs.addArb("192.168.58.130:5336") mongodb01:PRIMARY> rs.status()
# 測試複製
在插入數據
for(var i=0;i<100000;i++)db.test.insert({title: 'MongoDB 教程'+i, description: 'MongoDB 是一個 Nosql 數據庫'+i, by: '菜鳥教程'+i, url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 })
在PRIMARY和SECONDARY查看數據是否一致
db.test.count()
# 測試切換
kill 掉PRIMARY,並在SECONDARY查看狀態
mongodb01:PRIMARY> rs.status() { "set" : "mongodb01", "date" : ISODate("2017-09-20T02:15:23.819Z"), "myState" : 1, "term" : NumberLong(3), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "192.168.58.128:5336", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2017-09-20T02:15:21.902Z"), "lastHeartbeatRecv" : ISODate("2017-09-20T02:01:16.163Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Connection refused", "configVersion" : -1 }, { "_id" : 1, "name" : "192.168.58.129:5336", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 69990, "optime" : { "ts" : Timestamp(1505872886, 2), "t" : NumberLong(3) }, "optimeDate" : ISODate("2017-09-20T02:01:26Z"), "electionTime" : Timestamp(1505872886, 1), "electionDate" : ISODate("2017-09-20T02:01:26Z"), "configVersion" : 3, "self" : true }, { "_id" : 2, "name" : "192.168.58.130:5336", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 69615, "lastHeartbeat" : ISODate("2017-09-20T02:15:23.303Z"), "lastHeartbeatRecv" : ISODate("2017-09-20T02:15:21.905Z"), "pingMs" : NumberLong(0), "configVersion" : 3 } ], "ok" : 1 }
能夠看到原 SECONDARY 已經變爲 PRIMARY。此時咱們在向該PRIMARY插入數據;
mongodb01:PRIMARY> for(var i=0;i<100000;i++)db.test.insert({title: 'MongoDB 教程'+i,
description: 'MySQL 是一個 關係型數據庫'+i, by: '菜鳥教程'+i, url: 'http://www.runoob.com', tags: ['MySQL', 'database', 'SQL'], likes: 100 })
重啓剛kill掉的 "PRIMARY",查看數據是否同步
mongodb01:SECONDARY> db.getMongo().setSlaveOk() mongodb01:SECONDARY> db.test.count() 200000
最後,在給一些在生產環境中的建議,當某個節點宕機後從新啓動該節點會有一段的時間(時間長短視集羣的數據量和宕機時間而定)致使整個集羣中全部節點都成爲secondary而沒法進行寫操做(若是應用程序沒有設置相應的ReadReference也可能不能進行讀取操做)。
所以官方推薦的最小的副本集也應該具有一個primary節點和兩個secondary節點。兩個節點的副本集不具有真正的故障轉移能力。
最後的最後,MongoDB相關文章,參考http://www.cnblogs.com/zhanjindong/p/3268963.html,文章至關不錯。