DataLife Engine > Система > Тюнинг ZFS на FreeBSD

Тюнинг ZFS на FreeBSD


18-11-2012. Разместил: synergix Тюнинг ZFS на FreeBSDZFS это современная 128-битная файловая система, основанная на модели "копирование-при-записи" (copy-on-write). Разработанная в проекте OpenSolaris, впервые была представлена в FreeBSD в 2008 году. ZFS обладает множеством современных характеристик, таких как интегрированный менеджер томов с зеркалированием и возможностями RAID, контрольные суммы данных, сжатие данных, записываемые снэпшоты, которые могут быть перемещены между системами и многое другое.

Что вы будете знать…
• Как оптимизировать ZFS для различных приложений и рабочих нагрузок
• Как измерить и оценить эффективность кэша ZFS

Что вы должны знать…
• Базовые навыки администрирования ZFS системы
• Навыки работы с опциями sysctl(8) и loader(8)

В этой статье будут обсуждаться параметры настроек ZFS, включая sysctl(2) и приведены примеры оценки производительности и эффективности ZFS. Материал статьи предназначен для пользователей FreeBSD, начиная с релизов 8.3 и 9.0 с ZFS версии 28.
В ZFS доступно множество настроек, изменяемых с помощью команды sysctl(8). Кроме того, ZFS является частью OpenSolaris kstat(kernel statistics facility) фреймворка, также доступного и в FreeBSD, который предоставляет доступ к необработанным данные различных счетчиков. Существует более 60 vfs.zfs и более 80 kstat.zfs настроек, предоставляющих доступ к разным счетчикам ядра, состояния и калибровочным переменным. К сожалению, на данный момент доступно небольшое количество инструментов обработки этой информации.
Первый раздел этой статьи ознакомит Вас с настройкой предвыборки и кэша ZFS, используя такие инструменты оценки и обработки статистики как zfs-stats и zfs-mon. Также будут даны советы по использованию ZFS на web-серверах, серверах баз данных и файловых серверах, приведены рекомендации для дисков с размером сектора 4кБ.

Основные советы по тюнингу

Оперативная память

Производительность ZFS сильно зависит от объема доступной оперативной памяти, особенно если использовать дедупликацию данных. Во многих случаях бывает достаточно простого увеличения оперативной памяти системы. Рекомендуется использовать минимум 1 Gb RAM, для высоконагруженных систем не менее 8 GB. Для серверов, использующих коррекцию ошибок ECC памяти это будет весомым преимуществом.

Время доступа

На FreeBSD каждый раз, когда происходит обращение к файлу, обновляется время доступа (atime). На сервере, работающим с большим количеством файлов, это может спровоцировать увеличение количества запросов на перезапись. В этом случае вы захотите отключить atime (время доступа) для используемых данных или для всего пула. Отключение atime может улучшить производительность всех типов приложений сереверов.

#zfs set atime=off dataset

Сжатие данных

Использование сжатия данных в ZFS позволяет экономить дисковое пространство, но увеличивает нагрузку на CPU и снижает отзывчивость системы в целом. С другой стороны, включение сжатия (главным образом LZJB) может ускорить операции с данными, особенно на медленных носителях. Например, процессорные затраты при сжатии gzip существенно больше, чем при использовании сжатия LZJB. Поэтому я рекомендую использовать сжатие данных только в том случае, если имеются хорошо сжимающиеся данные или мало свободного места на дисках. Например, к таким данным относятся логи. Если у вас есть быстрый накопитель с достаточным пространством и нужна максимальная производительность, отключите сжатие данных.

# zfs set compression=[on|off] dataset

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

# zfs set dedup=on

Увидеть подробно информацию о дедупликации пула можно используя команду zdb:

# zdb –D pool

или

# zdb –DD pool

В случае необходимости можно сымитировать включение дедупликации пула для оценки в приросте дискового пространства. Если в результате отношение будет более чем 2.00, рекомендуется включить дедупликацию на пуле.

# zdb –S pool

