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