《萬億級數據庫MongoDB集羣性能數十倍提高優化實踐》核心17問詳細解答

《萬億級數據庫MongoDB集羣性能數十倍提高優化實踐》核心17問詳細解答

說明:

       爲了更好的理解背景,請提早閱讀oschina分享的《萬億級數據庫MongoDB集羣性能數十倍提高及機房多活容災實踐》一文。html

      本文是2020年深圳Qcon全球軟件開發大會《專題:現代數據架構》專場dbaplus專場:萬億級數據庫MongoDB集羣性能優化實踐、mongodb2020年終盛會分享後,得到一致好評。本文收集了會後衆多mongodb用戶提的比較頻繁的17個問題,並對每一個問題進行了詳細解答,一併整理到本文中。前端

分享內容回顧以下:node

  • MongoDB在OPPO互聯網推廣經驗分享-如何把一個淘汰邊緣的數據庫逐步變爲公司主流數據庫
  • 談談當前國內對MongoDB誤解(丟數據、不安全、難維護)?
  • MongoDB跨機房多活方案-實現成本、性能、一致性"三豐收"
  • MongoDB線程模型瓶頸及其優化方法
  • 並行遷移:MongoDB內核擴容遷移速率數倍/數十倍提高優化實踐
  • 百萬級高併發讀寫/千億級數據量MongoDB集羣性能數倍提高優化實踐
  • 萬億級數據量MongoDB集羣性能數十倍提高優化實踐
  • 磁盤80%節省-記某服務接口千億級數據遷移MongoDB,近百臺SSD服務器節省原理

關於做者

       前滴滴出行技術專家,現任OPPO文檔數據庫mongodb負責人,負責數萬億級數據量文檔數據庫mongodb內核研發、性能優化及運維工做,一直專一於分佈式緩存、高性能服務端、數據庫、中間件等相關研發。後續持續分享《MongoDB內核源碼設計、性能優化、最佳運維實踐》,Github帳號地址:https://github.com/y123456yzmysql

  1. 性能優化有推薦的分析和監控工具麼?

      mongodb經常使用性能分析主要以下:ios

1.1 mongodb自帶性能分析工具

   mongodb官方對外工具mongostatgit

    命令行使用方法(ip:port爲代理ip和端口):github

       mongostat  -h  ip:port  -u用戶名 -p密碼 --authenticationDatabase=admin --discoversql

      mongostat工具帶上--discover,能夠把全部分片節點信息一塊兒打印出來,直觀查看整個集羣全部節點實例級監控信息。mongostat統計信息中最核心的幾個影響性能的統計項:mongodb

  1. dirty:存儲引擎髒數據比例,默認該值爲5%的時候,wiredtiger存儲引擎自帶的evict現成開始選擇髒數據page淘汰到磁盤;若是該值達到20%,客戶端請求對應mongodb處理現成將會選擇髒數據page淘汰到磁盤,等page淘汰騰出內存空間後,纔會處理客戶端請求的DB訪問,因此若是閥值達到20%客戶端訪問將會變慢。
  2. used:存儲引擎cacheSize配置佔用百分比,若是配置cacheSize=10G,存儲引擎實際使用了7G,則used贊比爲70%。當該統計值達到80%,evict線程將會觸發選擇漲數據淘汰,若是這個佔比提升到95%,用戶請求線程將會觸發淘汰,客戶端請求將會變慢。
  3. qrw arw:等待隊列數,若是該值越大,說明會引發客戶端請求排隊處理。通常該值會再dirty佔比超過20%,used佔比太高超過95%,或者磁盤IO慢會出現。
  4. vsize res:虛擬內存和物理內存真實佔用,若是vsize太高,遠遠超過res,或者res太高,遠遠超過cachesize配置,則說明內存碎片,pageheap等問題,這時候能夠經過加速tcmalloc內存釋放速率來解決問題。
  • 慢日誌分析

    經過如下命令分析日誌文件數據庫

