本文最初發表於MongoDB。感謝支持使SitePoint成為可能的合作夥伴。
理解各種內部緩存與磁盤性能之間的關係,以及這些關係如何影響數據庫和應用程序性能,可能具有挑戰性。我們使用了YCSB基準測試,改變工作集(測試中使用的文檔數量)和磁盤性能,以更好地展示它們之間的關係。在審查結果時,我們將介紹一些MongoDB內部機制,以提高對常見數據庫使用模式的理解。
關鍵要點
摘要
整體系統性能的主要影響因素是工作集如何與存儲引擎緩存大小(專用於存儲數據的內存)和磁盤性能(它為訪問數據的速度提供了物理限制)相關。
使用YCSB,我們探索了磁盤性能和緩存大小之間的相互作用,演示了這兩個因素如何影響性能。雖然本測試使用了YCSB,但合成基準測試不能代表生產工作負載。通過這些方法獲得的延遲和吞吐量數字不會映射到生產性能。我們使用了MongoDB 3.4.10、YCSB 0.14和MongoDB 3.6.0驅動程序進行這些測試。 YCSB配置了16個線程和“uniform”只讀工作負載。
我們證明,將工作集放入內存中可以提供最佳的應用程序性能,並且與任何數據庫一樣,超過此限制會對延遲和整體吞吐量產生負面影響。
理解磁盤指標
考慮磁盤性能時,有四個重要的指標:
測試磁盤性能
雖然雲提供商可能會為給定的捲和磁盤提供IOPS閾值,並且磁盤製造商會發布預期的性能數字,但您系統上的實際結果可能會有所不同。如果觀察到的磁盤性能有問題,執行IO測試會非常有幫助。
我們通常使用fio(靈活IO測試器)進行測試。我們在10GB的數據上進行了測試,ioengine為psync,讀取範圍在4kb到32kb之間。雖然默認的fio設置不能代表WiredTiger工作負載,但我們發現此配置是WiredTiger磁盤利用率的一個很好的近似值。
所有測試都在三種磁盤場景下重複進行:
場景1
AWS c5 io1 100GB卷提供的默認磁盤設置。 5000 IOPS
場景2
將磁盤限制為600 IOPS並引入7毫秒的延遲。這應該反映典型的帶有硬盤的RAID10 SAN的性能
場景3
進一步將磁盤限制為150 IOPS,延遲為7毫秒。這應該模擬普通旋轉硬盤。
查詢如何從磁盤服務?
WiredTiger存儲引擎執行自己的緩存。默認情況下,WiredTiger緩存的大小為系統內存的50%減去1GB,以便為其他系統進程、文件系統緩存和使用額外內存的內部MongoDB操作(例如構建索引、執行內存排序、重複數據刪除結果、文本評分、連接處理和聚合)留出足夠的空。為了防止緩存完全滿導致性能下降,當利用率超過80%時,WiredTiger會自動開始從緩存中逐出數據。對於我們的測試,這意味著有效的緩存大小為(7634MB – 1024MB)* .5 * .8,或2644MB。
所有查詢都由WiredTiger緩存服務。這意味著查詢將導致索引和文檔通過文件系統緩存讀取到WiredTiger緩存中,然後再返回結果。如果請求的數據已在緩存中,則跳過此步驟。
WiredTiger默認使用snappy壓縮算法存儲文檔。從文件系統緩存讀取的任何數據在存儲到WiredTiger緩存之前都會先解壓縮。索引默認使用前綴壓縮,並在磁盤和WiredTiger緩存中都被壓縮。
文件系統緩存是操作系統結構,用於將經常訪問的文件存儲在內存中,以方便更快地訪問。 Linux在緩存文件方面非常積極,並將嘗試使用文件系統緩存消耗所有可用內存。如果需要更多內存,則會逐出文件系統緩存,以便為應用程序提供更多內存。
這是一個動畫圖形,顯示了由100個YCSB讀取操作產生的YCSB集合的磁盤訪問。每個操作都是單個文檔的_id的單個查找。
左上角代表WiredTiger集合文件中的第一個字節。磁盤位置向右遞增並環繞。每一行代表WiredTiger集合文件的3.5MB段。訪問按時間順序排列,並由動畫幀表示。訪問用紅色和綠色方塊表示,以突出顯示當前的磁盤訪問。
3.5 MB vs 4KB
在這裡,我們看到我們的集合數據文件被讀入內存。因為數據存儲在B 樹中,所以我們可能需要通過訪問磁盤上的一個或多個位置來查找文檔的磁盤位置(較小的訪問),然後才能找到並讀取我們的文檔(較大的訪問) 。
這演示了MongoDB查詢的典型訪問模式——文檔不太可能在磁盤上彼此靠近。這也表明,即使在彼此之後插入,文檔也不太可能位於連續的磁盤位置。
WiredTiger存儲引擎旨在“完全讀取”:它將一次發出所有所需數據的讀取請求。這導致我們建議將WiredTiger部署的磁盤提前讀取限制為零,因為後續訪問不太可能利用通過提前讀取檢索的額外數據。
工作集適合緩存
對於我們的第一組測試,我們將記錄計數設置為200萬,導致數據和索引的總大小為2.43 GB,或緩存的92%。
在這裡,我們看到場景1的強大性能為每秒76,113個請求。檢查文件系統緩存統計信息,我們觀察到WiredTiger緩存命中率為100%,沒有訪問,並且沒有字節讀入文件系統緩存,這意味著在整個測試過程中不需要額外的IO。
不出所料,在場景2和場景3中,更改磁盤性能(添加7毫秒的延遲並將iops限制為600或150)對吞吐量的影響最小(分別為69,579.5和70,252次操作/秒) 。
我們所有三個測試的99%響應延遲都在0.40到0.44毫秒之間。
工作集大於WiredTiger緩存,但仍適合文件系統緩存
現代操作系統緩存經常訪問的文件以提高讀取性能。因為文件已在內存中,所以訪問緩存文件不會導致物理讀取。 free Linux命令顯示的文件系統緩存統計信息詳細說明了文件系統緩存的大小。
當我們將記錄計數從200萬增加到300萬時,我們將數據和索引的總大小增加到3.66GB,比僅從WiredTiger緩存服務的大38%。
指標清楚地表明,我們平均讀取548 mbps到WiredTiger緩存中,但是當檢查文件系統緩存指標時,我們可以觀察到99.9%的命中率。
對於此測試,我們開始看到性能下降,每秒僅執行66,720次操作,與我們的基線相比,減少了8%,而我們的基線僅從WiredTiger緩存服務。
正如預期的那樣,在這種情況下,降低磁盤性能不會顯著影響我們的整體吞吐量(分別為64,484和64,229次操作)。在文檔更易於壓縮或CPU是限制因素的情況下,從文件系統緩存讀取的懲罰將更加明顯。
我們注意到觀察到的p99延遲增加了54%,達到.53–.55毫秒。
工作集略大於WiredTiger和文件系統緩存
我們已經確定WiredTiger和文件系統緩存協同工作以提供數據來服務我們的查詢。但是,當我們將記錄計數從300萬增加到400萬時,我們不能再僅僅利用這些緩存來服務查詢。我們的數據大小增長到4.8GB,比我們的WiredTiger緩存大82%。
在這裡,我們以257.4 mbps的速率讀取到WiredTiger緩存中。我們的文件系統緩存命中率降低到93-96%,這意味著4-7%的讀取導致從磁盤進行物理讀取。
改變可用的IOPS和磁盤延遲對本測試的性能有巨大影響。
第99個百分位數的響應延遲進一步增加。場景1:19毫秒,場景2:171毫秒,場景3:770毫秒,與緩存內的情況相比,增加了43倍、389倍和1751倍。
與我們之前完全適合緩存的測試相比,當MongoDB提供完整的5000 iops時,我們看到性能降低了75%。場景2和場景3分別實現了5139.5和737.95次操作/秒,進一步證明了IO瓶頸。
工作集遠大於WiredTiger和文件系統緩存
移動到500萬條記錄,我們將數據和索引大小增加到6.09GB,大於我們組合的WiredTiger和文件系統緩存。我們看到我們的吞吐量低於我們的IOPS。在這種情況下,我們仍然從文件系統緩存中服務81%的WiredTiger讀取,但是從磁盤溢出的讀取正在飽和我們的IO。我們看到此測試的文件系統緩存讀取速度為71、8.3和1.9 Mbps。
第99個百分位數的響應延遲進一步增加。場景1:22毫秒,場景2:199毫秒,場景3:810毫秒,與緩存內響應延遲相比,增加了52倍、454倍和1841倍。在這裡,更改磁盤IOPS會顯著影響我們的吞吐量。
摘要
通過這一系列測試,我們證明了兩個主要觀點。
了解MongoDB如何利用內存和磁盤是調整部署規模和理解性能的重要組成部分。 WiredTiger存儲引擎的內部工作試圖充分利用硬件,但內存和磁盤是影響工作負載整體性能特徵的兩個關鍵基礎設施部分。
關於MongoDB中內存和磁盤性能的常見問題
MongoDB使用內存和磁盤空間來存儲和管理數據。它使用內存映射文件系統進行數據存儲,這意味著它將整個數據文件映射到RAM中。這允許MongoDB有效地處理大型數據集。操作系統的虛擬內存子系統管理細節,根據需要將數據進出內存交換。另一方面,磁盤空間用於存儲數據文件、索引和日誌。 MongoDB自動以大塊分配磁盤空間,以優化寫入操作。
高磁盤I/O利用率會嚴重影響MongoDB數據庫的性能。它會導致讀取和寫入操作變慢,這會降低應用程序的整體性能。對於需要實時數據訪問的應用程序來說,這尤其成問題。高磁盤I/O利用率還會導致CPU使用率增加,因為系統花費更多時間來管理磁盤操作。
MongoDB提供了幾種監控磁盤空間使用情況的工具。 db.stats()命令提供數據庫的高級概述,包括數據文件和索引的總大小。 db.collection.stats()命令提供有關特定集合的更詳細信息,包括數據和索引的大小。此外,MongoDB Atlas(MongoDB提供的數據庫即服務產品)提供了一套全面的監控工具,包括有關高磁盤空間使用情況的警報。
有幾種策略可以解決MongoDB中的高磁盤空間利用率。一種方法是刪除不必要的數據或集合。另一種方法是使用compact命令,該命令對數據文件進行碎片整理並回收未使用的磁盤空間。但是,此命令需要大量的可用磁盤空間,並且會影響數據庫性能。分片(將數據分佈到多台服務器)也可以幫助管理磁盤空間使用情況。
RAM驅動器是操作系統視為磁盤驅動器的一塊內存。因為RAM比磁盤存儲快得多,所以使用RAM驅動器可以顯著提高需要高速數據訪問的應用程序的性能。但是,因為RAM是易失性的,所以當系統重新啟動時,存儲在RAM驅動器中的數據會丟失。在MongoDB的上下文中,RAM驅動器可用於存儲經常訪問的數據或索引以提高性能。但是,應謹慎執行此操作,因為如果系統重新啟動,可能會發生數據丟失。
MongoDB依賴於底層操作系統進行內存管理。它使用內存映射文件系統,允許操作系統的虛擬內存子系統管理內存中數據的細節以及磁盤上的數據。這種方法允許MongoDB有效地處理大型數據集,但這也意味著MongoDB的內存使用情況可能會受到同一系統上運行的其他進程的影響。
有幾種策略可以優化MongoDB的內存使用情況。一種方法是確保您的工作集適合內存。工作集是經常訪問的數據部分。如果您的工作集適合內存,MongoDB可以避免代價高昂的磁盤I/O操作。另一種方法是有效地使用索引。索引可以顯著提高查詢性能,但它們也會消耗內存。因此,明智地創建索引並監控它們對內存使用情況的影響非常重要。
MongoDB使用預寫日誌來確保數據完整性。在對數據文件進行任何更改之前,它們首先會被寫入日誌。這允許MongoDB從崩潰或電源故障中恢復。但是,日誌記錄也會增加磁盤I/O操作,這會影響性能。因此,監控磁盤I/O利用率並在必要時採取措施對其進行優化非常重要。
有幾種策略可以優化MongoDB的磁盤I/O操作。一種方法是使用SSD,它可以處理比傳統硬盤更多的IOPS。另一種方法是使用針對寫入操作進行優化的RAID配置。此外,您可以調整MongoDB的日誌記錄設置以減少對磁盤I/O的影響。但是,應謹慎執行此操作,因為它會影響數據完整性。
內存和磁盤性能是MongoDB數據庫整體性能的關鍵因素。如果您的工作集適合內存,MongoDB可以避免代價高昂的磁盤I/O操作,這可以顯著提高性能。同樣,有效的磁盤I/O操作可以提高寫入操作的性能並確保數據完整性。因此,監控和優化內存和磁盤性能以確保MongoDB數據庫獲得最佳性能非常重要。
以上是內存和磁盤性能如何影響您的MongoDB數據庫的詳細內容。更多資訊請關注PHP中文網其他相關文章!