#####################################
副本集管理命令大全:
rs.add() 為復制集新增節點。 rs.addArb() 為復制集新增一個 arbiter rs.conf() 返回復制集配置信息 rs.freeze() 防止當前節點在一段時間內選舉成為主節點。 rs.help() 返回 replica set 的命令幫助 rs.initiate() 初始化一個新的復制集。 rs.printReplicationInfo() 以主節點的視角返回復制的狀態報告。 rs.printSlaveReplicationInfo() 以從節點的視角返回復制狀態報告。 rs.reconfig() 通過重新應用復制集配置來為復制集更新配置。 rs.remove() 從復制集中移除一個節點。 rs.slaveOk() 為當前的連接設置 slaveOk 。不推薦使用。使用 readPref() 和 Mongo.setReadPref() 來設置 read preference 。 rs.status() 返回復制集狀態信息。 rs.stepDown() 讓當前的 primary 變為從節點並觸發 election 。 rs.syncFrom() 設置復制集節點從哪個節點處同步數據,將會覆蓋默認選取邏輯。
過程1:
副本集成員實例的keyfile文件要求:每個實例的keyfile文件內容完全相同,keyfile文件的權限為0600,keyfile文件的所屬組合所屬主均為work用戶:安裝mongodb和生成相同keyfile文件:
如keyfile文件名稱為test:
[work@xxx etc]$ ll total 8 -rw-rw-r-- 1 work work 1228 Nov 27 11:23 mongodb.conf -rw------- 1 work work 1004 Nov 27 10:14 test
過程2:
副本集成員均先不要授權,即注釋掉授權配置,刪掉data目錄(dbpath)所有內容,然后啟動所有成員實例:去掉授權檢測,刪掉所有數據,啟動數據庫,只需在主庫上操作,其他從庫則不需要去掉授權檢測,直接刪除data目錄,保證keyfile文件相同即可:
過程3:
只在其中一個實例上執行:rs.initiate() ,千萬別在多個成員上執行,然后再該實例上執行:rs.add(hostportstr),來添加其他實例成員:初始化副本集,添加成員:
過程4:
然后再主庫的admin庫下創建超級管理員:創建用戶:
db.createUser({user:'mongo_dba',pwd:'123456',roles:['root']})
過程5:
開啟配置文件中的授權,關閉實例,再啟動實例:開啟授權,重啟實例:
###################################################################################################################
01 新加的節點一定不要再執行rs.initiate()了,即一個集群中,只有一個實例執行該方法,否則,無法構建主從;
只需不要在兩個服務器上都初始化復制即可
初始化副本集時:
1,關閉security配置,如下:
systemLog: destination: file path: /home/work/mongodb/mongo_28008/log/mongodb.log logAppend: true #net Options net: maxIncomingConnections: 10240 port: 28008 bindIp: 10.10.10.10,localhost serviceExecutor : adaptive #security Options #security: # authorization: 'enabled' # keyFile: /home/work/mongodb/mongo_28008/etc/test # clusterAuthMode: "keyFile" #storage Options storage: engine: "wiredTiger" directoryPerDB: true dbPath: /home/work/mongodb/mongo_28008/data indexBuildRetry: true journal: enabled: true commitIntervalMs: 100 wiredTiger: engineConfig: directoryForIndexes: true cacheSizeGB: 60 journalCompressor: "snappy" collectionConfig: blockCompressor: "snappy" indexConfig: prefixCompression: true #wiredTigerCollectionConfigString: lsm #wiredTigerIndexConfigString: lsm #replication Options replication: oplogSizeMB: 2048 #2GB replSetName: test #operationProfiling Options operationProfiling: slowOpThresholdMs: 100 mode: "slowOp" processManagement: fork: true pidFilePath: /home/work/mongodb/mongo_28008/tmp/mongo_28008.pid
2,需要在admin數據庫下創建管理員賬號,否則不成功,如下:
[work@hostname mongo_28008]$ /home/work/mongodb/3.6/bin/mongo --port 28008 Percona Server for MongoDB shell version v3.6.17-4.0 connecting to: mongodb://127.0.0.1:28008/?gssapiServiceName=mongodb Implicit session: session { "id" : UUID("03494baa-ad28-4ebe-89ea-ca3c6d523f90") } Percona Server for MongoDB server version: v3.6.17-4.0 Welcome to the Percona Server for MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see https://www.percona.com/doc/percona-server-for-mongodb Questions? Try the support group https://www.percona.com/forums/questions-discussions/percona-server-for-mongodb Server has startup warnings: 2020-10-28T15:33:16.353+0800 I STORAGE [initandlisten] 2020-10-28T15:33:16.353+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2020-10-28T15:33:16.353+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2020-10-28T15:33:16.353+0800 I STORAGE [initandlisten] 2020-10-28T15:33:16.353+0800 I STORAGE [initandlisten] ** WARNING: The configured WiredTiger cache size is more than 80% of available RAM. 2020-10-28T15:33:16.353+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/faq-memory-diagnostics-wt 2020-10-28T15:33:17.154+0800 I CONTROL [initandlisten] 2020-10-28T15:33:17.154+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2020-10-28T15:33:17.154+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2020-10-28T15:33:17.154+0800 I CONTROL [initandlisten] ** You can use percona-server-mongodb-enable-auth.sh to fix it. 2020-10-28T15:33:17.154+0800 I CONTROL [initandlisten] > rs.initiate() { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "10.10.10.10:28008", "ok" : 1, "operationTime" : Timestamp(1603870486, 1), "$clusterTime" : { "clusterTime" : Timestamp(1603870486, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } test:SECONDARY> db.createUser({user:'mongo_dba',pwd:'123456',roles:['root']}) 2020-10-28T15:34:55.470+0800 E QUERY [thread1] Error: couldn't add user: No role named root@test : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DB.prototype.createUser@src/mongo/shell/db.js:1437:15 @(shell):1:1 test:PRIMARY> db.createUser({user:'mongo_dba',pwd:'123456',roles:['root']}) 2020-10-28T15:35:04.103+0800 E QUERY [thread1] Error: couldn't add user: No role named root@test : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DB.prototype.createUser@src/mongo/shell/db.js:1437:15 @(shell):1:1 test:PRIMARY> use admin switched to db admin test:PRIMARY> db.createUser({user:'mongo_dba',pwd:'123456',roles:['root']}) Successfully added user: { "user" : "mongo_dba", "roles" : [ "root" ] } test:PRIMARY>
3,關閉實例,開啟security配置,如下:
[work@hostname mongo_28008]$ ps aux|grep mongod work 19967 0.0 0.0 103244 848 pts/1 S+ 15:40 0:00 grep mongod work 31347 2.0 0.3 1627896 58348 ? SLl 15:33 0:08 /home/work/mongodb/3.6/bin/mongod --config /home/work/mongodb/mongo_28008/etc/mongodb.conf [work@hostname mongo_28008]$ kill 31347 [work@hostname mongo_28008]$ vim /home/work/mongodb/mongo_28008/etc/mongodb.conf systemLog: destination: file path: /home/work/mongodb/mongo_28008/log/mongodb.log logAppend: true #net Options net: maxIncomingConnections: 10240 port: 28008 bindIp: 10.38.10.10,localhost serviceExecutor : adaptive #security Options security: authorization: 'enabled' keyFile: /home/work/mongodb/mongo_28008/etc/test clusterAuthMode: "keyFile" #storage Options storage: engine: "wiredTiger" directoryPerDB: true dbPath: /home/work/mongodb/mongo_28008/data indexBuildRetry: true journal: enabled: true commitIntervalMs: 100 wiredTiger: engineConfig: directoryForIndexes: true cacheSizeGB: 60 journalCompressor: "snappy" collectionConfig: blockCompressor: "snappy" indexConfig: prefixCompression: true #wiredTigerCollectionConfigString: lsm #wiredTigerIndexConfigString: lsm #replication Options replication: oplogSizeMB: 2048 #2GB replSetName: test #operationProfiling Options operationProfiling: slowOpThresholdMs: 100 mode: "slowOp" processManagement: fork: true pidFilePath: /home/work/mongodb/mongo_28008/tmp/mongo_28008.pid
4,開啟服務
[work@hostname mongo_28008]$ /home/work/mongodb/3.6/bin/mongod --config /home/work/mongodb/mongo_28008/etc/mongodb.conf about to fork child process, waiting until server is ready for connections. forked process: 20145 child process started successfully, parent exiting
######################
配置解讀:
storage:
engine: "wiredTiger"
directoryPerDB: true
dbPath: /home/work/mongodb/mongo_28008/data # string類型。默認值:/data/db在Linux和macOS上,\data\db在Windows上,這里,咱們一般放在實例部署的位置,而不是默認位置:mongod實例存儲其數據的目錄。該storage.dbPath設置僅適用於mongod。 indexBuildRetry: true journal: enabled: true # boolean類型。默認值:true在64位系統上,false在32位系統上。啟用或禁用持久性日志以確保數據文件保持有效和可恢復。此選項僅在您指定storage.dbPath設置時適用 。mongod默認情況下啟用日記功能。 commitIntervalMs: 100 # 數字類型。默認值:100或30。版本3.2中的新功能。mongod進程允許在日志操作之間的最長時間(以毫秒為單位)。值的范圍為1到500毫秒。較低的值會增加日志的持久性,但會犧牲磁盤性能。默認日記帳提交間隔為100毫秒。 wiredTiger: engineConfig: directoryForIndexes: true cacheSizeGB: 60 # float類型。WiredTiger將用於所有數據的內部緩存的最大大小。在版本3.4中更改:值的范圍可以從256MB到10TB,並且可以是浮點數。此外,默認值也已更改。 journalCompressor: "snappy" collectionConfig: blockCompressor: "snappy" indexConfig: prefixCompression: true #wiredTigerCollectionConfigString: lsm #wiredTigerIndexConfigString: lsm
給副本集創建keyfile讓集群成員之間通過認證:
創建keyFile文件: keyFile文件的作用: 集群之間的安全認證,增加安全認證機制KeyFile(開啟keyfile認證就默認開啟了auth認證了,為了保證后面可以登錄,我已創建了用戶) (1):openssl rand -base64 765 > /root/mongodb/keyfile 其中765是文件大小 /root/mongodb/keyfile : 文件存放路徑 (2):該key的權限必須是0600或0400 chmod 0600 /root/mongodb/keyfile 注意:創建keyFile前,需要先停掉副本集中所有主從節點的mongod服務(systemctl stop mongodb.service),然后再創建,否則有可能出現服務啟動不了的情況。 mongodb集群有自動切換主庫功能,如果先關主庫,主庫就切換到其它上面去了,這里預防主庫變更,從庫關閉后再關閉主庫 (3):將主節點中的keyfile文件拷貝到副本集其他從節點服務器中,路徑地址對應mongo.conf配置文件中的keyFile字段地址。並設置keyfile權限為0600
副本集成員配置:
glc:PRIMARY> rs.conf() { "_id" : "glc", "version" : 2, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "xxx:27076", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "yyy:27076", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "zzz:27076", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : true, "priority" : 0, "tags" : { }, "slaveDelay" : NumberLong(21600), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("5fd6e787187fc38ca7584ed4") } }
一、優先級配置:
在設置mongodb副本集時,Primary節點,second節點,仲裁節點,有可能資源配置(CPU或者內存)不均衡,所以要求某些節點不能成為Primary
我們知道mongodb的設置:
- 除了仲裁節點,其他每個節點都有個優先權,可以手動設置優先權來決定誰的成為primay的權重最大。
- 副本集中通過設置priority的值來決定優先權的大小,這個值的范圍是0--100,值越大,優先權越高。
- 默認的值是1,如果值是0,那么不能成為primay。
- 規划時直接設置,這個就略過了。
- 在線加入的節點配置:
配置過程:通過修改priority的值來實現,默認的優先級是1,取值范圍是:0-100,priority的值設的越大,就優先成為主。
注意:第2步members大括號里面的成員和_id是沒有關系的,而是rs.conf查出來節點的數值的順序;這些操作必須在Primary上進程。
- 我們通過設置不同的優先級來提高部分節點成為主節點的可能性,也可以讓某些節點不能成為主節點。復制集節點的 priority 參數的值決定了選舉中該節點的優先級。值越高,優先級越高。
- 在維護視窗時間內修改優先級。修改優先級會使主節點降職並觸發選舉。在選舉前,主節點將關閉所有已有連接。
- 我們可以通過修改復制集配置參數中 members 數組位置的優先級來修改對應機器的優先級。數組索引從 0 開始。不要將數組下標與數組 _id 混淆。
- MongoDB不能將當前的 primary 的優先級設置為 0 。為了防止現有的主節點再次成為主節點,我們需要先使用 rs.stepDown() 來將主節點降職。
舉例說明:特別要注意的是:members[下標],下標這個值始終從0開始算起,與members數組中每個元素的_id毫無關系,不要搞錯了!!!!!!!!!
cfg = rs.conf() cfg.members[0].priority = 0 cfg.members[1].priority = 0.5 cfg.members[2].priority = 1 cfg.members[3].priority = 2 rs.reconfig(cfg)
禁止從節點升為primary節點的可能:
cfg = rs.conf() cfg.members[2].priority = 0 rs.reconfig(cfg)
將某個指定節點升為主庫primary:也可以將不能作為主庫的實例先rs.remove(),切換之后再rs.add()也可以
cfg = rs.conf() cfg.members[0].priority = 1 cfg.members[1].priority = 1 cfg.members[2].priority = 5 rs.reconfig(cfg)
如上操作將2號節點提升為主庫primary,執行了rs.reconfig(cfg)后,將會立馬進行選舉:
二、配置隱藏節點:
cfg = rs.conf()
cfg.members[0].priority = 0 cfg.members[0].hidden = true rs.reconfig(cfg)
說明:
- 將優先級設置為最低值0的目的:防止被選舉為master節點。
- 將其配置為hihhen節點的目的:對應用程序不可見,即程序的讀寫流量都不會打到該節點上。
特別地,當業務開啟了讀寫分離,如果采取了通過普通同步數據的方式來新增一台mongod從庫的話,那么一定要記得在主庫執行了rs.add("hostname:port")后,
需要將該新增的實例配置為隱藏節點或延遲節點,不然業務會將流量打到該實例而報錯,直到數據完全同步了,便可改回來。
以下是新增實例后忘記設置為隱藏節點或延遲節點情況下業務的報錯信息:
10:16 2021-03-16 10:15:24,093|INFO |cluster-ClusterId{value='4023aa92897e9155d7e40602', description='null'}-xxx:28011|org.mongodb.driver.cluster|
|Exception in monitor thread while connecting to server xxx:28011 com.mongodb.MongoCommandException: Command failed with error 211 (KeyNotFound): 'Cache Reader No keys found for HMAC that is valid for time: { ts: Timestamp(1615860924, 2) } with id: 6888689310090919952'
on server xxx:28011. The full response is {"ok": 0.0, "errmsg": "Cache Reader No keys found for HMAC that is valid for time: { ts: Timestamp(1615860924, 2) }
with id: 6888689310090919952", "code": 211, "codeName": "KeyNotFound"} at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:175) at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:303) at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:259) at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83) at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:38) at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:180) at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:124) at java.lang.Thread.run(Thread.java:748)
三、配置延遲節點:
- 優先級必須設置為0,防止延時節點被選為主節點。
- 應該把延時節點設置為隱藏節點,這樣客戶端在做從服務器讀操作時,請求不會被分發到延時節點。
- 在發生選舉時,該節點可以投票。
- 延時節點通過延時從opLog同步數據來實現,因此延時時長的設置需要考慮兩個因素:不小於維護時間窗口。比opLog的容量要小一些,不然會不能同步而進入stale狀態。
舉例說明:
cfg = rs.conf()
cfg.members[0].priority = 0
cfg.members[0].hidden = true
cfg.members[0].slaveDelay = 3600
rs.reconfig(cfg)
如果刪除mongodb的數據目錄會報錯:
2021-02-02T12:04:43.736+0800 I STORAGE [initandlisten] exception in initAndListen: NonExistentPath: Data directory /home/work/mongodb/mongo_28042/data not found., terminating 2021-02-02T12:04:43.736+0800 I NETWORK [initandlisten] shutdown: going to close listening sockets... 2021-02-02T12:04:43.736+0800 I NETWORK [initandlisten] removing socket file: /tmp/mongodb-28042.sock 2021-02-02T12:04:43.736+0800 I CONTROL [initandlisten] now exiting 2021-02-02T12:04:43.736+0800 I CONTROL [initandlisten] shutting down with code:100
通過initial sync來直接新增一個mongdb副本集的成員:
ssd固態硬盤的情況下,每分鍾能備份8G數據;
更改指定副本集從庫的復制源:
先登錄指定的副本集從庫,然后更改復制源:
glc:SECONDARY> rs.syncFrom("xxx:28042"); { "syncFromRequested" : "xxx:28042", "prevSyncTarget" : "yyy:28042", "ok" : 1, "operationTime" : Timestamp(1612342134, 1), "$clusterTime" : { "clusterTime" : Timestamp(1612342134, 1), "signature" : { "hash" : BinData(0,"f7Bx8Jqa5QIfu0ZzOG9eBe3+KmU="), "keyId" : NumberLong("6919692836459773955") } } } glc:SECONDARY>
# 顯示將原來的yyy:28042同步源更改為xxx:28042同步源:
查看同步源信息:
glc:PRIMARY> rs.status().members [ { "_id" : 1, "name" : "xxx:28042", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1219104, "optime" : { "ts" : Timestamp(1612342939, 57), "t" : NumberLong(8) }, "optimeDate" : ISODate("2021-02-03T09:02:19Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "electionTime" : Timestamp(1612256361, 1), "electionDate" : ISODate("2021-02-02T08:59:21Z"), "configVersion" : 15, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 4, "name" : "xxx:28042", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1999, "optime" : { "ts" : Timestamp(1612342939, 57), "t" : NumberLong(8) }, "optimeDurable" : { "ts" : Timestamp(1612342939, 57), "t" : NumberLong(8) }, "optimeDate" : ISODate("2021-02-03T09:02:19Z"), "optimeDurableDate" : ISODate("2021-02-03T09:02:19Z"), "lastHeartbeat" : ISODate("2021-02-03T09:02:28.433Z"), "lastHeartbeatRecv" : ISODate("2021-02-03T09:02:29.351Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "xxx:28042", "syncSourceHost" : "xxx:28042", "syncSourceId" : 1, "infoMessage" : "", "configVersion" : 15 } ] glc:PRIMARY>
# "syncingTo" : "xxx:28042",
# "syncSourceHost" : "xxx:28042",
服務端配置寫入數據策略:
cfg = rs.conf() cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 } rs.reconfig(cfg)
客戶端配置寫入策略:
也可以通過客戶端來指定具體的策略,如下: 至少要寫入兩個節點,超時時間是 5s
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: 2, wtimeout: 5000 } }
)
###########################