Ппреимущества и стоимость ZFS дедупликации обсуждается в блоге Константина Гонзалеса (http://constantin.glez.de/blog/2011/07/zfs-dedupe-or-notdedupe)

Потоки ввода/вывода ZFS

Для ускорения потоков ввода/вывода ZFS рекомендуется использовать буферизацию. Я лично рекомендую утилиту mbuffer, доступную в портах FreeBSD как misc/mbuffer. mbuffer позволяет вам буферизовать локальные потоки (через трубу) и способную посылать поток по сети.

# zfs send tank/a@s1 | mbuffer –m 128M | zfs receive tank2/a@s1

Тюнинг кэша и предвыборки

Адаптивная замена кэша

Одна из главных настраиваемых возможностей ZFS - это основанный на памяти Адаптивный Замещающий Кэш (Adaptive Replacement Cache). Данные и метаданные, считанные блоками с дискового устройства, сохраняются в кэше ARC, что приводит к существенному ускорений операций ZFS и данная опция включена по умолчанию.

Основные опции ARC настраиваются через loader(8):

vfs.zfs.arc_min: Минимальный размер ARC (в байтах)
vfs.zfs.arc_max: Максимальный размер ARC (в байтах)
vfs.zfs.arc_meta_limit: Лимит метаданных ARC (в байтах)

Данные настройки контролируют размер лимитов кэша ARC в вашей системе. В зависимости от доступного размера оперативной памяти, минимальные и максимальные значения лимитов ARC автоматически изменяются при загрузке системы. Значения по умолчанию:

vfs.zfs.arc_max: При размере RAM меньше 1 Гб(или соответствует vm.kmem_size)
vfs.zfs.arc_meta_limit: 1/4 от arc_max
vfs.zfs.arc_min: половина arc_meta_limit (равнозначно 1/8 arc_max)

Значения arc_min и arc_max имеют заданный в коде минимум 16MB. Значения arc_meta_limit и arc_min не могут быть выше чем arc_max. Для отображения текущего размера ARC(в байтах), выполните:

# sysctl.kstat.zfs.misc.arcstats.size

Значения по умолчанию являются предпочтительными для большинства пользователей, но в случае, если для ваших задач потребуется больше оперативной памяти, ARC автоматически освобождает ее, снижая ее потребление до arc_min. Используйте изменение значения vfs.zfs.arc_max только в случае необходимости выделения гарантированного объема памяти. Также может возникнуть ситуация с заполнением кеша метаданных (в случае наличия большого количества маленьких файлов) и понижением производительности ARC. В данном случае вы можете увеличить значение arc_meta_limit(через loader(8)). Также следует учесть, что значение arc_min должно составлять половину от arc_meta_limit в случае его изменения.

Для вывода значений метаданных ARC и его лимита запустите:

# sysctl vfs.zfs.arc_meta_used

# sysctl vfs.zfs.arc_meta_limit

По умолчанию, ARC включен на всех наборах данных. Если у вас наблюдаются проблемы с производительностью по причине заполненности или неэфффективности кэша ARC, то можно либо отключить ARC полностью либо кэшировать только метаданные на некритичных наборах данных.

# zfs set primarycache=[all|metadata|none] dataset

Для отображения времени работы и реального времени активности ARC и его эффективности, пожалуйста обратитесь к разделу этой статьи zfs-stats и zfs-mon.

Адаптивный Заменяющий Кэш второго уровня(L2ARC)

Быстрое блочное устройство (например, SSD диски) могут быть использованы расширения ARC кэша определенных пулов ZFS. Этот кэш называется Адаптивный Заменяющий Кэш второго уровня (L2ARC). Этот тип кэша в основном оптимален на одну запись и множественные чтения сценариев хранилища, например, статический контент сайтов в Интернете с изображениями и видео файлами, которые не перезаписываются (но общее используемое пространство продолжает расти). Для этого необходимы устройства с быстрым кэшем (рекомендуется использование быстрых SSD дисков). В отличии от обычного кэша ARC, общего для всей системы, L2ARC кэширует данные только указанных устройств.
Размер L2ARC кэша от доступного дискового пространства кэширующего устройства. Для добавления/удаления кеша в пул вы можете использовать следующие команды:

# zfs add pool cache device

# zfs remove pool device

Ниже приведены несколько параметров настройки L2ARC:

vfs.zfs.l2arc_feed_again: turbo warmup
vfs.zfs.l2arc_feed_secs: interval secs
vfs.zfs.l2arc_write_max: max write size
vfs.zfs.l2arc_write_boost: extra write during warmup
vfs.zfs.l2arc_headroom: number of dev writes to precache
vfs.zfs.l2arc_noprefetch: don’t cache prefetch bufs

Первый параметр выше включает или выключает L2ARC турбо режим warm-up. Турбо режим warm-up это фаза происходящая между загрузкой системы и получением кэшем L2ARC состояния “warm” (= первое получение данных кешем L2ARC). В течение этой фазы ARC записывает вычисленное как l2arc_write_max + l2arc_write_boost в байтах каждые l2arc_feed_secs секунд. Если фаза warm-up выключена или L2ARC уже в состоянии warm, данные записываются на максимальной скорости l2arc_write_max байт каждые l2arc_feed_secs секунд. Настройки по умолчанию при включенном warm-up l2arc_feed_secs установлен в одну секунду, значения l2arc_write_max и l2arc_write_boost установлен в 8Мб. L2arc_headroom параметры определяются количеством L2ARC записей, которые были предкешированы. Значение по умолчанию 2.
Цель этих настроек уберечь от большого количества перезаписи SSD устройств, так как они имеют ограниченное число циклов перезаписи. Эти настройки определялись в 2008 и современные SSD диски легко могут работать на больших скоростях.
Рекомендуется удвоить значения vfs.zfs.l2arc_write_max и vfs.zfs.l2arc_write_boost, выставив через loader(8) значения в 16 MB.

По умолчанию значение l2arc_noprefetch выставлено в 0 и соответствует отключению кэширования при последовательном чтении. Включение данной опции (значение 1) в большинстве случаев увеличивает производительность L2ARC, например для потокового видео или отдачи веб-сервером больших файлов.

# sysctl vfs.zfs.l2arc_noprefetch=1

По умолчанию L2ARC включен для всех наборов данных. Вы можете либо отключить L2ARC полностью либо кэшировать только метаданные наборов данных:

# zfs set secondarycache=[all|metadata|none] dataset

Для отображения времени работы и реального времени активности L2ARC и его эффективности, пожалуйста обратитесь к разделу этой статьи zfs-stats и zfs-mon.

Целевой журнал ZFS (ZFS Intent Log)

ZIL предоставляет приложениям возможность узнать, что данные, ими изменённые, находятся на стабильном хранилище, по возврату из системного вызова fsync(2). Целевой журнал хранит записи этих системных вызовов, они воспроизводятся заново, если произошёл сбой питания или критическая ошибка, при которой основной пул не подтвердил их выполнение.
По умолчанию ZIL занимает маленькое количество дискового пространства в каждом пуле ZFS. Он может быть использован для ускорения синхронизации записи путем записи лога на несколько устройств (включая зеркалированные устройства). Для этих целей рекомендуется использовать быстрые SSD диски.

Чтобы добавить или удалить устройство журнала в пул, используйте следующие команды:

# zpool add tank log device

# zpool remove tank device

Синхронизацию лога можно настроить для каждого набора данных:

# zfs set sync=[standard|always|disabled] dataset

В случае отключения синхронизации, данные записываются только периодически (TXG – Транзакция Группы). Это увеличивает производительность записи, но вносит риск потери данных при сбоях в ядре, аппаратном сбое или отключении питания и имеет смысл только для временных или быстро изменяющихся данных. Использование опции always вносит существенные потери в производительности.

Предварительная загрузка уровня файлов (zfetch)

Механизм предварительной загрузки файлов реализован в ZFS и называется zfetch. Это механизм анализирует шаблоны чтения файлов и пытается предсказать результаты следующего чтения для сокращения времени отклика приложений. В некоторых случаях, zfetch может интенсивно нагружать процессор и иметь предел масштабируемости. Эффективная предварительная загрузка может быть показана и отображена утилитами zfs-status, zfs-mon(обсуждается ниже). Zfetch включена по умолчанию (но отключена на системах с меньше чем 4 GB ОЗУ) и вы можете отключить или заново включить zfetch установив значения 1 и 0 соответственно в загрузчике:

vfs.zfs.prefetch_disable: Disable prefetch

Предварительная загрузка уровня устройств (vdev prefetch)

Механизм предварительной загрузки vdev заранее считывает данные о пуле устройств. В настоящий момент, предварительная загрузка vdev отключена по умолчанию. Длительное применение показало, что это неэффективно в большинстве случаев и потребление памяти пропорционально количеству vdev в системе.
Имеются отзывы пользователей, у которых при заново включенном vdev кэше значительно ускоряются операции скраббинга (scrubbing) и на raid-z (или систем с медленными дисками) за счет сокращения времени поиска на диске и ускорения чтения метаданных.
Предварительная загрузка vdev в основном настраивается через параметр vfs.zfs.vdev.cache.size в loader(8) и содержит значение размера кэша в байтах, но отключено по умолчанию путем установки 0. Для опытных пользователей доступны также и другие параметры vfs.zfs.vdev.cache

# sysctl -d vfs.zfs.vdev.cache

Для включения предварительной загрузки vdev установите vfs.zfs.vdev.cache в loader.conf(5) в желаемый размер в байтах отличный от нуля, значение по умолчанию имеет значение в 10MB:

vfs.zfs.vdev.cache.size=10485760

zfs-stats и zfs-mon: инструменты статистики ZFS

Параметр kstat.zfs sysctl(8) предоставляет доступ к значениям множества счетчиков ZFS. Они содержат необработанные "сырые" данные и для более удобного представления должны быть обработаны. Perl скрипты zfs-stats и zfs-mon обрабатывают эти данные и предоставляют вывод в удобном для человека виде. Zfs-stats утилита основана на arc_summary.pl Бена Роквуда и включает изменения сделанные Джейсоном Хелленталем и мной. Оба эти инструмента доступны в портах FreeBSD в sysutils/zfs-stats.
zfs-stats суммирует и/или усредняет значения счетчиков и выводит их значения только после того, как будет загружена система:

Листинг 1. Пример вывода zfs-stats
ARC Size: 79.89% 25.57 GiB
Target Size: (Adaptive) 79.89% 25.57 GiB
Min Size (Hard Limit): 12.50% 4.00 GiB
Max Size (High Water): 8:1 32.00 GiB
ARC Efficiency: 1.25b
Cache Hit Ratio: 90.52% 1.13b
Cache Miss Ratio: 9.48% 118.08m
Actual Hit Ratio: 84.54% 1.05b
Data Demand Efficiency: 95.45% 356.90m
Data Prefetch Efficiency: 40.64% 11.36m
L2 ARC Breakdown: 118.18m
Hit Ratio: 62.87% 74.29m
Miss Ratio: 37.13% 43.89m
Feeds: 849.64k
File-Level Prefetch: (HEALTHY)
DMU Efficiency: 28.09b
Hit Ratio: 88.54% 24.87b
Miss Ratio: 11.46% 3.22b

Текущие("моментальные") значения не несут информации о действительной производительности системы. Для отображения кэша эффективности в реальном времени я написал утилиту zfs-mon. Она отслеживает ARC, L2ARC и zfetch в реальном времени и выводит 10 секундные, 60 секундные и усредненные значения в секунду (с момента запуска программы).
Пример вывода "zfs-mon –a" после сбора 120 секундных данных: Листинг 2.

ZFS real-time cache activity monitor
Seconds elapsed: 120
Cache hits and misses:
1s 10s 60s tot
ARC hits: 259 431 418 466
ARC misses: 51 40 49 52
ARC demand data hits: 223 417 390 437
ARC demand data misses: 36 20 17 16
ARC demand metadata hits: 36 11 25 25
ARC demand metadata misses: 15 19 21 25
ARC prefetch data hits: 0 4 3 4
ARC prefetch data misses: 0 1 10 8
ARC prefetch metadata hits: 0 0 0 0
ARC prefetch metadata misses: 0 0 1 3
L2ARC hits: 47 34 40 37
L2ARC misses: 4 5 9 15
ZFETCH hits: 47903 47294 48155 47138
ZFETCH misses: 272 449 1147 3593
Cache efficiency percentage:
10s 60s tot
ARC: 91.51 89.51 89.96
ARC demand data: 95.42 95.82 96.47
ARC prefetch data: 80.00 23.08 33.33
ARC prefetch metadata: 0.00 0.00 0.00
L2ARC: 87.18 81.63 71.15
ZFETCH: 99.06 97.67 92.92

Поскольку L2ARC кэш используется, когда данные не помещаются в кеш ARC, то общая эффективность кэша вычисляется как:

[ARC efficiency] + (100-[ARC efficiency])*([L2ARC efficiency]/100).

Результат для примера выше:

89,96 + (100-89,96)*(71,15/100) = 97,10.

Интерпретация вывода zfs-stats и zfs-mon

Вывод zfs-stats и zfs-mon может помочь вам в выявлении "бутылочного горлышка" и оптимальной настройки значений по умолчанию. Основное предназначение - отображение использования и эффективности кэшей. Значение в 100% означает что все данные считываются с кеша, 0% - что данные берутся с дисков. В моем случае, эффективность выше 80% является хорошей, а выше 90% - отличной. Помните, что L2ARC требует некоторого времени для эффективной работы и повышения эффективности общего кеша. При использовании утилиты zfs-mon, попробуйте собрать данные за длительный период времени и посмотрите колонку tot.

Приведу несколько советов:

Если вы выявили неэффективный кэш данных ARC:
• Если у вас лимитированный размер ARC, увеличьте или удалите лимит
• Отключите ARC для некоторых наборов данных
• Рассмотрите снижение лимита метаданных ARC
• Добавьте больше RAM в вашу систему
• Учтите использование дополнительного L2ARC кэширующего устроства

Неэффективный кэш метаданных ARC:

• Подумайте о повышение лимита метаданных ARC
• Добавьте больше RAM в вашу систему

Неэффективный кэш L2ARC:

• Учитывайте, что его эффективность его зависит от типа чтения
• Если ваш ARC уже очень эффективен, L2ARC может лишь в определенных ситуация увеличить его эффективность
• Если ваш ARC неэффективен, рассмотрите увеличение размеров RAM и L2ARC кеша
• В некоторых случаях эффективность в 30-40% L2ARC уже считается приемлемой

Неэффективность ZFETCH:

• Отключите zfetch

Неэффективность предварительной загрузки vdev:

• Рассмотрите отключение предварительной загрузки vdev
• Scrub (очистка) и resilver могут работать значительно быстрее в случае использования
• Настройте дополнительные опции предварительной загрузки vdev (только для экспертов)

Тюнинг ZFS для приложений

Вебсерверы

Использование на FreeBSD показывает, что следует отключать sendfile и mmap, если данные хранятся на веб-сервере с ZFS. Иначе ваши данные могут кэшироваться в системную память дважды, что снижает размер доступной памяти.

Вот примеры конфигурационных опций для популярных веб-серверов:

Apache

EnableMMAP Off
EnableSendfile Off

Nginx

Sendfile Off

Lighttpsd

server.network-backend = “writev”

Серверы баз данных

Для баз данных, таких как PostgreSQL и MySQL, пользователям рекомендуется хранить их в наборах данных, созданных с отличными по умолчанию размером записи в 128 килобайт.
Для PostgreSQL и MySQL (MyISAM хранилище),предпочтительно установить размер записи в 8 килобайт:

# zfs create -o recordsize=8k tank/mysql

Для MySQL InnoDB хранилища (не логов) устанавливают размер записи в 16 килобайт, логи должны быть использованы с размером записи по умолчанию.

NFS серверы

Если у вас большое количество операций записи на NFS сервере с ZFS, то целевой журнал ZIL можеть стать вашим "бутылочным горлышком". Возможно вы захотите отключить ZIL или переместить его на другое логирующее устройство (например, SSD-диск) для увеличения производительности, но следует учесть, что отключение ZIL приведет к повреждению данных на NFS-клиенте.

# zfs set sync=disabled dataset

ZFS и Размер сектора в 4к

Изначально жесткие диски использовали для хранения данных 512-байтные физические сектора. В настоящее время, объемные диски используют расширенный формат (4-х килобитные сектора), поддерживая сектора в 512 байт в режиме совместимости.
Как правило, в FreeBSD такие диски все еще сообщают о 512-байтных секторах:

ada0: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)

