前段時間維護的一個事業羣的其中一條業務線的開發找到運維,提出來了一個MongoDB的優化問題,那段時間MongoDB正在從op管理移交給db進行維護,整個部門都對MongoDB的運維經驗缺少,MongoDB的優化更是一個未知的挑戰。當op找到我,核心系統的公共服務平臺用來進行短信服務的MongoDB集羣想進行一次優化,我當仁不能讓的承擔了這項我都以爲可能搞不定的任務。mysql
開發找到我提出了兩點兒問題,並尋求運維團隊解決這個問題,不過最終在個人理性的思考和他感性的思惟碰撞下,最終我仍是以勝利者的姿態勝出。我成功說服了他,並解答了他一些疑問,獲得了滿意的答覆後再也沒找我了。固然這裏確定不會就憑几句話,任你理論再怎麼豐富,態度如何曖昧,不拿點兒真實數據,作點兒什麼,怎麼能說服經驗豐富的開發認定的事兒。溝通了大半天,佔據了我白天的工做時間,不過他提出來的問題仍是很值得討論。sql
根據開發的邏輯,是想橫向擴充secondary節點,把其餘要求不高的業務放到secondary節點上,減輕primary節點的壓力,達到部分讀寫分離,使得主要業務優先保障。我以爲這個出發點是好的,但並無就此做出迴應,其一是他沒有認識到這個他認爲的有延遲並非數據庫集羣的問題(這裏不詳細講述排查的過程,下一篇文章會講些MongoDB的寫入與業務邏輯),其二是咱們確實缺少有效的資源硬件去進行擴充節點。mongodb
不一樣的業務場景應用不一樣的架構策略,擴充secondary節點有時候不能解決問題,尤爲是那些實時性很高的業務,但有時候擴充secondary節點確實有效,好比硬件升級後須要作的服務遷移,須要在線擴充secondary節點來知足業務須要的更高的硬件要求。數據庫
MongoDB的secondary節點的擴充,我總結起來有兩種方式:一、rs.add()直接擴充 二、一致性備份後進行擴充(我的叫法)json
一、rs.add("HOST_NAME:PORT")vim
具體的實現方式是登錄擴充節點的機器,編輯好配置文件,並創建相應的目錄和權限,啓動MongoDB實例就能夠了。網絡
須要注意的一點兒是這種擴充方式要保證同步源的數據量級,即保證在同步完數據前MongoDB的oplog不會被覆蓋,這點兒相似與MySQL的redo log日誌,若是被覆蓋那麼同步的數據出現不一致,致使同步失敗。架構
須要注意的另外一點是同步數據的過程當中,當集羣數據達到必定量級時,同步數據的大小很大就會對網絡形成必定的壓力,可能對業務的核心交換機形成影響,所以須要用TC工具對同步流量作限速處理。這個限速須要考慮同步源可能不會是primary,也多是一樣角色的secondary節點,令外限速同步勢必會增大同步時間,這個會增大oplog被覆蓋的機率,具體限速值仍是要通過計算才能把握好。app
二、一致性快照快速添加secondary節點(自我命名,歡迎各位交流)運維
a)primary節點上進行一致性快照備份
b)secondary節點上進行一致性快照恢復,僅僅對數據部分進行恢復,暫時不要對oplog進行恢復
c)初始化oplog.rs集合,並恢復oplog記錄
d)初始化local數據庫的其餘兩個集合db.replset.election,db.system.replset
e)修改數據庫配置並重啓數據庫(這一步操做前實例不開啓認證模式、複製集的配置),rs.add("HOST_NAME:PORT")將secondary添加進集羣並觀察同步狀態、校驗數據的完整和一致性
實踐的詳細實踐過程以下(僅供參考交流,生產環境慎用):
一、primary上進行一致性快照備份
1 #primary節點或者其餘secondary節點備份數據 2 [root@172-16-3-190 mongodb]# /opt/app/mongodb/bin/mongodump -uroot -ppwd4mysql --authenticationDatabase=admin --port=27017 --oplog -o /tmp/dump_mongo/ 3 2018-08-20T15:42:47.028+0800 writing admin.system.users to 4 2018-08-20T15:42:47.030+0800 done dumping admin.system.users (1 document) 5 2018-08-20T15:42:47.030+0800 writing admin.system.version to 6 2018-08-20T15:42:47.031+0800 done dumping admin.system.version (2 documents) 7 2018-08-20T15:42:47.032+0800 writing super_hero.user_address to 8 2018-08-20T15:42:47.032+0800 writing super_hero.user_info to 9 2018-08-20T15:42:47.033+0800 done dumping super_hero.user_address (1 document) 10 2018-08-20T15:42:47.033+0800 done dumping super_hero.user_info (1 document) 11 2018-08-20T15:42:47.034+0800 writing captured oplog to 12 2018-08-20T15:42:47.036+0800 dumped 1 oplog entry 13 14 #查看備份的文件 15 [root@172-16-3-190 mongodb]# ls -lh /tmp/dump_mongo/ 16 total 12K 17 drwxr-xr-x 2 root root 4.0K Aug 20 15:42 admin 18 -rw-r--r-- 1 root root 110 Aug 20 15:42 oplog.bson 19 drwxr-xr-x 2 root root 4.0K Aug 20 15:42 super_hero 20 21 #傳遞備份到準備添加爲secondary的節點上 22 [root@172-16-3-190 tmp]# scp -r -P22222 /tmp/dump_mongo/ liyingxiao@172.16.3.189:/tmp
二、secondary節點一致性快照恢復
1 #auth=true 2 #replSet = repl_mongo 3 #clusterAuthMode=keyFile 4 #keyFile=/opt/app/mongodb/keyfile/mongodb.key 5 6 ##恢復數據 7 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongorestore --oplogReplay --port=27017 /tmp/dump_mongo/ 8 2018-08-20T15:56:32.161+0800 preparing collections to restore from 9 2018-08-20T15:56:32.193+0800 reading metadata for super_hero.user_info from /tmp/dump_mongo/super_hero/user_info.metadata.json 10 2018-08-20T15:56:32.194+0800 reading metadata for super_hero.user_address from /tmp/dump_mongo/super_hero/user_address.metadata.json 11 2018-08-20T15:56:32.222+0800 restoring super_hero.user_address from /tmp/dump_mongo/super_hero/user_address.bson 12 2018-08-20T15:56:32.300+0800 restoring super_hero.user_info from /tmp/dump_mongo/super_hero/user_info.bson 13 2018-08-20T15:56:32.867+0800 no indexes to restore 14 2018-08-20T15:56:32.867+0800 finished restoring super_hero.user_address (1 document) 15 2018-08-20T15:56:32.881+0800 no indexes to restore 16 2018-08-20T15:56:32.881+0800 finished restoring super_hero.user_info (1 document) 17 2018-08-20T15:56:32.881+0800 restoring users from /tmp/dump_mongo/admin/system.users.bson 18 2018-08-20T15:56:32.993+0800 replaying oplog 19 2018-08-20T15:56:32.997+0800 done
三、初始化oplog.rs集合,並恢復oplog記錄
建立oplog.rs集合並初始化大小
1 use local 2 db.createCollection("oplog.rs",{"capped":true,"size":100000000})
恢復一致性備份的oplog.rs集合的數據到secondary節點
1 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongorestore -d local -c oplog.rs --port=27017 /tmp/dump_mongo/oplog.bson 2 2018-08-20T16:12:49.848+0800 checking for collection data in /tmp/dump_mongo/oplog.bson 3 2018-08-20T16:12:49.852+0800 restoring local.oplog.rs from /tmp/dump_mongo/oplog.bson 4 2018-08-20T16:12:49.925+0800 no indexes to restore 5 2018-08-20T16:12:49.925+0800 finished restoring local.oplog.rs (1 document) 6 2018-08-20T16:12:49.925+0800 done
四、初始化db.replset.election,db.system.replset集合,其中replset.election須要查詢主節點數據並將這些數據存儲到secondary節點,或者兩個結合自行save到secondary節點。另集合system.replset加入複製集後可自動識別primary節點內容(這裏我採起自行同步數據)
1 #primary節點 2 repl_mongo:PRIMARY> db.replset.election.find() 3 { "_id" : ObjectId("5b7a6ee5de7a24b82a686139"), "term" : NumberLong(1), "candidateIndex" : NumberLong(0) } 4 #secondary節點 5 db.replset.election.save({ "_id" : ObjectId("5b7a6ee5de7a24b82a686139"), "term" : NumberLong(1), "candidateIndex" : NumberLong(0) })
五、修改數據庫配置並重啓,添加secondary節點到複製集羣中
#auth=true #replSet = repl_mongo #clusterAuthMode=keyFile #keyFile=/opt/app/mongodb/keyfile/mongodb.key [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongod --shutdown -f /opt/app/mongodb/mongo.conf killing process with pid: 5331 [root@172-16-3-189 we_ops_admin]# vim /opt/app/mongodb/mongo.conf #註釋去掉並重啓 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongod -f /opt/app/mongodb/mongo.conf about to fork child process, waiting until server is ready for connections. forked process: 5722 child process started successfully, parent exiting #添加secondary節點 repl_mongo:PRIMARY> rs.add({"_id":1,"host":"172.16.3.189:27017"}) { "ok" : 1, "operationTime" : Timestamp(1534752953, 1), "$clusterTime" : { "clusterTime" : Timestamp(1534752953, 1), "signature" : { "hash" : BinData(0,"Tt9nzhoVYdUtGFZnc1Kg1exl0Hc="), "keyId" : NumberLong("6591702943026642945") } } }
六、登陸添加的secondary節點,驗證複製集狀態,數據完整和一致性。
1 [root@172-16-3-189 we_ops_admin]# /opt/app/mongodb/bin/mongo -uroot -ppwd4mysql --authenticationDatabase=admin --port=27017
重點介紹第二種省時省心但費力費操做的添加secondary節點的方法,實踐過程當中數據庫實例前期去掉認證和複製集參數,是方便咱們下面的一些須要用戶權限的操做,避免創建管理員帳號,後續加入集羣后自行同步了primary節點的帳號。重啓後登陸secondary節點驗證服務的可用性和數據一致性時,使用集羣的管理帳號進入,不然會報認證的錯誤。
總結如上兩種擴充方式,對於方式1的擴充簡單省事,須要保證oplog不被覆蓋和評估同步流量的影響問題,是咱們一般進行橫向複製集添加secondary節點的方法。對於第二種方式,操做繁瑣但不用擔憂oplog被覆蓋,且操做期間不會過多擔心網絡流量的問題,僅僅考慮網絡傳輸的流量影響。第一種方式操做時間週期長,不可控的影響範圍大費時費精力,第二種方式操做時間短,操做的步驟多,容易出現其餘問題。