1)找出文件末尾1000000行中存在掃表的操做,不包含oplog,getMore

      tail  mongod.log  -n 1000000 | grep ms |grep COLLSCAN |grep -v "getMore" | grep -v "oplog.rs"

2)找出文件末尾1000000行中全部的慢日誌,不包含oplog,getMore

      tail mongodb.log -n 1000000 |grep ms | grep op_msg | grep find | grep -v "oplog.rs" |grep -v "getMore"

3.)找出文件末尾1000000行中執行時間1-10s的請求,不包含oplog,getMore

    tail mongodb.log -n 1000000 |grep ms | grep op_msg | grep find | grep -v "oplog.rs" |grep -v "getMore" | egrep [1-9][0-9][0-9][0-9]ms

4)currentOp正在執行的慢操做分析

      慢日誌只有當請求執行完畢纔會,若是一個表很大,一個查詢掃表,則整個執行過程可能須要數小時,可能還沒記錄慢日誌,則能夠經過以下命令獲取當前執行時間超過5s的全部請求,查詢請求,command請求:

    db.currentOp({"secs_running":{"$gt":5}})

    db.currentOp({"secs_running":{"$gt":1}, "op":"query"})

    db.currentOp({"secs_running":{"$gt":5}, "op":"command"})

   kill查詢時間超過5s的全部請求:

      db.currentOp().inprog.forEach(function(item){if(item.secs_running > 5 )db.killOp(item.opid)})

  • 節點存儲引擎監控信息

       db.serverStatus().wiredTiger能夠獲取mongod節點對應存儲引擎的各自詳細統計信息,裏面能夠完整獲取時延消耗在存儲引擎哪個環節。

       下面是空餘時間分析的wiredtiger源碼,分析不是很完整,後續等mongodb server層單機、複製集、分片等完整模塊化分析後,會回頭繼續分析。

       wiredtiger存儲引擎源碼詳細註釋分析

1.2 操做系統性能瓶頸分析

      系統層面性能分析工具主要有:top、iostat、pstak、ptress、perf、iotop、isof等,具體請參考對應工具說明。

1.3 開源mongodb詳細監控套記

    開源方案能夠參考如下組件:

      Grafana+Prometheus+node_exporter+mongodb_exporter

  • 服務端組件:
    Prometheus #服務端
    Grafana #前端展現
  • 客戶端組件:
    node_exporter
    mongodb_exporter

2. 會話加標籤是怎麼指定服務器?

     舉一個例子形象說明:咱們把用戶分爲三組,20 歲如下(junior),20 到 40 歲(middle)和 40 歲以上(senior),按照下面的幾條命令執行之後,咱們的數據會按照用戶年齡段拆分紅若干個 chunk,並分發到不一樣的 shard cluster 中。

      若是對下面的命令不熟悉,能夠查看 MongoDB 官方文檔關於 Shard Zone/Chunk 的解釋。

       sh.addShardTag('shard01', 'junior')

      sh.addShardTag('shard02', 'middle')

      sh.addShardTag('shard03', 'senior')

      sh.addTagRange('test.users', {'user.age': MinKey}, {'user.age':20}, 'junior')

      sh.addTagRange('test.users', {'user.age': 21}, {'user.age':40}, 'middle')

      sh.addTagRange('test.users', {'user.age': 41}, {'user.age': MaxKey}, 'senior')

      經過上面的6個命令給'test庫的user表加標籤,20如下對應標籤爲'junior',21-40對應標籤爲'middle',41以上對應標籤爲'senior'。同時把'junior'標籤分配給'shard01',也就是0-20歲的user會所有寫到'shard01',21-40歲的user會所有寫到'shard01',41歲以上的user會所有寫到'shard01'。

      這樣就能夠解決跨機房寫的問題,只要對應分片主節點在對應機房便可。

3. 髒數據比例多少算高?

      默認20%算高,若是髒數據比例持續性超過20%,能夠試着提升wiredtiger存儲引擎後臺淘汰線程數:

  db.adminCommand( { setParameter : 1, "wiredTigerEngineRuntimeConfig" : "cache_size=35GB, eviction=(threads_min=4, threads_max=12)"})

