萬億級數據庫MongoDB集羣性能數十倍提高及機房多活容災實踐

說明:

       本文是2020年深圳Qcon全球軟件開發大會《專題:現代數據架構》專場dbaplus專場:萬億級數據庫MongoDB集羣性能優化實踐、mongodb2020年終盛會分享,分享內容以下(體驗萬億級mongodb服務層、存儲引擎、高併發線程模型、異地多活容災等實現細節):html

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

關於做者

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

分享目錄

  • 推廣經驗分享
  • 機房多活實現
  • 性能優化案例
  • 成本優化案例
  • 其餘

分享主題一:如何把mongodb從淘汰邊緣變爲公司主流數據庫?

背景:git

  • 入職前多個大數據量業務使用mongodb,使用中常常超時抖動
  • 多個核心業務忍受不了抖動的痛苦,準備遷移回mysql。
  • mongodb口碑差,新業務想用不敢用。
  • 入職1個月,業務遷移mongodb到公司其餘數據庫,mongodb總集羣數減小15%

我作了啥?github

  • 從服務層優化、存儲引擎優化、部署方式優化等方面入手,逐一解決抖業務抖動問題
  • 總結各個集羣抖動緣由及優化方法,公司內部分享。
  • 收集公司全部mongodb集羣對應用戶,成立mongodb用戶羣

入職2月後,mongodb公司內部狀態:算法

  • 以前準備遷移到mysql的幾個核心業務繼續使用mongodb
  • 對應業務負責人開始考慮把其餘大數據量集羣遷移到mongodb
  • 愈來愈多的未使用過mongodb的部門開始使用mongodb

入職1年後,mongodb相關數據增加:sql

  • 總集羣數增加比例:> 700%
  • 總數據量增加比例:> 2000%
  • 讀寫流量增加比例:> 550%
  • mongodb用戶羣用戶數增加比例:> 800%

總結:mongodb

  • mongodb贏得用戶信任緣由總結:口碑

分享主題二:當前國內對mongodb誤解(丟數據、不安全、難維護)?

  1. 業務接入過程當中常常諮詢的幾個問題:
  • 誤解一. 丟數據
  • 誤解二. 不安全,網上一堆說mongodb被黑客攻擊,截圖一堆新聞
  • 誤解三. DBA吐槽mongodb太難維護

誤解緣由:數據庫

  • mongodb自己很優秀,可是不少DBA和相應開發把控不住
  • 國內系統性分析mongodb內核實現原理相關資料欠缺
  • 網絡社會以訛傳訛,DBA或者相關開發自身把控不住演變爲mongodb的鍋

分享主題三mongodb機房多活方案-實現成本、性能、一致性"三豐收"

傳統社區mongodb雙向同步方案(放棄該方案)

放棄該方案緣由:json

  • 數據兩份、集羣兩份、物理成本高。三機房、五機房等更多機房多活,成本及複雜性更高。
  • 存在一致性問題,兩地集羣數據不一致,balance狀況下尤其突出
  • 因爲人力緣由,若是開源同步工具出現問題把控不在。

方案一:同城三機房多活方案(1mongod+1mongod+1mongod方式)

  • 每一個機房代理至少部署2個,保證業務訪問代理高可用
  • 若是某機房異常,而且該機房節點爲主節點,藉助mongodb自然的高可用機制,其餘機房2個mongod實例會自動選舉一個新節點爲主節點。
  • 客戶端配置nearest就近訪問,保證讀走本機房節點。
  • 弊端:若是是異地機房,B機房和C機房寫存在跨機房寫場景。若是A B C爲同城機房,則沒用該弊端,同城機房時延能夠忽略。

方案二:同城兩機房多活方案(2mongod+2mongod+1arbiter模式)數組

  • 每一個機房代理至少部署2個,保證業務訪問代理高可用
  • 若是機房A掛掉,則會在B機房mongod中從新選舉一個新的主節點。arbiter選舉節點不消耗資源
  • 客戶端配置nearest參數,保證讀走本機房節點
  • 弊端:若是是異地機房,B機房和C機房寫存在跨機房寫場景。若是A B 爲同城機房,則沒用該弊端,同城機房時延能夠忽略。

方案三:異地三機房多活方案(1mongod+1mongod+1mongod方式)-解決跨機房寫

  • 每一個機房代理經過打標籤的方式,代理轉發數據到主節點在本機房的分片上去。
  • A機房數據經過標籤識別轉發到分片shard-1,B機房數據轉發到分片shard-2,C機房數據轉發到分片shard-3。

分享主題四mongodb線程模型瓶頸及其優化方法

