文件緩存是一項重要的性能改進,在大多數情況下,讀緩存在絕大多數情況下是有益無害的(程序可以直接從RAM
中讀取數據)。寫緩存比較複雜,Linux
內核將磁盤寫入緩存,過段時間再異步將它們刷新到磁盤。這對加速磁盤I/O有很好的效果,但是當數據未寫入磁盤時,丟失數據的可能性會增加。
當然,也存在緩存被寫爆的情況。還可能出現一次性往磁盤寫入過多數據,以致使系統卡頓。這些卡頓是因爲系統認爲,緩存太大用異步的方式來不及把它們都寫進磁盤,於是切換到同步的方式寫入。
這些都是可控制的選項,根據工作負載和數據,你可以決定如何設置它們:
$ sysctl -a | grep dirty
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
vm.dirtytime_expire_seconds = 43200
vm.dirty_background_ratio
是內存可以填充髒數據的百分比。這些髒數據稍後會寫入磁盤,pdflush/flush/kdmflush
這些後臺進程會稍後清理髒數據。比如,我有32G內存,那麼有3.2G的髒數據可以待着內存裏,超過3.2G的話就會有後臺進程來清理。vm.dirty_ratio
是可以用髒數據填充的絕對最大系統內存量,當系統到達此點時,必須將所有髒數據提交到磁盤,同時所有新的I/O
塊都會被阻塞,直到髒數據被寫入磁盤。這通常是長I/O
卡頓的原因,但這也是保證內存中不會存在過量髒數據的保護機制。vm.dirty_background_bytes
和vm.dirty_bytes
是另一種指定這些參數的方法。如果設置_bytes
版本,則_ratio
版本將變爲0,反之亦然。vm.dirty_expire_centisecs
指定髒數據能存活的時間。在這裏它的值是30秒。當pdflush/flush/kdmflush
在運行的時候,他們會檢查是否有數據超過這個時限,如果有則會把它異步地寫到磁盤中。畢竟數據在內存裏待太久也會有丟失風險。vm.dirty_writeback_centisecs
指定多長時間pdflush/flush/kdmflush
這些進程會喚醒一次,然後檢查是否有緩存需要清理。
可以通過下面方式看內存中有多少髒數據:一共有106頁的髒數據
$ cat /proc/vmstat | egrep "dirty|writeback"
nr_dirty 106
nr_writeback 0
nr_writeback_temp 0
nr_dirty_threshold 3934012
nr_dirty_background_threshold 1964604
方法1:減少緩存
在很多情況下,我們有快速的磁盤子系統,它們有自己的大電池支持的NVRAM
緩存,所以將東西保存在系統頁面緩存中是有風險的。讓我們嘗試以更及時的方式向磁盤發送I/O
,並減少本地操作系統(借用服務行業的話)“陷入困境”的機會。爲了做到這一點,我們減小/etc/sysctl.conf
中vm.dirty_background_ratio
和vm.dirty_ratio
的數值,並執行sysctl -p
命令:
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
這是基於Linux
的虛擬機管理程序的典型方法。不建議將這些參數設置爲0,一些後臺I/O
可以很好地將應用程序性能與磁盤陣列在SAN(“峯值”)上的較短時間的較高延遲解耦。
方法2:增加緩存
在某些情況下,顯著提高緩存對性能有積極的影響。在這些情況下,Linux
客戶機上包含的數據不是關鍵的,可能會丟失,而且應用程序通常會重複或以可重複的方式寫入相同的文件。理論上,通過允許內存中存在更多髒頁,你將在緩存中一遍又一遍地重寫相同的塊,只需要每隔一段時間向實際磁盤寫一次。爲此,我們提出了以下參數:
vm.dirty_background_ratio = 50
vm.dirty_ratio = 80
有時候還會提高vm.dirty_expire_centisecs
這個參數的值,來允許髒數據更長時間地停留。除了增加數據丟失的風險之外,如果緩存已滿並需要同步,還會有長時間I/O卡頓的風險,因爲在大型虛擬機緩存中有大量數據。
方法3:增減都用
有時候系統需要應對突如其來的高峯數據,它可能會拖慢磁盤。比如說:每小時或者午夜進行批處理作業、在Raspberry Pi
上寫SD
卡等等。這種情況下,我們可以允許大量的寫I/O
存儲在緩存中,這樣後臺刷新操作就可以慢慢異步處理它:
vm.dirty_background_ratio = 5
vm.dirty_ratio = 80
這個時候,系統後臺進程在髒數據達到5%
時就開始異步清理,但在80%
之前系統不會強制同步寫磁盤。在此基礎上,你只需要調整RAM
和vm.dirty_ratio
大小以便能緩存所有的寫數據。當然,磁盤上的數據一致性也存在一定風險。
總結
無論你選擇哪種方式,都應該始終收集數據來支持你的更改,並幫助你確定是在改進還是變得更糟。我們可以從應用程序,/proc/vmstat
, /proc/meminfo
, iostat
, vmstat
以及/proc/sys/vm
裏面獲得大量有用信息。