Linux 上の ZFS - L2ARC が読み込まれない

Linux 上の ZFS - L2ARC が読み込まれない

今日、Linux 0.7.10 の最新の ZFS を使用して L2ARC のテストをいくつか行いました。L2ARC がデータでいっぱいになることは確認しましたが、デフォルトのモジュール設定では、L2ARC キャッシュにあるデータは変更されません。代わりに、データはメイン プールの vdev から読み取られます。0.7.9 でもこの動作を確認しましたが、これが想定される動作かどうかはわかりません。
想定される動作だとしても、読み取られないデータで L2ARC を台無しにするのは奇妙だと思います。


テスト インストールは VM です。

  • 最新パッチを適用した CentOS 7.5
  • Linux 0.7.10 上の ZFS
  • 2GBのRAM

ZFS 設定をいくつか行いました:

  • l2arc_headroom=1024l2arc_headroom=1024L2ARC人口の増加を加速させる

プールの作成方法とレイアウトは次のとおりです。実際の設定としては奇妙であることは承知していますが、これは 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 から読み取る準備ができました (前置きが長くてすみませんが、重要だと思ったので)。
そこで、コマンドを再度実行して、 2 番目のターミナルでdd if=/tank/testfile of=/dev/null bs=512確認しました。zpool iostat -v 5

驚いたことに、ファイルは L2ARC にあるにもかかわらず、L2ARC ではなく通常の vdevs から読み取られました。これはファイルシステム内の唯一のファイルであり、テスト中に他のアクティビティはアクティブになっていません。

              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_boostl2arc_write_max奇数に設定してみました。しかし、何も変わりませんでした。

変更後

  • l2arc_noprefetch=0(デフォルトは1)
  • またはzfs_prefetch_disable=1(デフォルトは0
  • 両方をデフォルトから切り替える

読み取りは L2ARC から提供されます。2番目のターミナルで再度実行しdd if=/tank/testfile of=/dev/null bs=512て監視し、L1ARC を削除します。zpool iostat -v 5

[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 に配置されると見なされます。
次に、ファイルの 2 回目の読み取り時に、ZFS はファイルのプリフェッチを実行し、ファイルのブロックが L2ARC に格納されているにもかかわらず、L2ARC をバイパスします。

でプリフェッチを完全に無効にするかzfs_prefetch_disable=1、 で ZFS に L2ARC でプリフェッチを行うように指示するとl2arc_noprefetch=0、読み取りでは L2ARC にあるファイルのブロックが使用されます。
これは、読み取り中のファイル サイズに比べて L2ARC が十分に大きい場合に望ましい場合があります。ただし、でのみ L2ARC に
配置することをお勧めします。これにより、大きなファイルが L2ARC に残って読み取られなくなるのを防ぐことができます。これは、metadatazfs set secondarycache=metadata tank甘やかすL2ARC では、プリフェッチされていない小さなファイルのブロックや、L2ARC に保持したいメタデータが削除される可能性があります。

ZFSに指示する方法が見つからない小さなファイルのみL2ARCにプリフェッチ候補をマージしない。そのため、今のところは、ファイルサイズとL2ARCサイズに応じてトレードオフを行う必要がある。ZoL
0.8.0リリースでは、異なるアプローチが利用可能であるようで、異なる割り当てクラス例えば、メタデータを高速SSDに置き、データブロックをSSD上に残すといったことが可能になる。遅い回転ディスク。それでも競合は残る小さなファイル大きなファイルL2ARC 用ですが、メタデータの高速アクセスの問題を解決します。

答え2

この場合、ZFSはランダム/非ストリーミング読み取り用にL2ARC帯域幅を確保しようとします。物理ディスクにアクセスするとパフォーマンスに大きな影響が出ます。ストリーミング読み取りは機械式HDDで十分に処理され、6/8以上のディスクを持つプールは、おそらくシーケンシャル読み取りのSATA L2ARCデバイスよりもパフォーマンスが優れています。また、中規模のzpool(つまり、24/48以上のディスク)は、多くの連続実帯域幅。

ご存知のとおり、L2ARC を変更して、被害者キャッシュに似た動作をさせることができます (つまり、ARC から追い出されたものはすべて保存し、L2ARC でブロックが見つかった場合は、メイン プールにアクセスしようとさえしません)。特定の設定では、これは良いことですが、ZFS は (正しく) L2ARC の消耗/使用を、実際に有利になる場所、つまり実際に使用されたブロックをキャッシュしてランダム読み取りのパフォーマンスを高速化できる場所のために保持するように設計されました。

関連情報