Ви купили великі, недорогі HDD для ємності. Потім почалася продукція: мільйон маленьких файлів, балакучі бази даних, образи VM, які не
збігаються з recordsize, і користувачі, які сприймають «спільне сховище» як «нескінченні IOPS». Пул «здоровий», scrubs проходять, але
піки латентності перетворюють вашу чергу тікетів на археологічний розкоп.
Гібридна схема ZFS може це виправити — якщо ви перестанете мислити маркетинговими гаслами («кеш!») і почнете думати про домени відмов, шляхи запису
і про те, що ZFS фактично робить з метаданими. Це план, який я застосував би, коли потрібна економіка HDD без мук HDD.
Ментальна модель: IO-шляхи ZFS, а не інтуїція
Робота над продуктивністю ZFS на 80% — це розуміння, де витрачається час, і на 20% — налаштування властивостей. Люди інвертують це, а потім
дивуються, чому їхній «NVMe кеш» не виправив повільну роботу з метаданими. Якщо зберегти одну ментальну модель — запам’ятайте цю:
- Читання: спочатку ARC в оперативній пам’яті, потім (опціонально) L2ARC на швидкому носії, потім основні vdev (ваш HDD пул).
- Записи (async): спочатку в пам’ять, агрегуються в TXG, потім сбрасываются на основні vdev.
- Записи (sync): мають бути підтверджені тільки після їхньої гарантованої збереженості. Якщо є SLOG, «гарантовано» означає «в SLOG», а пізніше — на HDD.
- Метадані: записи директорій, непрямі блоки, dnodes — це може домінувати в IO при великій кількості малих файлів і випадковому доступі.
Гібридний план — це про розміщення правильного типу IO на правильному носії:
великі послідовні дані на HDD; «гарячі» метадані (і опціонально малі блоки) на SSD через special vdev; наміри синхронного запису на NVMe SLOG
з малою латентністю; зменшення читального підсилення через L2ARC, коли ARC замало.
Ось нудна правда: більшість проблем із «кешем ZFS» — це фактично проблема нестачі RAM. ARC — єдиний кеш, що завжди коректний, завжди з низькою
латентністю і не потребує цілої інструкції для рев’ю змін.
Цитата, яку варто приклеїти на стикер:
парафразована ідея
від Werner Vogels: «You build it, you run it» не є просто культурою — це спосіб дізнатися, що ваша система реально робить.
Цікаві факти та історичний контекст (коротко, конкретно)
- ZFS народився в Sun, щоб виправити тиху корупцію даних і біль адміністрування; end-to-end контрольні суми були базовою можливістю, а не доповненням.
- ARC передує сучасному хайпу кешів; це кеш Adaptive Replacement у пам’яті, спроєктований працювати краще за просте LRU під змішаними навантаженнями.
- Copy-on-write змінив історію відмов: ZFS не перезаписує живі блоки; він записує нові й оновлює вказівники, зменшуючи проблеми «тутого» запису.
- SLOG — це не write cache; історично він був введений для прискорення sync-записів шляхом журналізації намірів, а не для поглинання об’ємного потоку.
- L2ARC має «податок заголовків»: він потребує метаданих в ARC для індексації вмісту L2ARC, тому додавання L2ARC може зменшити ефективний ARC.
- Special vdev з’явилися відносно недавно в історії OpenZFS; вони формалізували патерн «зберігати метадані на SSD» без хакингу.
- Ashift став кар’єрним обмежувачем: ранні адміністратори ZFS дізналися, що неправильне вирівнювання секторів може назавжди позбавити IOPS для 4K-дисків.
- Компресія стала мейнстримом не лише тому, що економить місце (це також), але й тому, що менше байтів для читання часто швидше за сирий диск.
Референсна архітектура: HDD дані + SSD метадані + NVMe кеш
Визначимо мету: пул, де великі холодні дані залишаються на HDD, а шаблони IO, що карають латентність HDD — пошуки метаданих, малі випадкові
читання, латентність синхронних записів — перенаправляються на швидкі носії так, щоб не скомпрометувати безпеку або керованість.
Базові припущення (проговоріть вголос)
- HDD — для ємності та послідовної пропускної здатності. Вони жахливі у випадкових IO за латентністю. Це фізика, не проблема вендора.
- SSDs/NVMe — для низької латентності та IOPS. Вони теж виходять з ладу; просто швидше і іноді креативніше.
- RAM — перший важіль продуктивності. Якщо ви не знаєте співвідношення влучань ARC, ви налаштовуєте в сліпу.
- Ви використовуєте OpenZFS на Linux (приклади припускають шляхи Ubuntu/Debian). Налаштуйте під свою систему.
Розумна «гібридна» схема (приклад)
Це звичний, придатний для продакшену патерн:
- Data vdevs: HDD RAIDZ2 (або mirror, якщо потрібні IOPS більше, ніж ефективність ємності)
- Special vdev: SSD у дзеркалі для метаданих (і опційно малих блоків)
- SLOG: дзеркальні NVMe (або принаймні NVMe enterprise з PLP) для латентності sync-записів
- L2ARC: опційно NVMe (часто того ж класу, що й SLOG, але не ті самі пристрої) для читально-важких навантажень, які перевищують ARC
Чому дзеркалення для special vdev та SLOG? Тому що ці компоненти — не «приємні доповнення». Вони стають частиною історії доступності пула.
Втрата special vdev може спричинити втрату пулу. Втрата SLOG — втрата прискорення sync-записів (і потенційно семантики in-flight sync під час аварії),
але з дзеркаленням і PLP ви уникаєте перетворення стрибка живлення на катастрофу запису.
Жарт №1: Якщо хтось пропонує «один consumer SSD як special vdev, щоб заощадити», спитайте, чи вони також віддають перевагу одному парашутисту при стрибку, щоб зменшити вагу.
SSD для метаданих правильно: дизайн special vdev
Що насправді роблять special vdev
Special vdev може зберігати метадані і, опційно, малі блоки на швидкому носії. Це означає, що обходи директорій, перегляд атрибутів файлів,
читання непрямих блоків і багато малих випадкових читань перестають бити по HDD.
Виграш найпомітніший коли:
- у вас багато малих файлів (CI-артефакти, шари контейнерів, репозиторії, поштові скриньки, кеші збірок)
- у вас глибокі дерева директорій і часті stat/open операції
- ваш робочий набір більший за ARC, але метадані відносно компактні
Непорушне правило: дзеркаліть special vdev
Special vdev — частина пулу. Якщо він помре і у вас немає надлишковості, ви можете не опинитися «degraded». Ви можете опинитися «done».
Ставтесь до нього як до основної надлишковості: ніяких одиночних точок відмови.
Як вирішити, чи зберігати малі блоки в special vdev
ZFS може поміщати блоки менші за поріг у special vdev через special_small_blocks. Це потужно і небезпечно — як дати SSD для метаданих підробляти
як рандом-рид тір.
Використовуйте це, коли:
- ваші HDD vdevs страждають від латентності на малих випадкових читаннях
- у вас відоме навантаження з малими блоками (багато файлів < 64K, багато дрібних об’єктних читань)
- ваш special vdev має достатню витривалість і запас ємності
Уникайте, коли:
- ви не можете точно оцінити зростання сліду малих блоків
- ваші SSD — споживчого класу з сумнівною витривалістю і без PLP
- ви вже ледве тримаєте special vdev під ~50–60% використання
Розмір special vdev без самообману
Орієнтовні рекомендації, що витримують практику:
- Лише метадані в special vdev: часто це кілька відсотків від використаного простору пулу, але може підстрибувати через snapshot-и, дрібні записи і високий churn.
- Метадані + малі блоки: можуть стати «більшістю вашого гарячого шару». Плануйте ємність серйозно.
Практичне правило: розмірюйте special vdev так, щоб у steady state вони залишалися комфортно нижче 70% використання. SSD повільніють, коли заповнені,
ZFS metaslab вибирає складніше, і ваш «швидкий рівень» стає обмеженим.
NVMe SLOG: що це і чого це не є
Що робить SLOG
Separate Intent Log (SLOG) — це пристрій для збереження ZFS Intent Log (ZIL) для sync-записів. Він зменшує латентність підтвердження sync-записів,
записуючи мінімальний журнал наміру на швидке сховище, а пізніше committing повного TXG на основні vdev.
Це не загальний write cache. Якщо ваше навантаження в основному async-записи, SLOG не допоможе. Якщо ваше навантаження sync-важке (NFS з sync,
бази даних з fsync(), сховище VM, що змушує sync), SLOG може бути різницею між «корисно» і «чому тут знову 1998 рік?»
Вимоги до носія SLOG (будьте вибіркові)
- Низька латентність при sync-записі (стабільна, а не лише пікові бенчмарки)
- Захист від втрати живлення (PLP), щоб підтверджені записи пережили стрибок живлення
- Витривалість, відповідна для write-heavy sync-навантажень
- Дзеркалити, якщо вам важлива доступність і передбачувана поведінка при відмовах пристроїв
Розмір SLOG: малий, швидкий, нудний
Зазвичай вам не потрібен величезний SLOG. Потрібен такий, що витримає ваш піковий sync-write rate на час між TXG commit (зазвичай секунди)
і поведінкою flush пристрою. Надмірне збільшення не дає багато. Недостатнє — купує вас схилами латентності.
Жарт №2: Споживчий NVMe без PLP, використаний як SLOG — це як ремінь безпеки з макаронів: формально є, духом його немає.
NVMe L2ARC: коли допомагає і коли бреше
Чесна пропозиція для L2ARC
L2ARC — це кеш читання другого рівня. Він допомагає, коли:
- у вас читально-важке навантаження з робочим набором більшим за ARC
- шаблон доступу має повторне використання (кешовані читання, а не скани один раз)
- вузьке місце — латентність/IOPS HDD, а не CPU або мережа
Чому L2ARC розчаровує людей
L2ARC не безкоштовний. Він:
- споживає пам’ять ARC для заголовків і індексування
- нагрівається з часом (не відразу після перезавантаження, якщо не налаштовано інше)
- може бути неефективним для потокових читань, великих послідовних сканів або датасетів з низькою локальністю
Практична порада
Якщо вам не вистачає RAM, купіть RAM, перш ніж купувати L2ARC. Якщо RAM достатньо, а ви все ще обмежені читальною латентністю, L2ARC може бути
корисним важелем. Але вимірюйте, не припускайте.
Тюнінг датасетів, що дійсно дає ефект
Компресія: включайте за замовчуванням, якщо немає протипоказань
compression=lz4 зазвичай виграш: менше байтів для читання з HDD, часто швидше в цілому. Якщо дані вже стиснені (медіа-файли,
зашифровані бінарні), це може не сильно зменшити розмір — але зазвичай не шкодить, якщо CPU не обмежує.
recordsize: підлаштуйтесь під те, як читаєте, а не як зберігаєте
Для загальних файлових систем recordsize=128K підходить. Для баз даних часто потрібні менші записи (наприклад 16K), щоб зменшити
read amplification. Для образів VM розгляньте 64K або 128K залежно від навантаження. Для zvol-ів підбирайте volblocksize при створенні (його не змінити пізніше).
sync та logbias: не «виправляйте» латентність, видаливши безпеку
Встановлення sync=disabled — це не тюнінг. Це вибір обманювати додатки щодо надійності. Іноді люди так роблять під тиском.
Іноді вони болісно дізнаються, що означає «crash-consistent».
Якщо потрібно оптимізувати sync-навантаження, використайте реальний SLOG і розгляньте logbias=latency для датасетів, де важлива латентність sync.
logbias=throughput використовуйте лише коли ви свідомо хочете, щоб ZFS надавав перевагу основним записам пулу над поведінкою ZIL — і ви це протестували.
atime: невелика вигода, низький ризик
Вимкнення atime (atime=off) зменшує метадані-записи для читально-важких навантажень. Це рідко контроверсійно в сучасних середовищах.
Практичні завдання з командами: що запускати, що це означає, яке рішення приймати
Це завдання, які я реально виконую на системах. Кожне містить: команду, правдоподібний фрагмент виводу, що це означає, і яке рішення прийняти.
Використовуйте як будівельні блоки для своїх runbook-ів.
Завдання 1: Підтвердити топологію пула (чи дійсно у вас те, що ви думаєте?)
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
ata-ST12000NM0008-1A-0001 ONLINE 0 0 0
ata-ST12000NM0008-1A-0002 ONLINE 0 0 0
ata-ST12000NM0008-1A-0003 ONLINE 0 0 0
ata-ST12000NM0008-1A-0004 ONLINE 0 0 0
ata-ST12000NM0008-1A-0005 ONLINE 0 0 0
ata-ST12000NM0008-1A-0006 ONLINE 0 0 0
special
mirror-1 ONLINE 0 0 0
nvme-SAMSUNG_MZ1LB960HAJQ-0001 ONLINE 0 0 0
nvme-SAMSUNG_MZ1LB960HAJQ-0002 ONLINE 0 0 0
logs
mirror-2 ONLINE 0 0 0
nvme-INTEL_SSDPED1D280GA-0001 ONLINE 0 0 0
nvme-INTEL_SSDPED1D280GA-0002 ONLINE 0 0 0
cache
nvme-SAMSUNG_MZ1LB960HAJQ-0003 ONLINE 0 0 0
errors: No known data errors
Що це означає: У вас HDD RAIDZ2 для даних, дзеркальний special vdev, дзеркальний SLOG і пристрій L2ARC.
Рішення: Якщо special або logs — одиночні пристрої, виправте це перед тим, як називати систему «готовою до продакшену».
Завдання 2: Перевірити ashift (вирівнювання) та розміри секторів
cr0x@server:~$ sudo zdb -C tank | grep -E "ashift|path" -n | head
34: ashift: 12
102: path: '/dev/disk/by-id/ata-ST12000NM0008-1A-0001'
Що це означає: ashift: 12 = 4K сектори. Добре для сучасних HDD/SSD. Якщо бачите 9 (512B) на 4K-носії — продуктивність може бути назавжди зіпсована.
Рішення: Неправильний ashift означає перебудову/пересоздання. Не сваріться з фізикою.
Завдання 3: Подивитися, скільки на спеціальному vdev (перевірка ризику ємності)
cr0x@server:~$ sudo zpool list -v tank
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 65.4T 40.1T 25.3T - 18% 61% 1.00x ONLINE -
raidz2 65.4T 39.4T 26.0T - 18% 60% - ONLINE
special 1.7T 0.7T 1.0T - 12% 41% - ONLINE
logs 279G 4.2G 275G - 1% 1% - ONLINE
cache 894G 812G 82G - 22% 90% - ONLINE
Що це означає: Special vdev на 41% — нормально. L2ARC на 90% «заповнений», що нормально; він так і працює.
Рішення: Якщо special vdev підповзає до 70–80% з увімкненим special_small_blocks, плануйте розширення, поки це не стало відмовою.
Завдання 4: Підтвердити властивості датасету (ви випадково себе саботуєте?)
cr0x@server:~$ sudo zfs get -o name,property,value -s local,received compression,atime,recordsize,sync,logbias,special_small_blocks tank/data
NAME PROPERTY VALUE
tank/data compression lz4
tank/data atime off
tank/data recordsize 128K
tank/data sync standard
tank/data logbias latency
tank/data special_small_blocks 16K
Що це означає: Розумні налаштування для багатьох змішаних навантажень. Малі блоки <=16K потрапляють на special vdev.
Рішення: Якщо витривалість special vdev викликає занепокоєння, збільшіть або відключіть special_small_blocks. Якщо проблема — латентність sync, залиште logbias=latency і інвестуйте в якісний SLOG.
Завдання 5: Визначити, чи ваше навантаження sync-важке (тест релевантності SLOG)
cr0x@server:~$ sudo zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 40.1T 25.3T 220 1800 38.2M 145M
raidz2 39.4T 26.0T 120 240 34.1M 120M
special 0.7T 1.0T 90 1550 4.0M 25.0M
mirror (logs) 4.2G 275G 0 1600 0 22.0M
cache - - - - - -
-------------------------- ----- ----- ----- ----- ----- -----
Що це означає: Записи сильно йдуть в logs і special vdev. Це часто вказує на sync-трафік і активність метаданих/малих блоків.
Рішення: Якщо logs показують нуль, а у вас «проблеми з базою даних», можливо ви не sync-обмежені; шукайте інше (ARC misses, черги HDD, CPU).
Завдання 6: Перевірити поведінку ARC (чи пам’ять виконує свою роботу?)
cr0x@server:~$ sudo arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
12:01:10 420 35 8 9 2 26 6 0 0 62G 64G
12:01:11 410 40 10 12 3 28 7 0 0 62G 64G
12:01:12 395 33 8 8 2 25 6 0 0 62G 64G
Що це означає: Miss rate ARC ~8–10% — пристойно. Якщо miss% постійно високий, HDDи будуть завалені, і L2ARC може допомогти — після збільшення RAM.
Рішення: Якщо arcsz прив’язаний до c і miss% високий, подумайте про додавання RAM або зменшення навантаження на пам’ять.
Завдання 7: Перевірити ефективність L2ARC (чи дійсно він обслуговує читання?)
cr0x@server:~$ sudo arcstat -f time,read,miss,l2hits,l2miss,l2read 1 3
time read miss l2hits l2miss l2read
12:02:21 500 70 120 40 160
12:02:22 480 65 110 35 145
12:02:23 510 68 130 38 168
Що це означає: L2ARC має хіти. Якщо l2hits близько нуля, ваш L2ARC не допомагає (або ще не прогрівся, або в навантаженні немає повторного використання).
Рішення: Якщо L2ARC не допомагає — видаліть його або переосмисліть використання пристрою; не тримайте складність як декоративний аксесуар.
Завдання 8: Інспектувати тиск IO на special vdev (насичення шару метаданих)
cr0x@server:~$ sudo iostat -x 1 3 /dev/nvme0n1 /dev/nvme1n1
Linux 6.8.0 (server) 12/26/2025 _x86_64_ (32 CPU)
Device r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await %util
nvme0n1 820.0 540.0 42.0 31.5 94.0 2.10 1.8 92.0
nvme1n1 815.0 530.0 41.5 30.9 93.5 2.05 1.9 91.0
Що це означає: SSD special vdev близькі до насичення (%util ~90+), але все ще з малою латентністю (await ~2ms). Це нормально… поки не стане ні.
Рішення: Якщо await підстрибує (скажімо 10–20ms) під навантаженням, special vdev — ваш вузький пляшок. Розгляньте швидші SSD, більше ліній або підвищення special_small_blocks.
Завдання 9: Підтвердити шлях латентності sync-запису (здоров’я та тиск SLOG)
cr0x@server:~$ sudo iostat -x 1 3 /dev/nvme2n1 /dev/nvme3n1
Device r/s w/s rMB/s wMB/s avgqu-sz await %util
nvme2n1 0.0 2200.0 0.0 28.0 0.60 0.4 55.0
nvme3n1 0.0 2180.0 0.0 27.8 0.58 0.4 54.0
Що це означає: SLOG-записи швидкі та стабільні. Якщо await підстрибує, ваша sync-продуктивність обмежена латентністю SLOG.
Рішення: Якщо латентність SLOG погана, замініть на PLP enterprise NVMe. Не «налаштовуйте навколо» поганих носіїв.
Завдання 10: Визначити, чи HDD vdevs чергуються (класична біль RAIDZ при дрібних IO)
cr0x@server:~$ sudo zpool iostat -v tank 1 3
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 40.1T 25.3T 900 600 110M 80M
raidz2 39.4T 26.0T 860 560 106M 76M
ata-ST12000...0001 - - 140 95 18.0M 12.7M
ata-ST12000...0002 - - 145 92 18.2M 12.4M
ata-ST12000...0003 - - 142 93 18.1M 12.5M
ata-ST12000...0004 - - 143 96 18.0M 12.8M
ata-ST12000...0005 - - 145 92 18.3M 12.4M
ata-ST12000...0006 - - 145 92 18.2M 12.4M
-------------------------- ----- ----- ----- ----- ----- -----
Що це означає: Багато per-disk операцій вказує на випадкові IO. RAIDZ2 може впоратися, але дрібні випадкові записи дорогі (паритетні обчислення + RMW).
Рішення: Якщо це пул для VM або БД і важлива латентність, дзеркала часто кращі за RAIDZ для IOPS. Або перемістіть малі блоки/метадані на special vdev продумано.
Завдання 11: Слідкувати за TXG та тиском на commit (підказка для піків латентності)
cr0x@server:~$ sudo cat /proc/spl/kstat/zfs/txgs
dmu_tx_assign 0
txg_sync 0
txg_quiesce 0
txg_birth 0
txg_state 0
txg_timeout 5
txg_synctime_ms 312
Що це означає: TXG timeout 5s, synctime ~312ms зараз. Якщо synctime зростає до секунд, пул бореться зі скиданням.
Рішення: Якщо synctime корелює з латентністю додатка, зосередьтеся на пропускній здатності записів і латентності пристроїв — часто насичення HDD vdev або тиск special vdev.
Завдання 12: Перевірити, що autotrim налаштований відповідно (довговічність SSD + стабільна продуктивність)
cr0x@server:~$ sudo zpool get autotrim tank
NAME PROPERTY VALUE SOURCE
tank autotrim on local
Що це означає: TRIM увімкнено, допомагає SSD підтримувати продуктивність і зменшує write amplification.
Рішення: Для SSD у special vdev, logs і L2ARC, autotrim=on зазвичай правильне рішення.
Завдання 13: Перевірити лічильники помилок пристроїв та повільне деградування
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 05:12:33 with 0 errors on Sun Dec 21 04:00:31 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
ata-ST12000NM0008-1A-0003 ONLINE 0 0 0
ata-ST12000NM0008-1A-0004 ONLINE 0 0 0
special
mirror-1 ONLINE 0 0 0
nvme-SAMSUNG_MZ1LB960HAJQ-0001 ONLINE 0 0 0
nvme-SAMSUNG_MZ1LB960HAJQ-0002 ONLINE 0 0 0
errors: No known data errors
Що це означає: Scrub чистий; немає зростаючих лічильників помилок.
Рішення: Якщо READ/WRITE/CKSUM почнуть інкрементуватися на special vdev або SLOG, ставтеся до цього як до термінового. «Воно ще працює» — не стратегія.
Завдання 14: Підтвердити, що special allocation дійсно використовується (шлях від placebo-дизайну)
cr0x@server:~$ sudo zdb -bbbs tank | grep -E "Special|special" | head
Special allocation class: 734.22G used, 1.01T available
Що це означає: Відбувається алокація в special класі. Якщо мало на metadata-heavy системі, ваш дизайн не задіяний.
Рішення: Перевірте special_small_blocks і підтвердьте, що ви створили special vdev правильно; не припускайте, що «SSD присутній» означає «SSD використовують».
Швидкий план діагностики: що перевірити першим/другим/третім
Коли гібридний пул ZFS «повільний», вам не потрібен день філософських дебатів. Потрібен короткий цикл: ідентифікуйте, який шар насичений, потім
зіставте його з класом пристрою та типом IO.
Перше: чи це проблема кешу/RAM?
- Перевірте розмір ARC і miss% (
arcstat). - Якщо miss% високий і ARC обмежений: ймовірно ви дисково-обмежені, бо RAM не тримає робочий набір.
- Рішення: додайте RAM, зменшіть тиск на пам’ять або прийміть, що HDD отримуватимуть читання (і тоді розгляньте L2ARC).
Друге: чи це проблема латентності sync-записів?
- Перевірте, чи активні logs (
zpool iostat -vпоказує записи в logs). - Перевірте латентність SLOG пристрою (
iostat -xна SLOG пристроях). - Рішення: якщо sync-важке і SLOG await високий, оновіть/замініть SLOG-носій; не чіпайте
sync=disabled, якщо не хочете постмортемів.
Третє: чи це тиск метаданих/малих блоків на special vdev?
- Перевірте використання та IO special vdev (
zpool list -v,iostat -x). - Перевірте, чи special близький до заповнення або показує зростаючу латентність.
- Рішення: розширіть special vdev (додайте ще один дзеркальний special vdev), використайте швидші пристрої або відкоригуйте
special_small_blocks.
Четверте: чи це насичення HDD vdev?
- Перевірте per-vdev і per-disk операції (
zpool iostat -v). - Високі ops і низька пропускна спроможність на HDD = біль випадкових IO; RAIDZ відчуває це особливо.
- Рішення: змініть розміщення навантаження (окремий пул для VM/DB), перемістіть гарячі датасети на SSD-пул або прийміть дзеркала для IOPS-орієнтованих шарів.
П’яте: перевірте не-ZFS частини (бо реальність)
- Мережна латентність (для NFS/SMB), CPU steal, насичення IRQ, глибина черги HBA і обмеження віртуалізації можуть маскуватися під «зберігання».
- Рішення: перевірте системні метрики; не звинувачуйте ZFS через вузьке місце 1GbE.
Типові помилки (симптоми → корінь → виправлення)
1) «Ми додали NVMe кеш і нічого не змінилось.»
Симптоми: Та сама латентність читання, ті ж HDD операції, L2ARC hit rate близько нуля.
Корінь: Навантаження має низьке повторне використання (стримінг), або ARC занадто маленький і заголовковий оверхед L2ARC зробив гірше, або L2ARC не прогрівся.
Виправлення: Вимірюйте arcstat. Спочатку додайте RAM. Якщо шаблон доступу — стримінг, приберіть L2ARC і зосередьтеся на vdev-розміщенні та послідовній пропускній здатності.
2) «Special vdev заповнюється і ми лякаємось.»
Симптоми: Використання special росте швидше, ніж очікували; зростає знос SSD; латентність під час метаданого-чорнових робіт стрибає.
Корінь: special_small_blocks встановлено занадто високо, малі блоки домінують, snapshot-и посилюють метадані або special vdev занадто маленький.
Виправлення: Зменшіть special_small_blocks (для майбутніх алокацій), додайте ще один дзеркальний special vdev і тримайте special нижче ~70% використання.
3) «Sync-записи повільні навіть з SLOG.»
Симптоми: Висока латентність підтвердження транзакцій бази даних; SLOG пристрій показує високий await; додаток зупиняється під піками.
Корінь: SLOG пристрій без PLP, має погану стабільну латентність, ділиться з іншими навантаженнями або фактично не використовується.
Виправлення: Перевірте активність логів з zpool iostat -v. Використовуйте виділений enterprise NVMe з PLP. Дзеркаліть його.
4) «Ми поставили sync=disabled і стало швидко. Чому б не залишити?»
Симптоми: Продуктивність одразу покращилась; управління задоволене; SRE тихо оновлює резюме.
Корінь: Ви обміняли надійність на швидкість. Додатки, що очікують fsync-стійкість, тепер вводяться в оману.
Виправлення: Поверніть sync=standard. Розгорніть належний SLOG і налаштуйте властивості датасетів під навантаження.
5) «Пул здоровий, але кожні кілька секунд піки латентності.»
Симптоми: Періодичні затримки; графіки показують пилкоподібну латентність записів; скарги користувачів під піками.
Корінь: TXG sync pressure: HDD не можуть скинути достатньо швидко; special vdev насичений; фрагментація і майже повний пул підсилюють проблему.
Виправлення: Перевірте TXG synctime, використання vdev, заповненість пулу. Додайте vdev-и, зменшіть write amplification (компресія допомагає) і тримайте пул нижче ~80% для write-heavy середовищ.
6) «Ми використали одиночний special vdev, бо це «лише метадані».»
Симптоми: Раптова відмова пула або відсутні метадані після смерті SSD; варіанти відновлення мізерні.
Корінь: Special vdev не опціональний; він у шляху даних.
Виправлення: Завжди дзеркаліть special vdev. Якщо ви вже розгорнули single-disk special, плануйте міграцію: бекап, перебудова правильної топології, відновлення. Немає чистого ретрофіта без переміщення даних.
Три корпоративні міні-історії (анонімізовано, правдоподібно, технічно коректно)
Інцидент через хибне припущення: «Метадані не можуть вивести пул з ладу, правда?»
Середня SaaS-компанія використовувала файловий конвеєр: артефакти збірок, шари контейнерів і багато маленьких JSON. Їх команда зробила «розумно»:
HDD RAIDZ2 для об’єму плюс один «metadata SSD», бо бюджетна нарада була контактною боротьбою.
Це працювало блискуче місяцями. Переліки директорій були шустрі. Збірки перестали таймаутитись. Люди почали використовувати пул для більше речей,
бо успіх притягує обсяг.
Потім SSD помер. Не драматично — просто тихе відключення з PCIe шини. Пул не «знизився» ввічливо. Він запанікував. Метадані, які ZFS очікував знайти… відсутні.
Сервіси перезапустилися в станах, що виглядали як випадкова корупція файлової системи.
Команда спочатку думала, що це кеш-фейл: ребут, рескан, перепідключення. Це втратило години. Насправді довелося болісно відновлювати з бекапів до правильно
сконструйованого пулу з дзеркальним special vdev. Система повернулась, але з новою політикою: «якщо це в топології пулу — воно має надлишковість».
Урок не в тому, що ZFS крихкий. Урок у тому, що ZFS буквальний. Якщо ви кажете йому, що метадані живуть на тому пристрої — ZFS повірить вам з відданістю золотистого ретривера.
Оптимізація, що відкотилася: «Давайте вмикати special_small_blocks скрізь»
Велика аналітична платформа мала змішані навантаження: файли data lake (великі), тимчасові ETL (середні) і купа дрібних логів та індексів.
Вони додали дзеркальний SSD special vdev і побачили негайне покращення. Далі — добре.
Хтось запропонував встановити special_small_blocks=128K для більшості датасетів. Міркування звучали чисто: «Якщо більшість блоків
піде на SSD, HDD стануть лише ємністю. SSD швидкі. Усі виграли.» Зміна пройшла, бо в першу годину графік латентності виглядав краще.
Через тижні SSD були заповнені більше, ніж очікували, і латентність записів почала коливатися. Не постійна відмова — гірше: переривчасті затримки під піковими бачами.
Scrubs були чисті. SMART виглядав «добре». On-call коло почало мати думки.
Причина була передбачуваною: special vdev тихо став основним шаром даних для більшості активних датасетів. Він поглинав write amplification, snapshot churn і
випадкові читання. Коли заповнився, внутрішнє GC SSD і поведінка алокації ZFS поєдналися в латентні піки. HDD були невинні.
Виправлення було нудне, але ефективне: зменшили special_small_blocks до консервативного значення для загальних датасетів, агресивні значення лишили
лише для кількох дрібно-орієнтованих дерев, і додали ємність у special клас. Продуктивність стабілізувалась. Графіки стали менш драматичні.
Нудна, але правильна практика, що врятувала день: «Міряйте, скрабьте і репетируйте»
Фінансова команда тримала NFS на ZFS для внутрішніх додатків. Ніхто поза командою не переймався деталями зберігання — найкращий стан для storage: невидимість.
Вони мали рутину, що здавалася майже старомодною: щомісячні scrub-вікна, квартальні тренування відновлення і дашборд, що відстежував ARC hit rate,
використання special vdev, латентність SLOG і фрагментацію пулу. Також була політика тримати special vdev використання нижче консервативного порогу.
Одного кварталу новий додаток збільшив churn малих файлів. Дашборд зловив це рано: алокація special vdev зростала, і латентність запису SSD піднімалась
під батчами. Нічого ще не «зламалося» — просто тренд був неправильний.
Оскільки вони побачили це рано, виправлення було хірургічним: додали ще одну пару дзеркальних special vdev в плановому вікні, відкоригували
special_small_blocks для кількох датасетів і тримали пул в межах узгодженого ліміту використання.
Ніякого аутейджу. Жодного інциденту. Жодних вихідних. Команда отримала нуль похвали — а в операціях саме так і слід робити свою роботу правильно.
Чеклісти / покроковий план
Покроково: побудувати гібридний пул (продакшен-орієнтовано)
- Спочатку оберіть vdev-розмітку. Якщо потрібні IOPS і стабільна латентність для VMs/DBs — віддайте перевагу дзеркалам. Якщо потрібна ефективність ємності і в основному послідовні IO — RAIDZ2 підходить.
- Оберіть SSD для special vdev. Дзеркаліть їх. Віддавайте перевагу витривалості і стабільній латентності, а не піковим IOPS у характеристиках.
- Оберіть NVMe для SLOG. Використовуйте PLP enterprise NVMe. Дзеркаліть його. Тримайте виділеним.
- L2ARC вирішуйте останнім. Тільки після вимірів ARC misses і підтвердження локальності читань.
- Створіть пул з правильним ashift. Використовуйте персистентні імена пристроїв в
/dev/disk/by-id. Не використовуйте/dev/sdXв продакшені. - Встановіть базові властивості.
compression=lz4,atime=off, адекватнийrecordsizeдля кожного датасету. - Увімкніть autotrim. Особливо коли в топології є SSD.
- Налаштуйте моніторинг. Відстежуйте ARC miss%, латентність SLOG, використання special vdev, результати scrub і помилки пристроїв.
- Репетируйте відмови. Виймете пристрій у стенді. Підтвердіть алерти. Підтвердіть поведінку resilver. Підготуйте рукодію команди.
Операційний чекліст: тримати в здоров’ї
- Тримайте заповненість пулу нижче ~80% для write-heavy навантажень.
- Плануйте scrubs і перевіряйте результати, а не лише «він запустився».
- Слідкуйте за зносом і використанням special vdev; ставтесь до нього як до шару, що може заповнитися.
- Не діліть SLOG з довільними навантаженнями; латентність — продукт.
- Тримайте firmware і драйвери стабільними; стеки зберігання не люблять несподівані оновлення.
Чекліст міграції: перетворення існуючого HDD пула в гібрид
- Підтвердіть, що можна додати special vdev без порушення політики надлишковості (можна, але він має бути надлишковим).
- Оцінивайте метадані/малі блоки; плануйте ємність special з запасом.
- Додайте дзеркальний special vdev; потім встановлюйте
special_small_blocksлише там, де потрібно. - Додайте дзеркальний SLOG, якщо важлива латентність sync.
- Підтвердіть зміни до/після метриками (ARC misses, iostat, латентність додатка).
FAQ
1) Чи потрібні мені і SLOG, і L2ARC?
Ні. SLOG допомагає sync-записам. L2ARC допомагає читанням, коли ARC недостатньо і навантаження має повторне використання. Багатьом системам не потрібен жоден з них, якщо RAM і vdev-розмітка налаштовані правильно.
2) Чи можна використовувати один NVMe для SLOG і L2ARC?
Можна, але зазвичай не варто. SLOG хоче передбачуваної низької латентності; L2ARC хоче пропускної здатності і може генерувати фоні записи. Змішування може створити джиттер саме там, де ви цього не хочете.
3) Чи special vdev — це «просто кеш»?
Ні. Це алокація, а не кеш. Дані, поміщені туди, є частиною пулу. Якщо ви втратите нерезервований special vdev, ви можете втратити пул.
4) Що встановлювати для special_small_blocks?
Починайте консервативно: 0 (лише метадані) або 16K. Збільшуйте лише для датасетів, доведених як маленько-блокові, і лише якщо ємність і витривалість special vdev достатні.
5) Чи SLOG покращує throughput?
Він покращує латентність sync-записів, що може підвищити пропускну здатність на рівні додатка, якщо додаток обмежений часом commit. Він не перетворює HDD на NVMe для масових записів.
6) Чи ставити sync=always для безпеки?
Лише якщо приймаєте вартість продуктивності і маєте хороший SLOG. Багато додатків вже викликають fsync там, де потрібно. Форсування всього в sync може бути самонанесеною болем.
7) Дзеркала чи RAIDZ для HDD vdev в гібридному дизайні?
Дзеркала — це гра за латентністю/IOPS; RAIDZ — гра за ефективністю ємності. Special vdev допомагає RAIDZ пулам із метаданими/малими читаннями, але не знімає витрат паритету для випадкових записів.
8) Як зрозуміти, що L2ARC шкодить?
Слідкуйте за тиском ARC і miss%. Якщо додавання L2ARC зменшило ARC і не дало значущих L2-хітів, ви додали складність і вкрали RAM даремно. Міряйте через arcstat.
9) Чи можна додати special vdev після створення пулу?
Так. Але існуючі метадані не мігрують автоматично. Ви побачите вигоди при нових алокаціях, і можна ініціювати перезапис через реплікацію або переміщення файлів за потреби.
10) Чи корисний dedup у цій гібридній схемі?
Зазвичай ні, якщо у вас немає дуже специфічного dedup-дружнього навантаження і бюджету на RAM/CPU. Компресія — безпечніша й ефективніша за замовчуванням.
Практичні наступні кроки
Якщо хочете, щоб гібридний план працював у продакшені — не починайте з купівлі «кешу». Почніть з опису фактів вашого навантаження: sync vs async,
середній розмір IO, локальність читань, інтенсивність метаданих і зростання. Потім спроектуйте топологію пулу так, щоб відмова не перетворювалася на трилер.
- Запустіть завдання перевірки топології та ARC з вищеописаних. Визначте, чи ви обмежені через read-misses, sync-latency або метадані.
- Якщо метадані/малі файли шкодять — додайте дзеркальний special vdev і тримайте його комфортно нижче 70% використання.
- Якщо sync-записи болять — додайте дзеркальний PLP NVMe SLOG і перевірте, що він дійсно використовується.
- Якщо читання болять після достатнього RAM — розгляньте L2ARC і валідуйте по hit rate та реальній латентності додатка.
- Закріпіть нудні практики: scrubs, моніторинг, тренування відновлення та письмова політика щодо заповнення пулу і надлишковості класів пристроїв.
Гібридний ZFS — це не набір трюків. Це план маршрутизації IO з наслідками. Зробіть правильно, і HDD знову стануть тим, чим добре: дешевою,
нудною ємністю. Зробіть неправильно — і ви дізнаєтесь, яка з ваших SSD має найяскравішу драматичну особистість.