mongodb默認線程模型(一個連接一個線程)

說明:

  • listener線程負責接受全部的客戶端連接
  • listener線程每接收到一個新的客戶端連接就建立一個線程,該線程只負責處理該連接請求處理。

該網絡線程模型缺陷:

  • 一個連接建立一個線程,若是10萬個連接,那麼就須要10萬個線程,系統負責、內存消耗也會不少
  • 當連接關閉的時候,線程銷燬,頻繁的線程建立和消耗進一步增長系統負載

典型案例:

  • mysql默認方式、mongodb同步線程模型配置,適用於請求處理比較耗時的場景,如數據庫服務

mongodb默認線程模型(動態線程模型:單隊列方式)

說明:

  • 該模型把一次請求轉換爲多個任務:mongodb數據讀操做(網絡IO)、db層數據訪問(磁盤IO)。
  • 任務入隊到全局隊列,線程池中的線程從隊列中獲取任務執行。
  • 同一個請求訪問被拆分爲多個任務,大部分狀況下經過遞歸調用同一個請求的多個任務會由同一個線程處理;。
  • 當任務太多,系統壓力大的時候,線程池中線程數動態增長;當任務減小,系統壓力減小的時候,線程池中線程數動態減小;

該網絡線程模型缺陷:

  • 線程池獲取任務執行,有全局鎖競爭,這裏就會成爲系統瓶頸

典型案例:

  • mongodb動態adaptive線程模型,適用於請求處理比較耗時的場景,如數據庫服務

mongodb優化後線程模型(動態線程模型-多隊列方式)

說明:

  • 把一個全局隊列拆分爲多個隊列,任務入隊的時候按照session連接hash散列到各自的隊列,工做線程獲取獲取任務的時候,同理經過一樣的hash算法去對應的隊列獲取任務,經過這種方式減小鎖競爭,同時提高總體性能。

典型案例:

  • mongodb內核多隊列adaptive線程模型優化,特定場景性能有很好的提高,適用於請求處理比較耗時的場景,如數據庫服務。

分享主題五並行遷移-集羣擴容速率N倍提高優化實踐

並行遷移-集羣擴容速率N倍提高優化實踐(高版本)

並行遷移過程(假設須要遷移的表名爲:test, 從3節點擴容到6節點):

  • 選取須要遷移的塊,假設源集羣有M分片,擴容新增N分片,則通常狀況須要遷移的塊=min(M,N)
  • 遷移步驟:1. configServer-master選出須要遷移的塊;2. config.locks表中id=test這條記錄上鎖;3.通知須要遷移的源分片開始遷移;4. 遷移完成後延時10s,重複1-4步驟實現持續性chunk數據遷移

並行遷移步驟:

   說明:假設須要遷移的表名爲test, 源分片數M,擴容後新增分片數N

  • configServer-master選出須要遷移的塊,通常S=min(M, N),也就是M和N中的最小值;
  • config.locks表中獲取id=test這條記錄對應的分佈式鎖;
  • 異步通知須要遷移的S個源分片開始遷移;
  • 等待S個chunk遷移完成
  • 遷移完成後延時10秒
  • 重複步驟1-5

並行遷移瓶頸:

  • 獲取分佈式鎖時間太長,緣由:config.locks表中id=test表的分佈式鎖可能被其餘操做鎖住
  • configServer異步通知源分片中的S個分片同時開始遷移數據到目的分片,任一個chunk遷移慢會拖累整個遷移過程。
  • 本批次確認遷移完成後,還須要延時10s;通常SSD服務器,一個chunk遷移都在幾百ms內完成。

優化方法:

  • 避免其餘操做佔用分佈式鎖,例如splite咱們能夠關閉autoSplite功能,或者調大chunksize
  • configServer並行遷移不把多個分片的並行遷移放到同一個邏輯,而是放到各自的邏輯。
  • 延時放到各自分片遷移邏輯裏面控制,不受全局延時控制
  • 分片延時可配置,支持實時動態命令行調整

分享主題六:性能優化案例

案例1.千億級數據量mongodb集羣性能數倍提高優化實踐-背景

業務背景:

  • 核心元數據
  • 數據量千億級
  • 前期寫多讀少,後期讀多寫少
  • 高峯期讀寫流量百萬級
  • 時延敏感
  • 數據增加快,不按期擴容
  • 同城多活集羣

優化策略1:部署及使用方式優化

  • 預分片,寫入負載均衡。
  • WriteConcern:{ w: "majority"},寫大部分節點成功才返回客戶端OK
  • 讀寫分離,讀從優先。
  • enableMajorityReadConcern關閉,有性能損耗。