4. 寫分開,會有時延嗎,是否是有一致性問題?

      一致性默認徹底由mongodb複製集自帶的主從同步機制來保證最終一致性,不存在雙向同步兩集羣的一致性問題。

      若是要實現複製集中主從節點的強一致性,能夠經過客戶端配置writeconcern策略來解決。

5. 好比想定位詳細的慢查詢呢?

      和問題1雷同,能夠經過分析currentop、日誌文件或者system.profile慢日誌表來獲取詳細的慢日誌信息。建議平臺化收集慢日誌,這樣界面展現分析更加直觀。

6. 如何快速定位Mongodb的問題發生在集羣中的哪些節點?  在啓用讀寫分離的狀況下?

      主要經過以下幾個步驟來分析:

  • db.serverStatus().opLatencies監控mongod實例時延
  • 若是由運維研發能力,能夠本身收集時延展現,若是沒有。則能夠藉助開源工具系統實現,參考《1.3 開源mongodb詳細監控套記
  • 充分利用mongostat監控集羣全部節點實時髒數據、隊列、內存信息
  • 參考《1.1 mongodb自帶性能分析工具》
  • 慢日誌分析 參考《好比想定位詳細的慢查詢呢?》

7. 楊老師,就您經驗來說,您以爲如何保證MongoDB 的安全性呢?

      安全性方面主要由如下幾方面保證:

  • 帳號鑑權認證,一個庫一個帳號
  • readWrite權限去除刪庫、刪表等危險操做權限
  • 不一樣業務不混用同一個集羣
  • 啓用黑白名單功能
  • 我司mongodb內核增長審計、流量控制、危險操做控制等功能(注:部分功能是mongodb企業級功能,須要付費,可使用percona mongodb版本)
  • 數據按期備份,我司mongodb內核增長有熱備功能。

      注意:若是數據量很大,建議不要使用mongodump備份,mongodump備份會很慢,同時經過mongorestore恢復也是一條數據一條數據恢復,一樣很慢。若是有內核研發能力,能夠增長熱備功能。若是沒有內核研發能力,能夠經過以下步驟備份:1. 隱藏節點;2. 鎖庫;3. 拷貝數據文件。或者採用percona mongodb版原本備份。

8. mysql和mongodb雙寫的話怎麼保證事務呢

      mysql我不是很瞭解,mongodb不推薦搭兩集羣雙向同步來備份,直接利用mongodb原生的複製集功能來完成多活容災,成本、性能、一致性均可以獲得保證。即便是4.2分佈式事務功能也能夠直接利用mongodb自身的機制來保證,具體方案參考我在Qcon全球軟件開發大會的分享:

     萬億級數據庫MongoDB集羣性能優化及機房多活容災實踐

9. hashnum 的方式來說數組中的方式來拆分紅多個表? 沒太明白

      分享的案例2:萬億級數據量mongodb集羣性能數倍提高優化實踐,不是拆分數據到多個表,而是把一條數據(該數據保護一個數組,數組中包含數百萬個子文檔)經過hash的方式散列爲多條數據。也就是以前數百萬個子文檔歸屬於一條數據,如今把他拆分爲歸屬到多條數據。

      經過這樣合理的數據合併和拆分,最終平衡磁盤IO,實現讀和寫達到一種平衡態,既能知足業務讀需求,同時也能知足業務寫需求。

10. 對分片鍵設計要求高嗎?

      分片集羣片建選擇很是重要,對分片模式集羣性能起着核心相當重要的做用,分片集羣片建選擇遵循如下幾個原則:

11. 首先須要考慮集羣部署是否須要分片?

      只有如下狀況才須要分片功能:1. 數據量太大,一個分片撐不住;2. 寫流量太大,寫只能走主節點,一個主節點撐不住,須要擴分片分擔寫流量。

