Назад | Перейти на главную страницу

ZFS на linux - L2ARC не читается

Сегодня я провел несколько тестов на L2ARC, используя последнюю версию ZFS для Linux 0.7.10. Я видел, что L2ARC заполняется данными, но с настройками модуля по умолчанию данные, находящиеся в кэше L2ARC, никогда не затрагиваются. Вместо этого данные считываются из vdev основного пула. Я также видел такое поведение в 0.7.9, и я не уверен, что это ожидаемое поведение.
Даже если это было бы ожидаемым поведением, я думаю, что странно портить L2ARC данными, которые никогда не читаются.


Тестовая установка - это ВМ:

Я сделал несколько настроек ZFS:


Вот как создавался пул и его планировка. Я знаю, что это довольно странно для реальной установки, но это было предназначено только для тестирования 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. Снова бег 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

Как уже упоминалось, я не уверен, является ли это предполагаемым поведением или я что-то упускаю.

Итак, после прочтения этой темы, в основном эта почта, похоже, это поведение ZFS по умолчанию.

Что происходит, так это то, что файл попадает в L1ARC после чтения, и из-за доступа к блокам он считается помещенным в L2ARC.
Теперь при втором чтении файла ZFS выполняет предварительную выборку файла, минуя L2ARC, хотя блоки файла хранятся в L2ARC.

Полностью отключив предварительную выборку с помощью zfs_prefetch_disable=1 или скажите ZFS выполнить предварительную выборку на L2ARC с помощью l2arc_noprefetch=0, при чтении будут использоваться блоки файла, находящиеся в L2ARC.
Это может быть желательно, если ваш L2ARC достаточно велик по сравнению с размерами файлов, которые читаются.
Но можно было бы только поставить metadata в L2ARC с zfs set secondarycache=metadata tank. Это предотвращает попадание больших файлов в L2ARC и невозможность их чтения. Поскольку это будет испортить L2ARC и может удалить блоки меньших файлов, которые не были предварительно загружены, и метаданные, которые вы хотите сохранить в L2ARC.

Я не нашел способа сказать ZFS, чтобы только маленькие файлы в L2ARC и не объединять кандидатов предварительной выборки в L2ARC. Итак, на данный момент, в зависимости от размеров файлов и размера L2ARC, нужно идти на компромисс.
Похоже, что в версии ZoL 0.8.0 доступен другой подход, где можно использовать разные Классы размещения и должен позволять, например, поместите свои метаданные на быстрые SSD, оставив блоки данных на медленный вращающиеся диски. Это все равно оставит спор небольшие файлы vs. большие файлы для L2ARC, но решит проблему быстрого доступа к метаданным.

В этом случае происходит то, что ZFS пытается сохранить полосу пропускания L2ARC для случайного / не потокового чтения, когда попадание на физические диски нанесет ущерб производительности. Потоковое чтение достаточно хорошо обслуживается с механических жестких дисков, и любой пул с дисками 6/8 +, вероятно, превзойдет любое устройство SATA L2ARC для последовательного чтения. И любой zpool среднего размера (например, 24/48 + диски) даст много последовательной реальной пропускной способности.

Как вы обнаружили, вы можете изменить L2ARC, чтобы позволить ему вести себя более похоже на кеш-память жертвы (то есть: хранить все, что исключено из ARC; если блок обнаружен в L2ARC, даже не пытайтесь получить доступ к основному пулу). В некоторых случаях это может быть хорошо; однако ZFS была (правильно) спроектирована так, чтобы сохранить износ / использование L2ARC там, где это может быть действительно выгодно: кэшировать действительно используемые блоки для более быстрой производительности произвольного чтения.