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

Подготовка кэша ZFS L2ARC в Solaris 11.3

Есть ли хороший способ настроить кеш ZFS L2ARC в Solaris 11.3?

L2ARC предназначен для игнорирования блоков, которые были последовательно прочитаны из файла. Это имеет смысл для непрерывной работы, но затрудняет загрузку кеша для начального прогрева или тестирования.

Кроме того, сильно фрагментированные файлы могут значительно выиграть от последовательного чтения, кэшируемого в L2ARC (поскольку на диске они являются произвольными чтениями), но с текущей эвристикой эти файлы никогда не будут кэшироваться, даже если L2ARC заполнен только на 10%.

В предыдущих выпусках Solaris 10 и 11 я успешно использовал dd дважды подряд по каждому файлу. Первый dd читаем файл в ARC, а второй dd казалось, что буферы щекотали, поэтому они получили право на кэширование L2ARC. Похоже, что тот же метод не работает в Solaris 11.3.

Я подтвердил, что файлы, о которых идет речь, имеют размер записи 8k, и я попытался установить zfs_prefetch_disable но это не повлияло на поведение L2ARC ОБНОВИТЬ: zfs_prefetch_disable оказывается важным, см. мой ответ ниже.

Если нет хорошего способа сделать это, я бы подумал об использовании инструмента, который генерирует случайное чтение более 100% файла. Это может стоить времени, учитывая, что кеш теперь является постоянным в 11.3. Существуют ли подобные инструменты?

Немного поэкспериментировав, я нашел четыре возможных решения.

При каждом подходе вам необходимо выполнить шаги, а затем продолжить чтение дополнительных данных, чтобы заполнить кеш ZFS ARC и запустить поток из ARC в L2ARC. Обратите внимание: если данные уже кэшированы в памяти или если сжатый размер на диске каждого блока превышает 32 КБ, эти методы обычно ничего не делают.

1. Установите задокументированный флаг ядра. zfs_prefetch_disable

L2ARC по умолчанию отказывается кэшировать данные, которые были предварительно загружены автоматически. Мы можем обойти это, отключив функцию предварительной выборки ZFS. В любом случае этот флаг часто бывает хорошей идеей для рабочих нагрузок базы данных.

echo "zfs_prefetch_disable/W0t1" | mdb -kw

..или, чтобы установить его постоянно, добавьте в /etc/system:

set zfs:zfs_prefetch_disable = 1

Теперь, когда файлы читаются с помощью dd, они по-прежнему будут иметь право на L2ARC.

С функциональной точки зрения это изменение также улучшает поведение чтения в моем тестировании. Обычно, когда ZFS обнаруживает последовательное чтение, она уравновешивает пропускную способность между vdevs данных и vdevs кэша вместо простого чтения из кеша - но это снижает производительность, если устройства кеширования имеют значительно меньшую задержку или более высокую пропускную способность, чем устройства данных.

2. Перепишите данные.

Поскольку данные записываются в файловую систему ZFS, они кэшируются в ARC и (если они соответствуют критериям размера блока) могут быть отправлены в L2ARC. Переписать данные не всегда просто, но некоторые приложения и базы данных могут это делать в реальном времени, например посредством зеркалирования файлов на уровне приложения или перемещения файлов данных.

Проблемы:

  • Не всегда возможно в зависимости от приложения.
  • Занимает дополнительное место, если используются снимки.
  • (Но с другой стороны, полученные файлы дефрагментируются.)

3. Снимите флажок недокументированного ядра. l2arc_noprefetch

Это основано на чтении исходного кода OpenSolaris и, без сомнения, полностью не поддерживается. Используйте на свой риск.

  1. Отключить l2arc_noprefetch флаг:

    echo "l2arc_noprefetch/W0" | mdb -kw
    

    Данные, считываемые в ARC, когда этот флаг отключен, будут иметь право на L2ARC, даже если это последовательное чтение (пока блоки на диске не превышают 32 КБ).

  2. Прочтите файл с диска:

    dd if=filename.bin of=/dev/null bs=1024k
    
  3. Повторно включите l2arc_noprefetch флаг:

    echo "l2arc_noprefetch/W1" | mdb -kw
    

4. Прочтите данные случайным образом.

Я написал сценарий Perl для псевдослучайного чтения файлов кусками по 8 КБ (на основе порядка хэша Perl). Он также может работать с большими кусками, но я еще не тестировал это.

#!/usr/bin/perl -W

my $BLOCK_SIZE = 8*2**10;
my $MAX_ERRS = 5;

foreach my $file (@ARGV) {
        print "Reading $file...\n";
        my $size;
        unless($size = (stat($file))[7]) {print STDERR "Unable to stat file $file.\n"; next; }
        unless(open(FILE, "<$file")) {print STDERR "Unable to open file $file.\n"; next; }
        my $buf;
        my %blocks;
        for(my $i=0;$i<$size/$BLOCK_SIZE;$i++) { $blocks{"$i"} = 0; }
        my $errs = 0;
        foreach my $block (keys %blocks) {
                unless(sysseek(FILE, $block*$BLOCK_SIZE, 0) && sysread(FILE, $buf, $BLOCK_SIZE)) {
                        print STDERR "Error reading $BLOCK_SIZE bytes from offset " . $block * $BLOCK_SIZE . "\n";
                        if(++$errs == $MAX_ERRS) { print STDERR "Giving up on this file.\n"; last; }
                        next;
                }
        }
        close(FILE);
}

Проблемы:

  • Это занимает много времени и создает большую нагрузку на диск.

Остающиеся проблемы

  • Вышеупомянутые методы переносят данные в основную память, подходящую для подачи в L2ARC, но они не запускают поток. Единственный известный мне способ запустить запись в L2ARC - это продолжить чтение данных, чтобы оказать давление на ARC.
  • В Solaris 11.3 с SRU 1.3.9.4.0 L2ARC редко достигает ожидаемого уровня. В evict_l2_eligible kstat увеличивается, даже когда устройства SSD не находятся под нагрузкой, указывая на то, что данные удаляются. Эта оставшаяся часть некэшированных данных оказывает непропорционально большое влияние на производительность.

Я бы предложил использовать реальную рабочую нагрузку и отслеживать результат с помощью arcstat.

Что-то вроде:

arcstat.py -f "time,read,l2read,hit%,hits,miss%,miss,l2hit%,l2miss%,arcsz,c,l2size" 1

Я не думаю, что кеш нужно "заливать". Если имеющаяся у вас рабочая нагрузка не заполняет кэш естественным образом, то это не репрезентативная рабочая нагрузка для тестирования, верно?

Возможно, у вас есть исключительный вариант использования (Какой у вас размер набора данных, размер ARC и размер рабочего набора?), но в целом фокус на L2ARC переоценивается.