300條mongodb資料變更引發的血案-記某十億級核心mongodb叢集部分請求不可用故障踩坑記
線上某核心mongodb 叢集資料量不大,單表資料量十億級,但是該叢集比較核心,影響公司收入流水。本文通過分享本次踩坑來分享整個故障經過,該故障為一次經典的 mongodb 分片 sharding 叢集踩坑故障,包括變更通知不到位、部署架構不到位、變更考慮不仔細等。
1. 問題背景
某核心mongodb 歷史叢集 ( 入職前就有的一個叢集 ) ,在對現在所有 mongodb 叢集進行風險梳理過程中,發現該叢集存在一些潛在的叢集抖動風險,該叢集架構及流量時延曲線如下:
如上圖所示,該分片叢集由3 個分片組成,叢集讀寫流量很低,峰值 QPS 約 4-6W/s ,平均時延 1ms ,每個分片採用 mongodb 複製集架構實現高可用。通過巡檢發現該叢集存在如下幾個問題:
l 該叢集只包含兩個使用者庫,userbucket 庫和 feeds_content 庫,兩個庫中只有 feeds_xxxxxxx.collection1 啟用了分片功能;第一個 userbucket 庫儲存叢集路由資訊,第二個 feeds_xxxxxxx 庫儲存約十億資料資訊;
l 由於該叢集主要是讀多寫少叢集,讀流量都是讀取feeds_xxxxxxx 庫中的資料,並且客戶端做了讀寫分離,所以幾乎大部分讀流量都在分片 1 。分片 2 和分片 3 只有少量資料。
庫表資訊如下表所示:
庫名 |
表名 |
功能說明 |
userbucket |
whitexxx/expxxx |
使用者路由資訊表,約 300 條資料。使用者訪問 feeds_xxxxxxx 庫前必須先獲取該表得使用者路由資料 |
feeds_xxxxxxx |
feeds_xxx_pool |
近億資料,未啟用分片 |
hardware_xxx_cost |
未啟用分片,少量資料 | |
news_xxx_profile |
數億資料,未啟用分片 | |
resource_xxx_info |
數千萬資料,啟用分片 | |
resource_xxx_info |
未啟用分片,數億資料 | |
resource_xxx_info |
未啟用分片,數億資料 |
上面的描述可以總結為下圖:
從上圖可以看出,分片2 和分片 3 幾乎沒起到任何作用;由於分片 3 有兩個節點為低 IO 的 sata 盤,可能影響 userbucket 庫的讀寫,因此考慮直接 removeShard 從叢集中剔除分片 3 和分片 2 。
2. 操作過程
由於分片3 為低 IO 伺服器,有潛在抖動叢集抖動分享;同時分片 2 和分片 3 幾乎都是浪費的分片,因此打散直接通過如下 removeshad 命令刪除分片 3 和分片 2 資訊,騰出無用伺服器資源,如下圖所示:
l 步驟1 :登陸任一一個代理,假設是代理 mongos1 。
l 步驟2 :由於分片 3( 也就是 shard_8D5370B4 分片 ) 為 userbucket 庫的主分片,因此報錯了,提示 "you need to drop or movePrimary these databases" ,意思是我們需要提前把該庫的主分片資訊遷移到其他分片。
l 步驟3 :通過 movePrimary 命令把 userbucket 庫的主分片從分片 3 遷移到分片 1 。
l 登陸監控列表中的其他兩個代理mongos2 、 mongos3 ,通過 db.adminCommand({"flushRouterConfig":1}) 強制重新整理路由資訊。
注意事項:由於 movePrimary 過程,其他代理不會感知到該庫的主分片變化,因此需要強制重新整理路由資訊或者重啟其他節點的 mongos ,參考如下:
3. 使用者反饋大部分請求業務請求不可用
對含有300 條資料的 userbucket 庫變更後,當我還在若無其事的處理其他叢集效能調優的時候,使用者突然很急的電話我反饋該核心叢集整個訪問不可用(注意:是整個 10 億資料的叢集不可用)。
收到電話後很突然,和業務人員詳細對接後可以基本上確定是因為這300 條資料變更引起。業務獲取這 300 條資料的時候,部分請求獲取成功,部分請求獲取失敗,說明肯定和 movePrimary 有關係。
於是,除了對監控列表中的所有代理做flushRouterConfig 強制路由重新整理外,還重啟了所有的代理,但是業務反饋,還是有部分請求獲取不到資料。比較棘手,我自己通過所有的 mongos 代理檢視 userbucket 庫下面的 300 條資料,完全可以獲取到資料。
於是懷疑是不是還有未重新整理路由的mongos 代理,於是登陸任一 mongos 代理獲取 config.mongos 表,檢視結果如下:
上面的config.mongos 表記錄了該叢集所有的代理資訊,同時記錄了這些代理和叢集最後一次 ping 通訊的詳細時間資訊。很明顯,該表中記錄的代理原不止叢集監控列表中的代理個數,比監控列表中的個數要多。
最終,把config.mongos 表中羅列的當前線上的所有代理強制通過 flushRouterConfig 重新整理路由後,業務恢復。
4. 問題總結
通過前面的分析可以得出,由於早期叢集監控中漏掉了部分代理,造成這部分代理對應的userbucket 路由資訊是 movePrimary 前的路由資訊,也就是指向了錯誤的分片,因此出現了路由不到資料的情況,如下圖所示:
l 為何使用者userbucket 庫對應表中資料有的成功有的失敗?
因為部分代理在moveprimary 後,沒有強制重新整理該表路由資訊,造成部分代理路由獲取資料的時候路由錯誤。
l 為何該300 條資料部分路由資訊錯誤會造成整個 10 億叢集部分訪問不可用?
和業務實現邏輯有關係,因為業務在獲取這10 億條資料前首先需要獲取業務的路由資訊,剛好業務路由資訊存在了 userbucket 庫對應表中,業務在獲取資料前必須要獲取到業務的路由資訊資料,如果 userbucket 資料獲取不到,使用者就無法確定指向 feeds_xxxxxxx 資料 。
l 為何會遺漏部分代理重啟或者強制路由重新整理?
歷史原因,造成部分代理業務程式碼有配置,但是服務端叢集監控後設資料遺漏了,也就是服務端叢集監控漏掉了部分代理,這部分代理沒有監控起來。也有可能是mongos 代理擴容,但是叢集監控列表中沒有加入後設資料。
l movePrimary 操作最安全的操作方法?
官方建議movePrimary 操作成功後需要強制路由重新整理或者重啟 mongos ,但是 movePrimary 操作成功和 mongos 重啟這個過程中有個中間狀態,如果中間狀態業務讀或者些該遷移的庫下面的表,還是可能路由錯誤。因此,最佳安全的 moveprimary 可以通過如下兩個方法操作:
法一: shutdown 所有代理,只留下一個代理,等該代理 moveprimary 成功後在重啟其他 mongos 代理。切記別遺漏代理,出現本文踩坑類似情況,提前檢查 config.mongos 表。
法二: 對主分片在該需要removeShard 的分片的庫中的所有表啟用分片功能,啟用分片功能後會有 chunk 資訊, mongodb 會自動遷移該分片的 chunk 到其他分片,整個過程可以保證路由資訊一致。
5.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69984922/viewspace-2771729/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 記某百億級mongodb叢集資料過期效能優化實踐MongoDB優化
- 記某百億級mongodb叢集資料過期效能最佳化實踐MongoDB
- Mongodb特定場景效能數十倍提升優化實踐(記一次mongodb核心叢集雪崩故障)MongoDB優化
- Mongodb特定場景效能數十倍提升最佳化實踐(記一次mongodb核心叢集雪崩故障)MongoDB
- mongodb叢集節點故障的切換方法MongoDB
- 記十億級Es資料遷移mongodb成本節省及效能優化實踐MongoDB優化
- MongoDB叢集同步MongoDB
- 搭建MongoDB分片叢集MongoDB
- MongoDB 分片叢集搭建MongoDB
- Docker 搭建叢集 MongoDBDockerMongoDB
- MongoDB高可用叢集搭建MongoDB
- mongodb 分片叢集設定MongoDB
- MongoDB分片叢集常用操作MongoDB
- Qcon/dbaplus/mongodb社群分享-萬億級資料庫MongoDB叢集效能數十倍提升最佳化實踐MongoDB資料庫
- 大資料叢集核心引數調優大資料
- mongodb 分片叢集建立分片集合MongoDB
- 高可用mongodb叢集(分片+副本)MongoDB
- MongoDB Sharding(二) -- 搭建分片叢集MongoDB
- 分散式文件儲存資料庫之MongoDB分片叢集分散式資料庫MongoDB
- MongoDB 記錄MongoDB
- 專案中請求第三方介面踩坑記錄
- 基於 Docker 的 MongoDB 主從叢集DockerMongoDB
- MongoDB中的分散式叢集架構MongoDB分散式架構
- mongodb叢集shard_replica的搭建方法MongoDB
- ZooKeeper-3.4.6叢集選舉Bug踩坑與恢復記錄
- Kafka服務不可用(當機)問題踩坑記Kafka
- MongoDB的聚合筆記MongoDB筆記
- OPPO萬億級資料庫MongoDB叢集效能數十倍提升優化實踐資料庫MongoDB優化
- 寫入請求轉換為一條SQL insert 語句發給後設資料叢集SQL
- SpringBoot踩坑日記-一個非空校驗引發的bugSpring Boot
- docker 下部署mongodb Replica Set 叢集DockerMongoDB
- Mongodb分散式叢集副本集+分片MongoDB分散式
- 研究人員發現可公開訪問的包含1100萬條記錄的MongoDB資料庫MongoDB資料庫
- 記一次Content-Length引發的血案
- mongodb索引--1億條記錄的查詢從55.7秒到毫秒級別MongoDB索引
- 《Qcon分享-萬億級資料庫 MongoDB 叢集效能數十倍提升優化實踐》核心17問詳細解答資料庫MongoDB優化
- 記一次Kafka叢集的故障恢復Kafka
- 【MongoDB學習筆記】MongoDB 快速入門MongoDB筆記