Linux的磁盤緩存和刷臟頁
我們討論了Linux客戶機上的內(nèi)存如何用于操作系統(tǒng)本身(內(nèi)核,緩沖區(qū)等),應用程序以及文件緩存。文件緩存是一項重要的性能改進,在大多數(shù)情況下,讀取緩存是一個明顯的勝利,與直接使用 RAM 的應用程序相比,這是平衡的。寫入緩存更棘手。Linux 內(nèi)核將磁盤寫入暫存到緩存中,并隨著時間的推移將它們異步刷新到磁盤。這在加速磁盤 I/O 方面有很好的效果,但存在風險。當數(shù)據(jù)未寫入磁盤時,丟失數(shù)據(jù)的可能性會增加。
也有可能大量 I/O 也會使緩存不堪重負。是否曾經(jīng)一次將大量數(shù)據(jù)寫入磁盤,并在嘗試處理所有這些數(shù)據(jù)時看到系統(tǒng)上出現(xiàn)大量暫停?這些暫停是緩存決定有太多數(shù)據(jù)要異步寫入(作為非阻塞后臺操作,讓應用程序進程繼續(xù))并切換到同步寫入(阻塞并使進程等待 I/O 提交到磁盤)的結果。當然,文件系統(tǒng)還必須保留寫入順序,因此當它開始同步寫入時,它首先必須轉儲緩存。因此長時間停頓。
好消息是,這些都是可控的選項,根據(jù)您的工作負載和數(shù)據(jù),您可以決定如何設置它們。一起來看看:
?vm.dirty_background_ratio是在 pdflush/flush/kdmflush 后臺進程啟動將其寫入磁盤之前,可以用“臟”頁(仍需要寫入磁盤的內(nèi)存頁)填充的空閑內(nèi)存和緩存和的百分比。我的例子是 10%,所以如果我的虛擬服務器有 32 GB 的內(nèi)存,那就是 3.2 GB 的數(shù)據(jù),可以在完成某些操作之前駐留在 RAM 中。
vm.dirty_ratio 是在必須將所有內(nèi)容提交到磁盤之前可以用臟頁填充的絕對最大系統(tǒng)內(nèi)存量。當系統(tǒng)到達此時,所有新的 I/O 塊,直到臟頁已寫入磁盤。這通常是長時間 I/O 暫停的根源,但可以防止在內(nèi)存中不安全地緩存過多數(shù)據(jù)。
vm.dirty_background_bytes和vm.dirty_bytes是指定這些參數(shù)的另一種方法。如果設置_bytes版本,則_ratio版本將變?yōu)?0,反之亦然。
vm.dirty_expire_centisecs是某些內(nèi)容在需要寫入之前可以在緩存中存在多長時間。在本例中為 30 秒。當 pdflush/flush/kdmflush 進程啟動時,它們將檢查臟頁的年齡,如果它早于此值,它將異步寫入磁盤。由于在內(nèi)存中保存臟頁是不安全的,這也是防止數(shù)據(jù)丟失的一種保護措施。
vm.dirty_writeback_centisecs是 pdflush/flush/kdmflush 進程喚醒并檢查是否需要完成工作的頻率。?
您還可以在 /proc/vmstat 中查看有關頁面緩存的統(tǒng)計信息:
就我而言,我有 878 個臟頁等待寫入磁盤。
方法 1:減少緩存
與計算機世界中的大多數(shù)事情一樣,如何調(diào)整這些取決于您要做什么。在許多情況下,我們有快速磁盤子系統(tǒng),它們有自己的大型電池備份 NVRAM 緩存,因此將內(nèi)容保留在操作系統(tǒng)頁面緩存中是有風險的。讓我們嘗試更及時地將 I/O 發(fā)送到陣列,并減少我們的本地操作系統(tǒng)(借用服務行業(yè)的一句話)“陷入困境”的可能性。為此,我們通過向 /etc/sysctl.conf 添加新數(shù)字并使用 “sysctl –p” 重新加載來降低vm.dirty_background_ratio和vm.dirty_ratio:
這是虛擬機以及基于 Linux 的虛擬機管理程序的典型方法。我不建議將這些參數(shù)設置為零,因為某些后臺 I/O 可以將應用程序性能與磁盤陣列和 SAN 上短時間的高延遲(“峰值”)分離。
方法 2:增加緩存
在某些情況下,顯著提高緩存會對性能產(chǎn)生積極影響。在這些情況下,Linux 來賓上包含的數(shù)據(jù)并不重要并且可能會丟失,并且通常是應用程序重復或以可重復的突發(fā)方式寫入相同的文件。從理論上講,通過允許內(nèi)存中存在更多的臟頁,您將在緩存中一遍又一遍地重寫相同的塊,并且只需要每隔一段時間對實際磁盤進行一次寫入。為此,我們提高了參數(shù):
有時人們還會增加 vm.dirty_expire_centisecs 參數(shù)以允許緩存中更多時間。除了數(shù)據(jù)丟失的風險增加之外,如果緩存已滿并需要轉儲,還面臨長時間 I/O 暫停的風險,因為在大型 VM 上,緩存中會有大量數(shù)據(jù)。
方法3:雙向
在某些情況下,系統(tǒng)必須處理不頻繁的突發(fā)流量到慢速磁盤(整點頂部的批處理作業(yè)、午夜、寫入 Raspberry Pi 上的 SD 卡等)。在這種情況下,一種方法可能是允許將所有寫入 I/O 存放在緩存中,以便后臺刷新操作可以隨著時間的推移異步處理它:
在這里,后臺進程在達到 5% 的上限時將立即開始寫入,但系統(tǒng)不會強制同步 I/O,直到它達到 80% 滿。從那里,您只需調(diào)整系統(tǒng)RAM的大小,vm.dirty_ratio就可以消耗所有寫入的數(shù)據(jù)。同樣,磁盤上的數(shù)據(jù)一致性需要權衡,這轉化為數(shù)據(jù)風險。購買 UPS 并確保您可以在 UPS 斷電之前轉儲緩存。:)
無論您選擇哪種路線,您都應該始終收集硬數(shù)據(jù)來支持您的更改,并幫助您確定是正在改進還是使事情變得更糟。在這種情況下,您可以從許多不同的位置獲取數(shù)據(jù),包括應用程序本身、/proc/vmstat、/proc/meminfo、iostat、vmstat 以及 /proc/sys/vm 中的許多內(nèi)容。
可以看到這個臟頁配置也是一種藝術,需要根據(jù)實際情況下調(diào)整,注意vm.dirty_background_ratio配置的比例是緩存和空閑內(nèi)存的比例,vm.dirty_ratio是總內(nèi)存的比例。