ZFS использует это значение когда определяет размер блока для устройства при добавлении его в пул (или при создании пула). Для просмотра используемого значения в вашем пуле используйте:

# zdb –C [poolname]

Параметр “ashift” описывает размер блока ZFS как значение 2^[ashift]. Значение «9» означает 512 байтный сектор. Чтобы иметь 4 килобайтные блоки, необходимо значение «12».
Пользователи сообщают о плохой производительности с Расширенным Форматом жестких дисков и ashift=9, особенно в конфигурациях RAIDZ. Чтобы создать пул оптимизированный для 4 Кбайт секторов, мы должны сделать размер блока ZFS соответствующим размеру физического сектора. Некоторые пользователи делают трюк с поддельным устройством gnop. Давайте предположим, что мы хотим создать новый пул на устройстве /dev/ada0.

# gnop create –S 4096 ada0
# zpool create tank ada0.nop
# zpool export tank
# gnop destroy ada0.nop
# zpool import tank
# zdb –C tank | grep ashift

При использовании 4кБ блоков, маленькие файлы до 4кБ занимают весь блок. Размер метаданных ZFS гораздо меньше 4кБ. Пожалуйста, учтите что использование ashift=12 увеличивает необходимое пространство для метаданных до большего значения (порядка 5% от общего размера диска). В зависимости от ваших данных, может увеличиваться нагрузка при заполнении пула данными (например, много маленьких файлов). Таким образом, вам следует избрать компромисс между эффективностью и свободным дисковым пространством.

Заключение

По умолчанию значения настроек ZFS предназначены для обычных пользователей. Эта статья предоставляет вам возможности по оптимизации систем с ZFS и настройки соответствующих опций. Утилиты zfs-stats и zfs-mon помогут вам получить необходимые для этого данные.
ZFS это значимая часть программного обеспечения и я использую ее на десятках систем с FreeBSD, OpenIndiana и даже Linux. Отсутствие средств измерения и оценки вдохновили меня на работу над zfs-stats и zfs-mon.

Мартин Матуска
Вернуться назад