web-dev-qa-db-ja.com

Linux上のZFS-L2ARCが読み取られていません

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


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

  • 最新のパッチを適用したCentOS7.5
  • Linux0.7.10上のZFS
  • 2GBのRAM

私はいくつかの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コマンドを再度実行すると、2番目の端末でzpool iostat -v 5を監視していました。

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

              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_streamsl2arc_write_boostl2arc_write_maxなどの設定をいじって、奇数の高い数値に設定しました。しかし、何も変わりませんでした。

変更後

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

読み取りはL2ARCから提供されます。再びdd if=/tank/testfile of=/dev/null bs=512を実行し、2番目の端末で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のサイズが大きすぎる可能性があることも読みました。しかし、そのトピックについて私が見つけたスレッドは、パフォーマンスの問題またはL1ARCを台無しにするL2ARCのスペースマップに言及していました。
ここではパフォーマンスは私の問題ではありません。私が知る限り、L2ARCのスペースマップもそれほど大きくありません。

[root@Host ~]# grep hdr /proc/spl/kstat/zfs/arcstats 
hdr_size                        4    279712
l2_hdr_size                     4    319488

すでに述べたように、それが意図した動作なのか、それとも何かが足りないのかはわかりません。

2
Thomas

したがって、このトピック、主に この投稿 を読んだ後、これがZFSのデフォルトの動作であるようです。

何が起こるかというと、ファイルは読み取られた後にL1ARCに送られ、アクセスされたブロックのためにL2ARCに入れられたと見なされます。
ファイルの2回目の読み取りで、ZFSはファイルのプリフェッチを実行します。これにより、ファイルのブロックはL2ARCに格納されますが、L2ARCはバイパスされます。

zfs_prefetch_disable=1を使用してプリフェッチを完全に無効にするか、l2arc_noprefetch=0を使用してL2ARCでプリフェッチを実行するようにZFSに指示することにより、読み取りはL2ARCにあるファイルのブロックを利用します。
これは、読み取り中のファイルサイズと比較してL2ARCが十分に大きい場合に必要になることがあります。
しかし、metadatazfs set secondarycache=metadata tankでL2ARCに入れたいだけかもしれません。これにより、大きなファイルがL2ARCになり、読み取られなくなるのを防ぎます。これはL2ARCを台無しにするので、プリフェッチされていない小さなファイルのブロックと、L2ARCに保持したいメタデータを削除する可能性があります。

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

2
Thomas

この場合に発生するのは、ZFSがランダム/非ストリーミング読み取り用にL2ARC帯域幅を維持しようとしていることです。この場合、物理ディスクにアクセスするとパフォーマンスが低下します。ストリーミング読み取りは、機械式HDDから非常に適切に提供され、6/8以上のディスクを備えたプールは、シーケンシャル読み取りのSATAL2ARCデバイスよりもパフォーマンスが優れている可能性があります。また、中規模のzpool(つまり、24/48以上のディスク)では、十分にのシーケンシャルな実帯域幅が得られます。

見つけたように、L2ARCを変更して、ビクティムキャッシュと同様に動作させることができます(つまり、ARCから削除されたものをすべて保存します。L2ARCでブロックが見つかった場合は、メインプールにアクセスしようとしないでください)。一部の特定の設定では、これは良いことです。ただし、ZFSは、L2ARCの摩耗/使用を維持するように(正しく)設計されており、実際に使用されるブロックをキャッシュして、ランダム読み取りのパフォーマンスを向上させることができます。

1
shodanshok