12. 片建選擇原則?

      片建選擇原則以下: 1. 保證數據儘可能離散;2. 儘可能保證更新和查詢到同一個分片(若是同一次更新或者查詢到多個分片,只要任何一個分片慢,該操做都會慢;同時部分查詢會進一步加重代理聚合負擔)。

      此外,若是查詢注意是範圍查詢,建議選擇範圍分片,這樣有利於範圍數據集中到同一個分片。

13. 大表分片後,寫表仍是會跨機房嗎?

      機房多活打標籤方式解決跨機房寫問題,一樣能夠對對應tag表啓用分片功能,保證數據到指定的多個分片,每一個分片主節點在指定機房,能夠解決跨機房問題。詳情參考:《會話加標籤是怎麼指定服務器?》

14. 老師您好,想請問下:MongoDB適合作商城app數據庫嗎?通常在哪些場景使用呢?謝謝!

      我的以爲徹底能夠知足要求,同時還有利於業務的快速迭代開發。mongodb自然的模式自由(加字段方便)、高可用、分佈式擴縮容、機房多活容災機制,能夠快速推動業務迭代開發。以個人經驗,至少90%以上使用mysql的場景,mongodb一樣能夠知足要求。mongodb惟一缺點多是生態沒mysql健全,研究mongodb的人至關少。

15. 老師能講講大家容量預警是怎麼作的嗎?

     容量水位咱們分爲如下幾種:

  • 磁盤容量限制

      當一個分片中磁盤使用率超過80%,咱們開始擴容增長分片。

  • 流量超過閥值

      讀寫流量閥值水位以下:1. 若是是分片的寫流量持續性超過3.5W/s(ssd服務器)則擴容分片;2. 若是是讀流量單節點持續性超過4W/s(ssd服務器,全部讀走磁盤IO),則擴容從節點來解決讀流量瓶頸,注意須要配置讀寫分離。

  • CPU閥值

      咱們全部實例容器部署,實例若是CPU使用率持續性超過80%,考慮增長容器CPU。

16. 數據一致性在遷移過程當中同步大家是怎麼保證的呢

      若是經過mongoshake等工具遷移集羣,須要提早關閉blance功能,不然沒法解決一致性問題。

      咱們線上集羣只有把數據從集羣遷移到另外一個集羣的時候纔會使用mongoshake,咱們機房多活不是多個集羣雙寫方式,而是同一個集羣,經過夫直接的主從同步拉取oplog機制實現一致性,因此不存在一致性問題。能夠參考   萬億級數據庫MongoDB集羣性能優化及機房多活容災實踐

17. 咱們數據體量不太大,主要是雜,這種環境想作好數據治理,老師你建議把重點放在哪些方面?而後有沒有一些比較常見的坑?

      數據量不大,比較雜的場景,通常集羣搞一個複製集便可知足要求,無需分片模式部署。

      我猜想大家的比較雜多是利用mongodb的模式自由,形成每條數據的字段各不相同,數據長度大小各不一致。建議在使用模式自由這一功能的時候,必定不要濫用亂用,在使用時代碼邏輯須要簡單控制。我重節線上遇到的對模式自由的濫用亂用引發的集羣問題:

  • 同一個表數據字段各不相同,建議同一個表全部數據的字段保持一致,即便新數據增長字段也須要在老數據中增長該字段,保持字段一致。
  • 同一個表的數據的字段控制在50個KV之內,這樣對應更新、查詢等性能分析有利,減小磁盤IO消耗。
  • 若是數據字段過多,查詢的時候不要返回全部字段,只獲取對本次查詢有用的字段,減小忘了IO開銷。
  • 數組別亂用,數組中的文檔保持格式統一。
  • 數組中的子文檔若是須要查詢指定字段,必定記得對數組中嵌套的字段添加子索引。
  • 數組字段中的文檔必定要控制在必定範圍,避免該數組過大,數組過大有遍歷、磁盤IO太高等問題。
  • 嵌套子文檔層數不宜過多。
  • ......

18. 在有多大數據量?

      公司內部mongodb規模已經很大了,整體超過數萬億級。