優化策略2:存儲引擎cache淘汰策略優化

   wiredtiger存儲引擎cache淘汰策略相關的幾個配置以下:

wiredtiger存儲引擎cache淘汰策略優化後配置:

eviction_target: 75%,eviction_trigger:97%,eviction_dirty_target: %3,eviction_dirty_trigger:25%,evict.threads_min:4,evict.threads_max:16

整體思想:evict線程儘早淘汰髒頁page到磁盤,增長evict淘汰線程數加快髒數據淘汰,避免用戶請求線程進行髒數據淘汰。

優化策略3:存儲引擎checkpoint優化

    存儲引擎checkpoint檢測點,把當前存儲引擎髒數據所有記錄到磁盤。觸發條件以下:

  • 固定週期作一次checkpoint快照,默認60s
  • 增量journal日誌達到2G

少部分實例存在以下現象:一下子磁盤IO幾乎空閒0%,一下子磁盤IO短暫性100%。進行以下優化後能夠緩解該問題:

     checkpoint=(wait=30,log_size=1GB)

該優化整體思路:縮短checkpoint週期,減小checkpoint期間積壓的髒數據,緩解磁盤IO高問題。

遺留問題:SSD盤只有極少數節點有該問題,緣由未知,後續繼續跟蹤。

瓶頸點:

  • 代理緩存全部客戶端的連接信息到內存中,並按期更新到config庫的system.sessions表中。
  • 大流量大數據量集羣客戶端連接衆多,大量更新sessions表,最終主分片性能降低引發整個集羣性能瞬間數倍降低。

優化方法:

  • config庫的system.sessions表啓用分片功能。  
  • mongos按期更新優化爲散列到不一樣時間點進行更新。

優化策略4:

  • sharding集羣system.session優化

該優化整體思路:

  • 以前代理集中式更新單個分片,優化爲散列到不一樣時間點更新多個分片。
  • 該優化後system.sessions表更新引發的瞬間性能數倍下降和大量慢日誌問題獲得瞭解決。

優化策略5:tcmalloc內存優化

  • db.serverStatus().tcmalloc監控發現部分mongod實例pageheap、內存碎片等消耗太高。經過系統調用分析得出:內存碎片率、pageheap太高,會引發分配內存過程變慢,引發集羣性能嚴重降低。

該優化整體思路:

  • 藉助gperftools三方庫中tcmalloc內存管理模塊,實時動態調整tcmalloc內存Release Rate,儘早釋放內存,避免存儲引擎獲取cache過程阻塞變慢。

案例2.萬億級數據量mongodb集羣性能數倍提高優化實踐

業務背景:

  • 集羣存儲離線數據
  • 集羣總數據量萬億級
  • 前期主要爲數據寫入,要求萬億級數據幾周內儘快所有寫入集羣
  • 後期主要是讀流量,單次查詢數據條數比較多,要求快速返回
  • 每隔必定時間週期(周爲單位)會有持續性大量寫入

優化策略1:基礎性優化

  • 分享主題六中讀寫分離、預分片、wiredtiger存儲引擎優化、session優化、tcmalloc使用優化等基礎性優化策略一樣適用於該集羣,具體詳見《分享主題六:百萬級高併發讀寫/千億級數據量mongodb集羣性能數倍提高優化實踐》

優化策略2:存儲模型優化前情況

    優化前數據模型結構以下:

1.{  
2.    "_id": ObjectId("5fh2ebd18856960dbac31abc"),  
3.    "characteristic": "xxxx",  
4.    "key1": "***",  
5.    ......  
6.    "keyn": "***",  
7.}  
  • 以上爲單條數據的數據模型,該集羣總數據量萬億級。
  • 數十萬條數據擁有一樣的characteristic特性,總特性數總計數百萬個。
  • 一次性查詢數十個characteristic很慢。

瓶頸點: 一次性查詢數十個characteristic特徵條件的數據,每一個特徵擁有數百萬數據,一次查詢總計千萬行數據。因爲數據量很大,每行數據幾乎全在磁盤,一次查詢須要千萬次IO操做,查詢成爲瓶頸。  

優化策略2:第一輪數據存儲模型優化:

1.{  
2.    "_id": ObjectId("5f29ebd18856960dbac31abc"),  
3.    "characteristic": "xxxx"  
4.    "group": [  
5.           {  
6.            "key1": "***"  
7.            ......  
8.            "keyn": "***"  
9.        },   #該characteristic下第一條數據  
10.            ......  
11.        {  
12.            "key1": "***"  
13.            ......  
14.            "keyn": "***"  
15.        } #該characteristic下第n條數據  
16.    ]  
17.} 
  • 該數據模型把相同characteristic特性的數十萬數據合併到爲一條數據,減小磁盤IO操做,整個讀性能會有近百倍提高。

