記某百億級mongodb集羣數據過時性能優化實踐

      某百億級mongodb業務只保存近期7天的數據,因爲數據量大、流量高,數據過時刪除點比較集中,同時不能錯峯方式解決問題,所以如何利用最小物理成原本知足業務需求就成爲了本集羣性能優化的難點。mysql

      經過幾輪和業務配合調優,包括存儲引擎調優、數據刪除方式調優、業務錯峯讀寫等,最終完美解決了業務痛點,達到ms級業務讀寫訪問。git

關於做者

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

序言

       本文是oschina專欄《mongodb 源碼實現、調優、最佳實踐系列》的第24篇文章,其餘文章能夠參考以下連接:sql

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

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

百萬級高併發 mongodb 集羣性能數十倍提高優化實踐 (上篇)緩存

百萬級高併發 mongodb 集羣性能數十倍提高優化實踐 (下篇)性能優化

Mongodb特定場景性能數十倍提高優化實踐(記一次mongodb核心集羣雪崩故障)網絡

經常使用高併發網絡線程模型設計及mongodb線程模型優化實踐架構

爲什麼要對開源mongodb數據庫內核作二次開發

盤點 2020 | 我要爲分佈式數據庫 mongodb 在國內影響力提高及推廣作點事

 百萬級代碼量 mongodb 內核源碼閱讀經驗分享

話題討論 | mongodb 擁有十大核心優點,爲什麼國內知名度遠不如 mysql 高?

Mongodb 網絡模塊源碼實現及性能極致設計體驗

網絡傳輸層模塊實現二

網絡傳輸層模塊實現三

網絡傳輸層模塊實現四

command 命令處理模塊源碼實現一

command 命令處理模塊源碼實現二

mongodb 詳細表級操做及詳細時延統計實現原理 (快速定位表級時延抖動)

[圖、文、碼配合分析]-Mongodb write 寫 (增、刪、改) 模塊設計與實現

Mongodb集羣搭建一篇就夠了-複製集模式、分片模式、帶認證、不帶認證等(帶詳細步驟說明)

300條數據變動引起的血案-記某十億級核心mongodb集羣部分請求不可用故障踩坑記

記十億級Es數據遷移mongodb成本節省及性能優化實踐

千億級數據遷移mongodb成本節省及性能優化實踐

記某千億級IOT業務遷移mongodb成本節省及性能優化實踐(附性能對比質疑解答)

記某百億級mongodb集羣數據過時性能優化實踐

  1. 業務背景

      線上某業務數據量約100億,白天爲寫流量高峯期,峯值寫約14W/s,以下圖所示:

      業務天天白天生產數據,同時凌晨批量拉取過去幾天數據作大數據分析,整個集羣只保存最近七天數據。單條數據約800字節,以下所示:

1.  {  
2.        "_id" : ObjectId("608592008bd3dad61675b491"),  
3.        "deviceSn" : "xxxxxxxxxxxxx",  
4.        "itemType" : 0,  
5.        "module" : "xxxxxx",  
6.        "userId" : "xxxxx",  
7.        "callTimes" : NumberLong(2),  
8.        "capacityAdd" : NumberLong(0),  
9.        "capacityDelete" : 」xxxxxxxx」,  
10.        "capacityDownload" :」xxxxxxxxxxxx」,  
11.        "capacityModify" : 」xxxxxxxxxxxx」,  
12.        "createTime" : NumberLong("1619366400003"),  
13.        "expireAt" : ISODate("2021-05-02T22:53:45.497Z"),  
14.        "numAdd" : NumberLong(2),  
15.        "numDelete" : NumberLong(345),  
16.        "numDownload" : NumberLong(43),  
17.        "numModify" : NumberLong(3),  
18.        "osVersion" : "xxxx",  
19.        "reversedUserId" : "xxxxx",  
20.        "updateTime" : NumberLong("1619366402106")  
21.} 
  1. mongodb資源評估及部署架構

      經過和業務對接梳理,該集羣規模及業務需求總結以下:

  • 數據量百億級
  • 單條數據800字節,100億條預計7.5T數據
  • 讀寫分離
  • 全部數據只保留七天

