Сегодня я провел несколько тестов на L2ARC, используя последнюю версию ZFS для Linux 0.7.10. Я видел, что L2ARC заполняется данными, но с настройками модуля по умолчанию данные, находящиеся в кэше L2ARC, никогда не затрагиваются. Вместо этого данные считываются из vdev основного пула. Я также видел такое поведение в 0.7.9, и я не уверен, что это ожидаемое поведение.
Даже если это было бы ожидаемым поведением, я думаю, что странно портить L2ARC данными, которые никогда не читаются.
Тестовая установка - это ВМ:
Я сделал несколько настроек 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
Как уже упоминалось, я не уверен, является ли это предполагаемым поведением или я что-то упускаю.
Итак, после прочтения этой темы, в основном эта почта, похоже, это поведение 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 там, где это может быть действительно выгодно: кэшировать действительно используемые блоки для более быстрой производительности произвольного чтения.