瓶頸點:該輪優化解決了讀瓶頸,卻引入了新的寫瓶頸。

  • 經過$addToSet方式向group數組中去重追加數據,數據長度愈來愈長,磁盤IO壓力愈來愈大、寫性能成爲新的瓶頸。

優化策略2:第二輪數據存儲模型優化:

1.{  
2.    "_id": ObjectId("5f29ebd18856960dbac31abc"),  
3.    "characteristic": "xxxx",  
4.   "hashNum": num,     
5.    "group": [  
6.           {  
7.            "key1": "***",  
8.            ......  
9.            "keyn": "***",  
10.        },   #該characteristic下第一條數據  
11.            ......  
12.        {  
13.            "key1": "***",  
14.            ......  
15.            "keyn": "***",  
16.        } #該characteristic下第n條數據  
17.    ]  
18.}  

        如上,把同一個characteristic特徵的數十萬/數百萬數據散列爲500份,這樣合併後group數組中也就只包含數百條數據信息,這樣合併後單條數據過大、mongodb單條數據64M限制問題磁盤IO太高等瓶頸問題均可以獲得解決。

整體數據模型優化思路:經過合理的數據合併操做來減小網絡IO、磁盤IO、mongodb內核處理時間,最終使讀和寫達到平衡。

分享主題七成本節省-記某服務千億級數據遷移mongodb,百臺SSD服務器節省優化實踐

成本節省-千億級數據遷移mongodb,百臺SSD服務器節省優化實踐

遷移背景:

  • 須要遷移的數據量數千億級
  • 源集羣磁盤緊張,業務寫入快,須要快速完成數據遷移
  • 源集羣數據存儲於高io ssd服務器
  • 業務對性能沒過高要求
  • 目的mongodb集羣採用低io 大容量sata盤

遷移難點:

  • 如何快速完成數據遷移?

瓶頸點:

  • 因爲目的集羣爲低io大容量sata盤,遷移太慢,源集羣磁盤有寫滿風險

優化策略:

  • 同步數據到大容量SSD中轉集羣
  • 拷貝中轉集羣數據到目標大容量SATA盤服務器
  • 加載數據

成本節省:

  • mongodb默認的snappy壓縮算法壓縮比約爲2.2-3.5倍
  • zlib壓縮算法壓縮比約爲4.5-7.5倍(本次遷移採用zlib高壓縮算法)

千億級數據遷移mongodb收益:

  • 源集羣磁盤消耗:目的集羣磁盤消耗 = 8:1(即便目的mongo集羣也用SSD服務器,成本也能夠節省七倍)
  • 源集羣物理資源:百臺SSD服務器
  • 目的mongodb集羣資源消耗:6臺SATA盤服務器

分享主題八展望-如何實現mongodb與SQL融合

問題背景:

    隨着mongodb-4.2版本中對分佈式事務的支持,以及mongodb-4.4版本產品規劃路線圖能夠看出,mongodb除了保持nosql特性外,還在朝着newSql方向前行。可是在實際業務接入中發現如下現象:

  • 開發習慣了SQL,轉mongodb語法各類不習慣。
  • 運營和數據分析崗位人員只會寫SQL,不會mongo語句。

咱們能作什麼?

  • mongos代理增長mongodb協議和SQL轉換支持,用最小開發成本知足業務SQL需求。
  • 5%-10%左右的SQL協議支持,知足90%的用戶需求。

分享主題九其餘-那些年咱們踩過的坑

「那些年咱們踩過的坑」 :      

  •       實際業務接入mongodb數據庫過程當中,咱們踩過不少坑,包括業務不合理使用、不合理運維、集羣不合理配置、mongodb內核踩坑、誤操做等,甚至出現過同一個核心業務幾回抖動。
  •       本次分享中集羣優化只列舉了主要的優化過程,實際優化過程比本次分享內容更加複雜,集羣更多優化細節及數十例典型踩坑過程將逐步在Qconf平臺、OPPO互聯網、mongodb中文社區發佈。

踩坑不可怕,在踩坑過程當中學習,學習過程當中減小踩坑

2021規劃:

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

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

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

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

 

代碼最能說明mongo實現細節,21年持續分析及優化mongodb內核源碼

《mongodb內核設計與實現、性能優化》

https://github.com/y123456yz/reading-and-annotate-mongodb-3.6

相關文章
相關標籤/搜索