19. 大家對這個大數據平臺有多少開發人員?

      咱們研發+運維人員不多,mongodb擁有自然的高可用、分佈式擴縮容、機房多活容災等功能,保證了能夠用不多的人力來知足公司快速增加的業務需求。

20. 最後:我的2021年規劃(爲mongodb國內推廣及影響力提高作點事)

    國內真正擁有企業級分佈式數據庫自研能力的公司主要集中在阿里、騰訊頭部幾家,即便二三線互聯網公司也沒法作到真正意義上的企業級分佈式數據庫研發能力,擁抱開源是一個明智的選擇。

    mongodb擁有自然的高可用、分佈式擴縮容、機房多活容災、完善的負載均衡及一致性策略等功能,能夠作到最少人力成本知足業務快速增加的需求,我的認爲mongodb絕對是頭部公司之外企業會分佈式數據庫需求的一個值得信賴的選擇。    

正如在Qcon專題:現代數據架構dbaplus、mongodb中文社區所分享,當前mongodb國內影響力待提高最大的問題在於國內真正研究mongodb內核實現細節的人太少,形成不少複雜問題沒法解決,最終這些的問題演變爲「mongodb問題」。

在此,後續持續性分享業務接入過程當中的典型踩坑,同時持續性模塊化分析mongodb內核設計原理,爲mongodb國內影響力提高作點實事,具體計劃以下(詳見:盤點 2020 | 我要爲分佈式數據庫 mongodb 在國內影響力提高及推廣作點事):

20.1 短時間目標

短時間目標主要是把我司數萬億級數據量mongodb業務接入過程所遇到的核心踩坑過程、性能優化案例、機房多活案例等分享到社區,避免國內其餘mongodb用戶踩一樣的坑,這些核心踩坑點也是分享中相關聽衆最關心的點,主要以下:

  1. 300條數據操做引起的血案-記一次線上300條數據變動操做引發某10億級mongodb核心集羣不可用故障。
  2. 主節點持續性OOM-記一次業務排序操做不合理使用引發的核心mongodb集羣故障。
  3. 千億級/萬億級集羣最優索引添加方法-記一次數十億級核心集羣后臺索引添加引發的集羣抖動及快速恢復過程。
  4. 連接數耗光如何快速恢復集羣-記一次百億級核心集羣連接數耗光的快速自救過程。
  5. mongodb機房多活方案-實現成本、性能、一致性"三豐收"。
  6. mongodb線程模型瓶頸及其優化方法。
  7. 並行遷移-集羣擴容速率N倍提高優化實踐。
  8. 千億級核心元數據mongodb集羣性能數倍提高優化實踐。
  9. 萬億級數據量mongodb集羣性能數十倍提高優化實踐。
  10. 成本節省-記某服務千億級數據遷移mongodb,百臺SSD服務器節省優化實踐。
  11. 如何快速完成數千億數據從SSD高IO服務器遷移到SATA盤低IO服務器?
  12. 。。。。。。

指望完成時間:2021年4-5月

20.2 中期目標

完成Qcon、知乎、github、itpub中專欄《mongodb內核源碼實現、性能調優、最佳運維實踐系列》中核心文章的分享。

沒有什麼比源碼更有說明力,完成github中mongodb內核源碼中文註釋分析:

mongodb內核源碼中文註釋分析

    指望完成時間:2021年11月

20.3 年度目標

     指望經過對mongodb核心內核核心技術內幕的分享整理,完成以下系列文章或者書籍的編寫整理:

  1. 《分佈式mongodb數據庫內核設計與實現》
  2. 《分佈式mongodb數據庫最佳運維實踐》

   指望完成時間:2021年12月底

20.4 公司內部目標

1.  公司自研mongodb內核深度優化,最大化解決高併發大流量、大數據量狀況下擴容過程的抖動問題。

2.  快速掌握mongodb-4.2分佈式事務實現原理,開始大力推廣分佈式事務功能。

3.  持續分享內部推廣過程當中的集羣踩坑、性能優化等案例到社區。

4.  其餘

    指望完成時間:整年

相關文章
相關標籤/搜索