2.1 mongodb資源評估

      分片數及存儲節點套餐規格選定評估過程以下:

  • 內存評估

      我司都是容器化部署,以以網經驗來看,mongodb對內存消耗不高,歷史百億級以上mongodb集羣單個容器最大內存基本上都是64Gb,所以內存規格肯定爲64G。

  1. 分片評估

      業務流量峯值10W/s多,預計須要3個分片支持讀寫。

  • 磁盤評估

    100億數據7.5T,因爲mongodb默認有高壓縮,預計真實磁盤佔用2.5~3T左右。三個分片,一個分片恰好1T。

  • CPU規格評估

      因爲容器調度套餐化限制,所以CPU只能限定爲16CPU(實際上用不了這麼多CPU)。

  • mongos代理及config server規格評估

       此外,因爲分片集羣還有mongos代理和config server複製集,所以還須要評估mongos代理和config server節點規格。因爲config server只主要存儲路由相關元數據,所以對磁盤、CUP、MEM消耗都很低;mongos代理只作路由轉發只消耗CPU,所以對內存和磁盤消耗都不高。最終,爲了最大化節省成本,咱們決定讓一個代理和一個config server複用同一個容器,容器規格以下:

       8CPU/8G內存/50G磁盤,一個代理和一個config server節點複用同一個容器。

分片及存儲節點規格總結:4分片/16CPU、64G內存、1T磁盤。

mongos及config server規格總結:8CPU/8G內存/50G磁盤

3.2 集羣部署架構

      該業務數據不是很重要,爲了節省成本,所以咱們採用2+1模式部署,也就是:2mongod+1arbiter模式,同城機房部署,部署架構圖以下圖所示:

       考慮到數據重要性不高,經過2mongod+1arbiter模式便可知足用戶要求,同時能夠最大化節省成本。

4. 性能優化過程

       該集羣優化過程按照以下兩個步驟優化:業務使用集羣前的性能優化、業務使用過程當中的性能優化。

       業務提早建好查詢對應的最優索引,同時建立過時索引:

db.xxx.createIndex( { "createTime": 1 }, { expireAfterSeconds: 604800} )

4.1 業務使用集羣前的性能優化

       和業務溝通肯定,業務每條數據都攜帶有一個設備標識userId,同時業務查詢更新等都是根據userId維度查詢該設備下面的單條或者一批數據,所以片建選擇userId。

  • 分片方式

       爲了充分散列數據到3個分片,所以選擇hash分片方式,這樣數據能夠最大化散列,同時能夠知足同一個userId數據落到同一個分片,保證查詢效率。

  • 預分片

       mongodb若是分片片建爲hashed分片,則能夠提早作預分片,這樣就能夠保證數據寫進來的時候比較均衡的寫入多個分片。預分片的好處能夠規避非預分片狀況下的chunk遷移問題,最大化提高寫入性能。

sh.shardCollection("xxx_xx.xxx", {userId:"hashed"}, false, { numInitialChunks: 8192} )

  • 就近讀

       客戶端增長secondaryPreferred配置,優先讀從節點。

  • 禁用enableMajorityReadConcern

       禁用該功能後ReadConcern majority將會報錯,ReadConcern majority功能注意是避免髒讀,和業務溝通業務沒該需求,所以能夠直接關閉。

mongodb默認使能了enableMajorityReadConcern,該功能開啓對性能有必定影響,參考:

MongoDB readConcern 原理解析

OPPO百萬級高併發MongoDB集羣性能數十倍提高優化實踐

  1. 存儲引擎cacheSize規格選擇

       單個容器規格:16CPU、64G內存、7T磁盤,考慮到全量遷移過程當中對內存壓力,內存碎片等壓力會比較大,爲了不OOM,設置cacheSize=42G。

5.2 業務使用過程當中遇到的問題及性能優化

