Сегодня я провел несколько тестов на L2ARC с использованием последней версии ZFS на Linux 0.7.10. Я видел, что L2ARC заполняется данными, но с настройками модуля по умолчанию данные, находящиеся в кэше L2ARC, никогда не затрагиваются. Вместо этого данные считываются из vdev главного пула. Я также видел такое поведение в 0.7.9, и я не уверен, что это ожидаемое поведение.
Сегодня я провел несколько тестов на L2ARC с использованием последней версии ZFS для Linux 0.7.10. Я видел, что L2ARC заполняется данными, но с настройками модуля по умолчанию данные, находящиеся в кэше L2ARC, никогда не затрагиваются. Вместо этого данные считываются из vdev главного пула. Я также видел такое поведение в 0.7.9, и я не уверен, что это ожидаемое поведение.
Сегодня я провел несколько тестов на 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. Я сделал следующее,
Итак, снова запустив команду 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.
Снова запускаем 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.
Снова запускаем 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 достаточно велик по сравнению с размерами файлов, которые читаются.
Но можно было бы поместить только метаданные
в L2ARC с zfs, установленным вторичным кэшем = резервуар метаданных
. Это предотвращает попадание больших файлов в L2ARC и невозможность их чтения. Поскольку это испортит L2ARC и может вытеснить блоки файлов меньшего размера, которые не были предварительно загружены, и метаданные, которые вы хотите сохранить в L2ARC.
Я не нашел способа указать ZFS помещать только небольшие файлы в L2ARC и не объединять кандидатов предварительной выборки в L2ARC. Так что на данный момент, в зависимости от размеров файлов и размера L2ARC, приходится идти на компромисс.
Похоже, что в версии ZoL 0.8.0 доступен другой подход, где можно использовать разные классы распределения и сделать возможным, например, размещайте метаданные на быстрых SSD, а блоки данных оставляйте на медленных вращающихся дисках. Это по-прежнему оставит конкуренцию маленьких файлов против больших файлов для L2ARC, но решит проблему быстрого доступа к метаданным.
В этом случае происходит то, что ZFS пытается сохранить полосу пропускания L2ARC для случайных / непотоковых операций чтения, когда попадание в физические диски может нанести ущерб производительности. Потоковое чтение достаточно хорошо обслуживается с механических жестких дисков, и любой пул с дисками 6/8 +, вероятно, превзойдет любое устройство SATA L2ARC для последовательного чтения. И любой zpool среднего размера (например, 24/48 + дисков) даст достаточную последовательную реальную полосу пропускания.
Как вы обнаружили, вы можете изменить L2ARC, чтобы он вел себя как кэш жертвы ( то есть:хранить все, что выселено из ARC; если блок обнаружен на L2ARC, даже не пытайтесь получить доступ к основному пулу). В некоторых случаях это может быть хорошо; однако ZFS была (правильно) спроектирована так, чтобы сохранить износ / использование L2ARC там, где это может быть действительно выгодно: кэшировать действительно использованные блоки для более быстрой производительности произвольного чтения.