Linux磁盤I/O(二):使用vm.dirty_ratio和vm.dirty_background_ratio優化磁盤性能

文件緩存是一項重要的性能改進,在大多數情況下,讀緩存在絕大多數情況下是有益無害的(程序可以直接從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_bytesvm.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.confvm.dirty_background_ratiovm.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%之前系統不會強制同步寫磁盤。在此基礎上,你只需要調整RAMvm.dirty_ratio大小以便能緩存所有的寫數據。當然,磁盤上的數據一致性也存在一定風險。

總結

無論你選擇哪種方式,都應該始終收集數據來支持你的更改,並幫助你確定是在改進還是變得更糟。我們可以從應用程序,/proc/vmstat, /proc/meminfo, iostat, vmstat 以及/proc/sys/vm裏面獲得大量有用信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章