Linux 上的 ZFS - L2ARC 未讀取

Linux 上的 ZFS - L2ARC 未讀取

今天我在 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=1024l2arc_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_szzfetch_max_distancezfetch_max_streams它們設置為奇數高數字。但一切都沒有改變。 l2arc_write_boostl2arc_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 與正在讀取的檔案大小相比足夠大,則可能需要這樣做。
但人們可能只想metadatazfs 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 磨損/使用,以便在真正有利的地方:快取真正使用的區塊以獲得更快的隨機讀取效能。

相關內容