5.2.1 第一輪優化:存儲引擎優化

       業務高峯期主要是數據寫入和更新,內存髒數據較多,當髒數據比例達到必定比例後用戶讀寫請求對應線程將會阻塞,用戶線程也會去淘汰內存中的髒數據page,最終寫性能降低明顯。

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

      因爲業務全量遷移數據是持續性的大流量寫,而不是突發性的大流量寫,所以eviction_target、eviction_trigger、eviction_dirty_target、eviction_dirty_trigger幾個配置用處不大,這幾個參數閥值只是在短期突發流量狀況下調整纔有用。

       可是,在持續性長時間大流量寫的狀況下,咱們能夠經過提升wiredtiger存儲引擎後臺線程數來解決髒數據比例太高引發的用戶請求阻塞問題,淘汰髒數據的任務最終交由evict模塊後臺線程來完成。

       全量大流量持續性寫存儲引擎優化以下:

db.adminCommand( { setParameter : 1, "wiredTigerEngineRuntimeConfig" : "eviction=(threads_min=4, threads_max=20)"})

5.2.2 第一輪優化後存在的問題

       通過存儲引擎後臺線程數的調優後,數據寫入和更新瓶頸解決,寫入和更新過程時延都很平滑。可是隨着一週後開始數據過時,業務寫開始大量抖動,以下所示:

        從上圖能夠看出平均時延極端狀況下甚至達到了幾百ms,這啥業務徹底接受不了的。經過mongostat監控發現以下現象:

  • 主節點mongostat監控統計

       從上面的監控能夠看出,三個分片的每一個主節點只有4000左右的寫更新操做(注意:實際上還有4萬左右的delete操做,因爲主節點過時delete不會統計,所以只能經過從節點查看,詳見後面分析,實際單個分片主節點寫和刪除操做4.4W/s),寫流量很低。可是,監控中的髒數據比例持續性的超過20%,超過20%後業務的請求就須要進行髒數據淘汰,最終形成業務請求阻塞抖動。

       經過前面的分析能夠看出,業務正常峯值寫入3個分片差很少10W/s。一星期後,七天前的數據須要過時,這時候過時刪除的ops也須要delete刪除10w/S,因爲這時候新數據一樣按照10w/s寫入,所以集羣就須要支持20w/s的ops操做才能支持。

       顯然,3個分片支持不了持續性的20w/s左右的ops操做,所以如何不擴容狀況下支撐業務需求將是一大難點。

  • 爲什麼ttl過時主節點沒用delete統計

        上圖爲mongodb單機模塊架構圖,主節點默認啓用一個TTLMonitor線程,藉助查詢引發模塊實時掃描過時索引,而後把知足條件的數據刪除。整個刪除過程沒有走command命令處理模塊,而命令計數操做只會在command模塊計數,所以主節點的過時刪除不會有delete操做。

     命令處理模塊處理流程及其計數統計詳見:mongodb內核源碼模塊化設計與實現專欄

      更多mongodb模塊化源碼設計實現詳見:

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

 

5.3 第二輪優化(過時刪除放凌晨低峯期)-不可行

       從前面的分析能夠看出,咱們三個分片支撐不了持續性20W/S的更新和刪除操做,所以咱們考慮業務改造使用方式,把過時刪除肯定到凌晨低峯期。

       可是業務上線後出現其餘的問題,因爲業務凌晨會持續性的批量拉取分析過去幾天的數據,若是過時和批量讀數據疊加到一塊兒,嚴重影響業務查詢效率。最終,該方案不可行,若是不擴容,則須要其餘方案。

5.4 第三輪方案優化(天維度建表,過時刪表)

       爲了避免增長成本,同時3個分片又支撐不了20W/s的讀寫刪除等致使,爲了儘可能經過3個分片不擴容條件下來知足用戶需求,所以轉變方式,經過刪表的方式來避免過時,具體實現以下:

  • 業務改造代碼,以天爲單位建表,天天的數據存到對應的表中。
  • 建表後業務啓用預分片功能,確保數據均衡分佈到三個分片。
  • 業務保存8天數據,第九天凌晨刪除第一天的表

    該方案業務時延統計對應收益以下:

       如上圖所示,經過過時方式的優化,最終問題完全解決,而且讀寫時延控制在0.5ms-2ms。

6 優化總結

     經過前面的一系列優化,最終沒有擴容,而且解決了業務過時和大量數據寫入更新引發的時延抖動問題,整體收益以下:

  • 優化前時延:常常幾百ms抖動
  • 優化後時延:0.5-2ms
相關文章
相關標籤/搜索