使用外部日誌時禁用 ext4 寫屏障
我目前正在嘗試使用不同的方法在 Debian 上使用快速 NVMe 設備提高寫入速度到相當大的、基於旋轉磁碟的軟體 raid (mdadm) 陣列。
我發現使用一對這樣的設備(raid1,mirrored)來儲存文件系統的日誌會產生有趣的性能優勢。我用來實現這一點的掛載選項是
noatime,journal_aync_commit,data=journal
.在我的測試中,我還發現添加該
barrier=0
選項在寫入性能方面具有顯著優勢。但是,我不確定在我的特定文件系統配置中使用此選項是否安全。這是核心文件中關於 ext4 寫屏障的內容:寫屏障強制執行日誌送出的正確磁碟順序,使易失性磁碟寫記憶體可以安全使用,但會降低一些性能。如果您的磁碟以一種或另一種方式由電池供電,則禁用屏障可以安全地提高性能。
我正在使用的特定 NVMe 設備是Intel DC P3700,它具有內置的斷電保護,這意味著在意外關機的情況下,由於備用能量,仍然存在於臨時緩衝區中的任何數據都會安全地送出到 NAND 儲存貯存。
所以我的問題是,如果日誌儲存在具有電池支持記憶體的設備上,而文件系統本身的其餘部分位於沒有此功能的磁碟上,我是否可以安全地禁用 ext4 寫屏障?
我正在寫一個新答案,因為經過進一步分析,我認為以前的答案不正確。
如果我們查看該
write_dirty_buffers
函式,它會發出帶有REQ_SYNC
標誌的寫入請求,但不會導致發出記憶體刷新或屏障。這是通過blkdev_issue_flush
呼叫來完成的,該呼叫通過對標誌的驗證進行適當的門控,該JDB2_BARRIER
標誌本身僅在文件系統安裝時啟用了屏障時才存在。因此,如果我們回顧一下
checkpoint.c
,障礙僅在事務從日誌中刪除時才重要。程式碼中的註釋在這裡提供了豐富的資訊,告訴我們這個寫屏障不太可能是必要的,但無論如何作為一種保護措施。我認為這裡的假設是,當事務從日誌中刪除時,數據本身不太可能仍然在驅動器的記憶體中徘徊,並且尚未送出到永久儲存。但由於這只是一個假設,所以無論如何都會發出寫屏障。那麼為什麼在向主文件系統寫入數據時不使用屏障呢?我認為這裡的關鍵是,只要日誌是連貫的,文件系統中失去的元數據(例如,因為它在斷電事件中失去)通常會在日誌重放期間恢復,從而避免文件系統損壞。此外,使用
data=journal
還應該保證實際文件系統數據的一致性,因為據我了解,恢復過程還將寫出作為其重放機制的一部分送出給日誌的數據塊。因此,雖然 ext4 實際上並沒有在檢查點結束時刷新磁碟記憶體,但應該採取一些步驟來最大限度地提高斷電時的可恢復性:
- 文件系統應該掛載
data=journal
,而不是data=writeback
(data=ordered
在使用外部日誌時不可用)。這一點應該很明顯:我們想要日誌中所有傳入數據塊的副本,因為這些數據塊很可能在斷電事件中失去。這在性能方面並不昂貴,因為 NVMe 設備非常快。- 應使用 102400 塊的最大日誌大小(使用 4K 文件系統塊時為 400MB),以最大限度地提高日誌重放中可恢復的數據量。這應該不是問題,因為所有 NVMe 設備的大小始終至少有幾 GB。
- 如果在寫入密集型操作期間發生意外關閉,問題仍然可能出現。如果事務從日誌設備中刪除的速度快於數據驅動器自行刷新記憶體的速度,則可能會發生不可恢復的數據失去或文件系統損壞。
因此,在我看來,底線是禁用寫屏障並不是 100% 安全的,儘管可以實施一些預防措施(#1 和 #2)以使此設置更安全一些。