今天我在 Linux 0.7.10 上使用最新的 ZFS 對 L2ARC 做了一些測試。我已經看到 L2ARC 被資料填滿,但使用預設模組設定時,駐留在 L2ARC 快取中的資料永遠不會被觸及。相反,資料是從主池的 vdev 讀取的。我也在 0.7.9 中看到了這種行為,我不確定這是否是預期的行為。
即使這是預期的行為,我認為用從未讀取的資料破壞 L2ARC 也是很奇怪的。
測試安裝是虛擬機器:
- CentOS 7.5 附有最新補丁
- Linux 0.7.10 上的 ZFS
- 2GB記憶體
我做了一些 ZFS 設定:
l2arc_headroom=1024
並l2arc_headroom=1024
加速 L2ARC 人口
這是池的創建方式和佈局。我知道這對於現實世界的設定來說相當奇怪,但這僅用於 L2ARC 測試。
[root@host ~]# zpool create tank raidz2 /dev/sda /dev/sdb /dev/sdc cache sdd -f
[root@host ~]# zpool list -v
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 2.95G 333K 2.95G - 0% 0% 1.00x ONLINE -
raidz2 2.95G 333K 2.95G - 0% 0%
sda - - - - - -
sdb - - - - - -
sdc - - - - - -
cache - - - - - -
sdd 1010M 512 1009M - 0% 0%
現在將一些資料寫入文件並查看設備使用情況。
[root@host ~]# dd if=/dev/urandom of=/tank/testfile bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 9.03607 s, 59.4 MB/s
[root@host ~]# zpool list -v
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 2.95G 1.50G 1.45G - 10% 50% 1.00x ONLINE -
raidz2 2.95G 1.50G 1.45G - 10% 50%
sda - - - - - -
sdb - - - - - -
sdc - - - - - -
cache - - - - - -
sdd 1010M 208M 801M - 0% 20%
好的,部分資料已移至 L2ARC,但不是全部。所以,多讀幾遍,讓它完全在L2ARC。
[root@host ~]# dd if=/tank/testfile of=/dev/null bs=512 # until L2ARC is populated with the 512MB testfile
[root@host ~]# zpool list -v
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 2.95G 1.50G 1.45G - 11% 50% 1.00x ONLINE -
raidz2 2.95G 1.50G 1.45G - 11% 50%
sda - - - - - -
sdb - - - - - -
sdc - - - - - -
cache - - - - - -
sdd 1010M 512M 498M - 0% 50%
好的,L2ARC 已填充並可供讀取。但首先需要擺脫 L1ARC。我做了以下操作,似乎有效。
[root@host ~]# echo $((64*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; echo $((1024*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; arc_summary.py -p1
------------------------------------------------------------------------
ZFS Subsystem Report Sun Sep 09 17:03:55 2018
ARC Summary: (HEALTHY)
Memory Throttle Count: 0
ARC Misc:
Deleted: 20
Mutex Misses: 0
Evict Skips: 1
ARC Size: 0.17% 1.75 MiB
Target Size: (Adaptive) 100.00% 1.00 GiB
Min Size (Hard Limit): 6.10% 62.48 MiB
Max Size (High Water): 16:1 1.00 GiB
ARC Size Breakdown:
Recently Used Cache Size: 96.06% 1.32 MiB
Frequently Used Cache Size: 3.94% 55.50 KiB
ARC Hash Breakdown:
Elements Max: 48
Elements Current: 100.00% 48
Collisions: 0
Chain Max: 0
Chains: 0
好的,現在我們準備閱讀 L2ARC(很抱歉前言很長,但我認為這很重要)。
因此,再次運行命令,我在第二個終端中dd if=/tank/testfile of=/dev/null bs=512
觀看。zpool iostat -v 5
令我驚訝的是,該檔案是從普通 vdev 而不是 L2ARC 讀取的,儘管該檔案位於 L2ARC 中。這是文件系統中唯一的文件,在我的測試期間沒有其他活動處於活動狀態。
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.50G 1.45G 736 55 91.9M 96.0K
raidz2 1.50G 1.45G 736 55 91.9M 96.0K
sda - - 247 18 30.9M 32.0K
sdb - - 238 18 29.8M 32.0K
sdc - - 250 18 31.2M 32.0K
cache - - - - - -
sdd 512M 498M 0 1 85.2K 1.10K
---------- ----- ----- ----- ----- ----- -----
然後我確實擺弄了一些設置,例如、 、 和zfetch_array_rd_sz
,zfetch_max_distance
將zfetch_max_streams
它們設置為奇數高數字。但一切都沒有改變。 l2arc_write_boost
l2arc_write_max
改變後
l2arc_noprefetch=0
(預設為1
)- 或
zfs_prefetch_disable=1
(預設為0
) - 將兩者都從預設值切換
讀取由 L2ARC 提供。再次在第二個終端機中運行dd if=/tank/testfile of=/dev/null bs=512
和觀看zpool iostat -v 5
並擺脫 L1ARC。
[root@host ~]# echo 0 > /sys/module/zfs/parameters/l2arc_noprefetch
[root@host ~]# echo $((64*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; echo $((1024*1024*1024)) > /sys/module/zfs/parameters/zfs_arc_max; sleep 5s; arc_summary.py -p1
...
[root@host ~]# dd if=/tank/testfile of=/dev/null bs=512
結果:
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.50G 1.45G 0 57 921 102K
raidz2 1.50G 1.45G 0 57 921 102K
sda - - 0 18 0 34.1K
sdb - - 0 18 0 34.1K
sdc - - 0 19 921 34.1K
cache - - - - - -
sdd 512M 497M 736 0 91.9M 1023
---------- ----- ----- ----- ----- ----- -----
現在從 L2ARC 讀取數據,但前提是切換上述模組參數。
我還讀到 L2ARC 的尺寸可能太大。但我發現有關該主題的線程提到了效能問題或 L2ARC 的空間映射破壞了 L1ARC。
效能不是我的問題,據我所知,L2ARC 的空間映射也沒有那麼大。
[root@host ~]# grep hdr /proc/spl/kstat/zfs/arcstats
hdr_size 4 279712
l2_hdr_size 4 319488
正如已經提到的,我不確定這是否是預期的行為,或者我是否遺漏了一些東西。
答案1
所以在閱讀這個主題後,主要是這個帖子,這似乎是 ZFS 的預設行為。
所發生的情況是,檔案在讀取後進入 L1ARC,並且由於區塊被訪問,因此被認為被放入 L2ARC。
現在,在第二次讀取檔案時,ZFS 正在對檔案進行預取,這會繞過 L2ARC,儘管檔案的區塊儲存在 L2ARC 中。
透過使用 完全停用預取zfs_prefetch_disable=1
或使用 告訴 ZFS 在 L2ARC 上進行預取l2arc_noprefetch=0
,讀取將利用駐留在 L2ARC 中的檔案區塊。
如果您的 L2ARC 與正在讀取的檔案大小相比足夠大,則可能需要這樣做。
但人們可能只想metadata
將zfs set secondarycache=metadata tank
.這可以防止大檔案最終出現在 L2ARC 中並且永遠不會被讀取。因為這會破壞L2ARC 並可能會驅逐未預取的較小文件區塊和您希望保留在 L2ARC 中的元資料。
我還沒有找到告訴 ZFS 放置的方法只有小文件到 L2ARC 中,並且不將預取候選合併到 L2ARC 中。因此,目前,根據檔案大小和 L2ARC 大小,必須做出權衡。
ZoL 0.8.0 版本中似乎提供了一種不同的方法,可以使用不同的方法分配類別並且應該可以將元資料放在快速 SSD 上,同時將資料塊保留在慢的旋轉盤。這仍然會留下爭論小文件與大文件對於L2ARC,但會解決元資料的快速存取問題。
答案2
在這種情況下,ZFS 會嘗試為隨機/非串流讀取保留 L2ARC 頻寬,而存取實體磁碟會對效能造成嚴重破壞。機械 HDD 可以很好地提供串流讀取,並且任何具有 6/8+ 磁碟的池在順序讀取方面可能會優於任何 SATA L2ARC 設備。任何中等大小的 zpool(即:24/48+ 磁碟)都會給出足夠的連續實際頻寬。
如您所發現的,您可以更改 L2ARC,使其行為更類似於受害者快取(即:儲存從 ARC 逐出的任何內容;如果在 L2ARC 上找到區塊,甚至不要嘗試存取主池)。在某些特定的設定上,這可能是一件好事;然而,ZFS 的架構(正確地)是為了保留 L2ARC 磨損/使用,以便在真正有利的地方:快取真正使用的區塊以獲得更快的隨機讀取效能。