У ZFS є маленький перемикач з імʼям sync, що виглядає нешкідливо, поки не зруйнує вам тиждень — або не врятує його. Переключіть його в одну позицію, і графік затримок заспокоїться, бенчмарки стануть героїчними, а хост віртуальних машин раптом «відчує швидкість». Переключіть в іншу — і ви отримаєте ті гарантії, які люблять аудитори, і на яких оператори можуть спати спокійно. Підступ в тому, що обидва результати можуть бути правдою одночасно, залежно від того, що ви розумієте під «записано на диск».
Це не повчання про «ніколи не вимикати безпеку». Це польовий довідник для тих, хто керує продакшном: що sync насправді робить, чому воно може задушити систему, як допомагають SLOG-пристрої (і де вони не допомагають), а також як вибирати налаштування під обіцянки вашого навантаження. Мета проста: бути швидким, не перетворивши зберігання даних на чемну пропозицію.
Що насправді означає ZFS «sync» (і чого воно не означає)
У ZFS властивість набору даних sync контролює, як ZFS обробляє запити на синхронний запис. Ця формулювання важлива. ZFS не вирішує випадково бути синхронним; саме викликач просить цього.
Синхронний запис означає, що додаток (або протокол) каже: «Не повідомляйте про успіх, доки ці дані не будуть на стійкому сховищі». Стійке сховище — це те, що переживе збій та раптове відключення живлення. Не «воно в ОЗП», не «контролер каже, що в кеші», не «Linux page cache оптимістично налаштований сьогодні». Стійке.
ZFS реалізує цю гарантію шляхом фіксації наміру запису в ZIL (ZFS Intent Log). Якщо у вас є окремий лог-пристрій (SLOG), ZFS може розмістити ті дані ZIL на низьколатентному пристрої, щоб зробити sync-записи швидшими. Пізніше ZFS згортає ці зміни в основний пул у звичайних комітах груп транзакцій (TXG).
Дві негайні наслідки:
syncсам по собі не робить систему «безпечнішою». Воно визначає, що ZFS зробить, коли викликач попросить semantics sync. Якщо викликач ніколи не просить (або неправильно налаштований), ви все ще можете втратити дані при відключенні живлення.syncцілком може зробити вас швидшими. Але прискорення часто досягається за рахунок відмови від гарантій стійкості. Саме тому це налаштування відоме: це один із небагатьох важелів, де продуктивність і безпека напряму повʼязані.
Перший жарт, бо він ще знадобиться: відключити sync — це як зняти пожежний датчик, бо він сигналить, коли ви підпалюєте тост — спокійно доти, поки не стане не до жартів.
Цікаві факти та історичний контекст
Трохи контексту робить поведінку менш магічною і більш інженерною:
- ZFS зʼявився в Sun Microsystems на початку 2000-х, розроблений для цілісності даних від краю до краю та розумних операцій на масштабі — в часи, коли «просто використовуй RAID і сподівайся» ще був популярним планом.
- ZIL — це не кеш записів для всього підряд. Він існує спеціально для задоволення синхронної семантики; більшість асинхронних записів ніколи його не торкаються.
- SLOG — це не «SSD-кеш». Це виділений пристрій для швидкого збереження ZIL. Він не прискорює читання і не робить автоматично швидшими всі записи.
- Багато корпоративних систем зберігання продавали «NVRAM-backed write cache» як магічний інгредієнт, що робить sync-записи швидкими. У світі ZFS захищений від втрати живлення SLOG виконує подібну роль, але лише для ZIL.
- NFS має репутацію «таємничої повільності» частково тому, що часто запитує стабільні записи. Якщо сховище не може швидко підтвердити sync, протокол мережі виглядає підозрілим.
- Бази даних часто використовують
fsync()як межу. PostgreSQL, MySQL/InnoDB та інші покладаються на явні виклики скидання на диск для збереження довговічності транзакцій. - Віртуалізаційні стекі посилюють проблему. VM, що робить sync-записи, перетворюється на хост, що робить sync-записи, помножені на кожного гостя. Один гучний орендар, чутливий до довговічності, може домінувати над затримками.
- Помилки в порядку записів раніше були звичними у файлових системах і контролерах. Дизайн ZFS (copy-on-write + контрольні суми) не знімає потребу в sync, але робить корупцію легшою для виявлення і складнішою для приховання.
Три режими: standard, always, disabled
Властивість sync налаштовується на рівні набору даних (файлова система або zvol). Має три значущі значення:
1) sync=standard (за замовчуванням)
Це означає: шанувати запит викликача. Якщо додаток виконує синхронні записи або викликає fsync()/fdatasync(), ZFS фіксує наміри в ZIL і тільки потім повідомляє про успіх.
Операційно: це режим «зробити те, що просив додаток». Якщо тут продуктивність погана, це реальний сигнал: ваше навантаження просить стійкості, а шлях збереження не може її швидко забезпечити.
2) sync=always
Це примушує всі записи трактувати як синхронні, навіть якщо викликач цього не просив.
Коли використовувати: коли ви не довіряєте навантаженню або проміжному ПЗ коректно запитувати sync, але вам все ще потрібна довговічна поведінка. Іноді застосовується для NFS-експортів або певних образів VM, де ви хочете гарантувати «безпеку на рівні хоста», незалежно від налаштувань гостя.
Компроміс: якщо у вас немає швидкого, безпечного SLOG, ви можете перетворити пристойний пул на музей затримок.
3) sync=disabled
Це каже ZFS трактувати синхронні запити як асинхронні. Воно підтвердить sync-записи до того, як вони насправді опиняться на стійкому сховищі.
Коли використовувати: для даних, які ви готові втратити при збої (тимчасові простори, кеші, проміжні результати аналітики), або в дуже специфічних архітектурах, де довговічність обробляється в іншому місці (наприклад, додаток має власний реплікований лог підтверджень і ви свідомо погоджуєтесь на локальні втрати).
Ризик: будь-який додаток, яке вважає, що отримало надійний коміт, може помилитися. Це включає бази даних, файлові системи VM і клієнтів NFS, які роблять безпечні записи.
Другий жарт, і потім повертаємося до серйозного: встановити sync=disabled на томі для бази даних — це як вставити слово «ймовірно» посеред вашого фінансового журналу: аудиторам це не сподобається.
Хто запитує синхронні записи: додатки, бази даних, NFS, гіпервізори
Більшість драм про продуктивність навколо sync походить від нерозуміння того, хто просить синхронної семантики і навіщо.
Бази даних
Бази даних часто перетворюють «транзакція підтверджена» на fsync() на журналі записів (WAL) або redo-журналі. Журнал — це більш-менш послідовний потік, але вимога жорстка: коли база каже «commit», журнал має пережити збій. Якщо ZFS потребує 5 мс, щоб це виконати, латентність коміту бази буде щонайменше 5 мс, навіть якщо все інше швидке.
Деякі СУБД можуть послабити це (наприклад, режими «async commit»), але це рішення на рівні додатку. Сховище не повинно непомітно змінювати значення «commit» без вашого відома.
NFS
Клієнти NFS часто запитують стабільні записи, і сервери повинні їх шанувати. На серверах NFS із ZFS це означає, що шлях ZIL/SLOG стає гарячою дорогою. Можна мати шалено швидкий пул для асинхронної пропускної здатності і при цьому отримати жахливу затримку NFS, якщо sync-коміти повільні.
Віртуалізація (zvol, образи VM)
Гіпервізори та файлові системи гостя можуть генерувати несподівано багато синхронних операцій — оновлення метаданих, коміти журналів, барʼєри, flush. Одна «безпечна» настройка в гості може перетворитися на постійні flush-і на хості, і ці flush-и мапляться безпосередньо на шлях ZIL.
Ось чому ви почуєте класичну скаргу: «Мій SSD-пул швидкий, але хост VM відчувається повільним». Часто пул у порядку для масових записів, але латентність sync-записів погана.
Шлях синхронного запису в ZFS: TXGs, ZIL, SLOG і що реально потрапляє на стійке сховище
ZFS записує дані групами транзакцій (TXG). Зміни накопичуються в памʼяті і періодично фіксуються на диску пакетами. Це пакетування робить ZFS ефективним: воно перетворює багато дрібних випадкових записів на більш впорядковані операції вводу/виводу.
Синхронні запити ускладнюють цю модель. Додаток не може чекати наступного коміту TXG (який може статися через секунди). Тому ZFS використовує ZIL: журнал намірів, що фіксує достатньо інформації для відтворення операції після збою. ZIL записується швидко, після чого sync-запис може бути підтверджений. Пізніше, коли TXG комітиться, реальні дані потрапляють у фінальні на-дискові структури, а записи ZIL стають застарілими.
Ключова операційна істина: ZIL читається лише під час відновлення після краху. За звичайної роботи його записують, а не читають. SLOG-пристрій не потрібен для покращення звичайних операцій читання; він існує, щоб приймати дрібні, чутливі до затримки sync-записи швидко і надійно.
Ще одна істина: якщо у вас немає окремого SLOG, блоки ZIL живуть на основному пулі. Це може бути прийнятно на дуже швидких низьколатентних пулах — особливо all-flash з захистом від втрати живлення. На повільніших пулах (обертальні диски або SSD з поганою латентністю під sync-записами) це може бути жорстоко.
Реалії SLOG: що він прискорює, а що не може
Люди купують SLOG з тієї ж причини, що купують кращу каву: вони хочуть, щоб ранки були менш болючими. Але SLOG — не чудо-пристрій. Він прискорює одну річ: латентність підтвердження синхронних записів.
Чому SLOG допомагає
- Навантаження NFS з великою кількістю sync, де вузьке місце — латентність коміту.
- Бази даних, де критична латентність коміту (і де СУБД наполягає на довговічних комітах).
- Кластери VM, де flush-и часті і блокують роботу.
Чого SLOG не прискорює
- Латентність читання або IOPS для читання (це вже зона ARC/L2ARC, і там теж є нюанси).
- Асинхронну пропускну здатність масових записів (це здебільшого роль основних vdev і поведінки TXG).
- Навантаження, яке майже не робить sync-записів; ви нічого не відчуєте.
Що робить пристрій хорошим SLOG
Дві властивості: низька латентність під sync-записами і захист від втрати живлення. Ви хочете, щоб пристрій підтверджував записи тільки тоді, коли дані насправді в безпечному стані. Побутові SSD можуть бути швидкими, але можуть «боятись» flush і брехати про довговічність. Корпоративні SSD (або пристрої, призначені для логування) зазвичай справляються краще, бо мають конденсатори і прошивку, адаптовану під таке завдання.
Розмір — не головне. SLOG має містити коротке вікно непідтверджених sync-транзакцій — зазвичай секунди, а не весь набір даних. Ви купуєте не ємність, а передбачувану латентність.
Дзеркалення SLOG
Якщо SLOG-пристрій відмовить, пул може продовжити роботу (ZFS може відкотитись), але ви ризикуєте втратити останні підтверджені синхронні транзакції, якщо лог-пристрій загине невчасно. На практиці багато команд дзеркалять SLOG з обґрунтованою параною — особливо на спільному сховищі для VM або баз даних.
Три міні-історії з корпоративного життя (реалістичні бойові історії)
Міні-історія №1: Інцидент через хибне припущення
Команда зберігання успадкувала кластер NFS на ZFS, що обслуговував build farm і кілька внутрішніх сервісів. Зʼявився новий сервіс: stateful черга, яка постійно записувала дрібні повідомлення і покладалася на синхронні коміти для коректності. Усі вважали, що «це як інші додатки», бо воно жило в тому ж Kubernetes і використовувало той самий клас NFS.
Але не було. Сервіс черги вимагав стабільних записів, і латентність з «нормальної» стала «що відбувається» за ніч. Збірки почали таймаутитися в несподіваних місцях. Команду мереж залучили через те, що графіки затримок NFS виглядали як втрата пакетів. SRE перезапускав демони, потім вузли, потім сумнівався в реальності.
Після кількох годин нічної боротьби хтось запустив zpool iostat -v 1 і помітив маленький пристрій (єдиний SLOG) з високою кількістю операцій запису і страшною латентністю, в той час як основний пул мав запас. SLOG був старим споживчим SATA SSD — швидким у бенчмарках, жахливим під тривалими sync-записами і, ймовірно, не коректно обробляв flush. Він став вузьким місцем і джерелом хвостової латентності.
Виправлення було банальним: замінити SLOG на належний низьколатентний пристрій з захистом від втрати живлення і зробити дзеркало. Продуктивність стабілізувалась негайно. Постмортем не про пошук винних, а про припущення: середовище змінилось з «переважно асинхронні артефакти збірки» на «синхронне навантаження, що вимагає коректності», а налаштування зберігання не встигли змінитись.
Міні-історія №2: Оптимізація, що дала зворотний ефект
Команда віртуалізації мала пул ZFS для дисків VM (zvol). Новий кластер вийшов у продакшн і під навантаженням показав гіршу продуктивність, ніж старий — хоча апарат був новішим. Хтось знайшов блог із пропозицією sync=disabled для «масового приросту продуктивності» на VM-сховищі. Вони тестували на staging з синтетичним IO і отримали прекрасні результати.
Тому впровадили поступово. Приріст був реальний: латентність комітів впала, IO wait зменшився, орендарі перестали скаржитися. Відчуття героя — поки не стався перший реальний випадок відключення живлення. Не катастрофа в дата-центрі, а просто відключення пристрою на час обслуговування, що відключило стійку. Хости перезавантажилися, пул імпортувався чисто, і більшість VM піднялися нормально.
Але кілька — ні. Файлові системи були пошкоджені так, що журнал не виправив. Одна база даних піднялася, але залишилася без останніх кількох хвилин підтверджених транзакцій — транзакцій, які додаток уже підтвердив upstream. «Швидка» настройка непомітно змінила значення «commit» всередині гостей. Це спричинило логічну корупцію: не зламані блоки, а порушена бізнес-правда.
Відкат був простим. Прибирання — ні. Довелося звірятися з журналами upstream і повторно обробляти події. У фінальному звіті висновок був не «ніколи не налаштовувати ZFS», а такий: якщо ви вимикаєте sync на зберіганні VM, ви берете на себе обіцянку довговічності від імені кожного гостя, і краще мати архітектуру, що це витримає. Інакше ваш бенчмарк — лише фокус із довірою.
Міні-історія №3: Нудна, але правильна практика, яка врятувала день
Команда фінансових послуг експлуатувала пару серверів ZFS, що експортували NFS до кластера додатків. У них була клопітка, але корисна звичка: перед кожним квартальним піком трафіку вони проводили «тренування довговічності». Це було просто: перевірити властивості наборів даних sync, перевірити здоровʼя SLOG, підтвердити, що flush-и працюють як очікується, і провести контрольований симульований відрив живлення в лабораторії на такому ж класі апаратури.
Інженери скаржились, що це культ. Нічого не ламалось під час тренувань. Це і був сенс. Це було еквівалентом перевірки парашута на землі.
Потім стався реальний інцидент: баг у прошивці почав повідомляти один із лог-пристроїв як здоровий, хоча він мовчки таймаутував під певними рівнями завантаження. ZFS не одразу його відфолтила, але латентність зростала, коли навантаження ставало синхронним. Оскільки команда мала базові цифри латентності з попередніх тренувань, вони швидко виявили відхилення і не витратили ніч на пошук причин у NFS, мережі або додатках.
Під час вікна техобслуговування вони замінили пару SLOG, і кластер повернувся до норми. Ніяких втрат даних, ніякої загадки. Це була нудна інженерія — саме те, що потрібно, коли гроші на кону.
Практичні завдання: команди, що шукати та як інтерпретувати
Команди нижче припускають типовий OpenZFS-оточення на Linux. Підлаштуйте імена пулів/наборів даних під вашу систему. Кожне завдання включає те, що означає вивід на практиці.
Завдання 1: Знайти налаштування sync наборів даних (і успадкування)
cr0x@server:~$ zfs get -r -o name,property,value,source sync tank
NAME PROPERTY VALUE SOURCE
tank sync standard default
tank/vm sync disabled local
tank/vm/critical sync standard inherited from tank
tank/nfs sync standard local
Інтерпретація: Не дивіться лише на корінь пулу. Один «корисний» набір даних з sync=disabled може ховатися в ієрархії VM. Стовпець source — ваш детектор правди: local проти inherited проти default.
Завдання 2: Перевірити, чи є у вас SLOG (і який він)
cr0x@server:~$ zpool status -v tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 00:18:42 with 0 errors on Mon Dec 16 03:10:05 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
logs
mirror-1 ONLINE 0 0 0
nvme2n1 ONLINE 0 0 0
nvme3n1 ONLINE 0 0 0
errors: No known data errors
Інтерпретація: Розділ logs — це ваш SLOG. Якщо його немає, ZIL живе на основних vdev. Якщо це один пристрій (не дзеркало), вирішіть, чи готові ви терпіти такий профіль ризику.
Завдання 3: Спостерігати латентність по vdev під навантаженням
cr0x@server:~$ zpool iostat -v tank 1
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 1.20T 2.40T 110 980 8.5M 72.1M
mirror-0 1.20T 2.40T 110 220 8.5M 15.4M
nvme0n1 - - 60 120 4.2M 7.8M
nvme1n1 - - 50 100 4.3M 7.6M
logs - - - -
mirror-1 - - 0 760 0K 56.7M
nvme2n1 - - 0 380 0K 28.4M
nvme3n1 - - 0 380 0K 28.3M
-------------------------- ----- ----- ----- ----- ----- -----
Інтерпретація: Якщо лог-пристрої несуть більшість операцій запису, а основні vdev спокійні — ваше навантаження синхронно-орієнтоване. Якщо продуктивність погана, SLOG — перший підозрюваний.
Завдання 4: Підтвердити, що ZFS бачить правильний ashift (вирівнювання розміру секторів)
cr0x@server:~$ zdb -C tank | grep -E "ashift|vdev_tree" -n | head
52: vdev_tree:
83: ashift: 12
121: ashift: 12
Інтерпретація: ashift=12 означає 4K сектори. Неправильне вирівнювання (забагато занадто мале ashift) може створювати ампліфікацію записів і жахливу латентність, включно для sync-трафіку.
Завдання 5: Перевірити здоровʼя пулу ZFS та лічильники помилок
cr0x@server:~$ zpool status tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 00:18:42 with 0 errors on Mon Dec 16 03:10:05 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
errors: No known data errors
Інтерпретація: Налагодження продуктивності sync на пулі з латентними помилками — як налаштовувати двигун з поламаною маслянною помпою. Виправте цілісність перш за все.
Завдання 6: Виявити викликачів sync, спостерігаючи активність fsync (Linux)
cr0x@server:~$ sudo perf trace -e fsync,fdatasync,openat -a --duration 10
0.000 ( 0.008 ms): postgres/1931 fdatasync(fd: 7) = 0
0.012 ( 0.006 ms): postgres/1931 fdatasync(fd: 7) = 0
0.030 ( 0.010 ms): qemu-kvm/2210 fsync(fd: 31) = 0
0.044 ( 0.009 ms): qemu-kvm/2210 fsync(fd: 31) = 0
Інтерпретація: Ви дивитесь на частоту. Якщо бачите тисячі sync-викликів за секунду, ваш бюджет латентності витрачається на довговічність.
Завдання 7: Виміряти латентність sync-записів за допомогою fio (прямий, схожий на sync)
cr0x@server:~$ fio --name=syncwrite --filename=/tank/test/syncwrite.bin \
--rw=write --bs=4k --iodepth=1 --numjobs=1 --direct=1 \
--fsync=1 --size=1G --runtime=30 --time_based=1
syncwrite: (g=0): rw=write, bs=4K-4K, ioengine=psync, iodepth=1
...
write: IOPS=6200, BW=24.2MiB/s (25.4MB/s)(726MiB/30001msec)
clat (usec): min=90, max=9200, avg=160.4, stdev=210.7
Інтерпретація: --fsync=1 змушує flush після кожного запису, імітуючи найгіршу поведінку комітів. Середня латентність — приємна; але максимум і хвости — те, що відчувають користувачі.
Завдання 8: Порівняти поведінку з sync=disabled на тестовому наборі даних
cr0x@server:~$ sudo zfs create tank/test_nodur
cr0x@server:~$ sudo zfs set sync=disabled tank/test_nodur
cr0x@server:~$ fio --name=syncwrite --filename=/tank/test_nodur/syncwrite.bin \
--rw=write --bs=4k --iodepth=1 --numjobs=1 --direct=1 \
--fsync=1 --size=1G --runtime=15 --time_based=1
...
write: IOPS=42000, BW=164MiB/s (172MB/s)(2462MiB/15001msec)
clat (usec): min=18, max=480, avg=22.7, stdev=7.1
Інтерпретація: Ця різниця демонструє, що ви віддаєте: підтвердження довговічності. Ставтеся до цього результату як до діагностичного інструмента, а не як до «рішення». Якщо єдиний спосіб стати швидким — брехати, справжній шлях — покращити sync-шлях (часто SLOG).
Завдання 9: Перевірити, чи використовують набори даних zvol (поширено для VM-зберігання)
cr0x@server:~$ zfs list -t volume -o name,volsize,volblocksize,sync,logbias
NAME VOLSIZE VOLBLOCKSIZE SYNC LOGBIAS
tank/vm-001 120G 16K standard latency
tank/vm-002 200G 16K disabled latency
Інтерпретація: zvol часто несуть IO шаблони VM. Зверніть увагу на несподівані sync=disabled. Також зауважте volblocksize — він впливає на ампліфікацію IO і латентність.
Завдання 10: Перевірити logbias (пріоритет латентності проти пропускної здатності)
cr0x@server:~$ zfs get -r logbias tank/vm
NAME PROPERTY VALUE SOURCE
tank/vm logbias latency default
Інтерпретація: logbias=latency заохочує використання лог-пристрою для sync-записів. throughput може зменшити використання лога у деяких випадках. Це не замінює коректного sync, але може впливати на поведінку для певних навантажень.
Завдання 11: Підтвердити компресію та recordsize (вони можуть опосередковано змінити історію sync)
cr0x@server:~$ zfs get compression,recordsize tank/nfs
NAME PROPERTY VALUE SOURCE
tank/nfs compression lz4 local
tank/nfs recordsize 128K default
Інтерпретація: Компресія може зменшити фізичний IO (часто добре), але збільшує навантаження на CPU. Якщо ваша проблема «sync повільний» фактично через насичення CPU під час комітів TXG, ви будете ганятися за неправильним винуватцем, якщо не виміряєте.
Завдання 12: Перевірити реальний тиск CPU і IO wait під час sync-штурмів
cr0x@server:~$ vmstat 1 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 712344 89244 3821000 0 0 8 420 980 1900 12 6 78 4 0
5 3 0 701112 89244 3818200 0 0 0 8200 1200 2400 10 7 55 28 0
3 2 0 700980 89244 3818500 0 0 0 7900 1180 2300 11 7 56 26 0
Інтерпретація: Зростання wa (IO wait) під час sync-періодів вказує, що шлях зберігання блокує CPU. Якщо wa низький, але латентність висока, можливо, ви маєте черги, поведінку flush пристрою або насичений лог-пристрій.
Завдання 13: Виявити файлові системи по мережі, що нав’язують семантику sync (ракурс сервера NFS)
cr0x@server:~$ sudo nfsstat -s
Server rpc stats:
calls badcalls badfmt badauth badclnt
18233990 0 0 0 0
Server nfs v4:
null compound
0 11239821
Server nfs v3:
null getattr setattr lookup access
0 226001 8402 110240 90412
commit write create mkdir remove
340882 901220 4800 220 1900
Інтерпретація: Висока активність NFS commit — це підказка: клієнти вимагають стабільних записів. Якщо коміти часті і повільні, ваш шлях ZIL/SLOG має більше значення, ніж масова пропускна здатність.
Завдання 14: Переконатися, що лог-пристрої дійсно працюють
cr0x@server:~$ iostat -x 1 5 | egrep 'nvme2n1|nvme3n1|nvme0n1'
nvme2n1 0.00 740.00 0.00 56000.00 0.00 74.20 0.02 0.35 3.10 0.20 74.9
nvme3n1 0.00 735.00 0.00 55800.00 0.00 73.80 0.02 0.34 3.00 0.19 75.1
nvme0n1 55.00 120.00 8200.00 15400.00 3.40 15.30 0.10 0.80 2.10 0.40 25.0
Інтерпретація: Якщо лог-пристрої показують високу швидкість запису і високу завантаженість, вони в гарячій дорозі. Якщо під sync-навантаженням вони майже неактивні, або навантаження не синхронне, або набір даних налаштований інакше, ніж ви думаєте.
Швидкий план діагностики (що перевірити першим, другим, третім)
Коли «ZFS повільний» дзвонить у ваш пейджер, часу на філософію немає. Потрібна послідовність триажу, яка швидко знайде вузьке місце.
Перше: Визначте, чи проблема повʼязана з sync
- Перевірте властивості наборів даних
syncу гарячій зоні (zfs get -r syncдля відповідних наборів даних/zvol). - Спостерігайте
zpool iostat -v 1і шукайте домінування записів на лог-пристроях (або основні vdev, що борються з дрібними записами). - На Linux — зніміть частоту
fsync/fdatasyncза допомогоюperf trace(або журнали/метрики додатку).
Рішення: Якщо бачите часті sync-виклики і високу активність/латентність лога, це вузьке місце sync-шляху. Якщо ні, не звинувачуйте sync марно.
Друге: Знайдіть chokepoint (SLOG vs main vdevs vs CPU)
- Якщо є SLOG: перевірте клас пристрою, здоровʼя і завантаженість. Використовуйте
iostat -xіzpool iostat -v, щоб побачити, чи він насичений. - Якщо SLOG немає: перевірте латентність основних vdev під синхронним навантаженням. Обертальні диски під sync-записами можуть виглядати як «випадкові зависання» для додатків.
- Перевірте насичення CPU і IO wait (
vmstat,top). Завантажена система може змусити виглядати, що sync-коміти — це проблема з диском, коли насправді причина в плануванні та конкуренції.
Третє: Підтвердьте очікування щодо довговічності перед «виправленням» продуктивності
- Визначте клас навантаження: база даних, диски VM, домашні каталоги NFS, кеш збірок, тимчасові дані тощо.
- Запитайте: яке допустиме вікно втрат при раптовому відключенні живлення? «Жодне» — також валідна відповідь.
- Лише після цього розгляньте зміни: додати SLOG, дзеркалити його, відрегулювати властивості наборів даних або (в рідких випадках) вимкнути sync для дійсно відкиданих даних.
Типові помилки (з конкретними симптомами та виправленнями)
Помилка 1: Вимкнення sync на VM або бази даних «бо повільно»
Симптоми: Бенчмарки та латентність різко покращуються; пізніше, після збою або відключення живлення, з’являється корупція файлової системи, відсутні підтверджені транзакції БД або неконсистентний стан додатка.
Виправлення: Відновити sync=standard (або always, якщо доречно). Інвестувати в належний SLOG і/або зменшити тиск sync на рівні додатка через підтримувані настройки (з явним прийняттям ризику).
Помилка 2: Купити SLOG, що швидкий, але не безпечний при відключенні живлення
Симптоми: Велика продуктивність; пізніше незрозумілі проблеми з цілісністю даних після раптового відключення живлення; або виявлення, що пристрій ігнорує flush.
Виправлення: Використовуйте пристрої з захистом від втрати живлення і прогнозованою латентністю при тривалих записах. Дзеркальте SLOG, коли навантаження критичне щодо цілісності.
Помилка 3: Очікування, що SLOG прискорить усе
Симптоми: Додали SLOG і не побачили покращення; або лише невелике; користувачі все ще скаржаться на затримки читання.
Виправлення: Підтвердіть, що проблема — у sync-записах. Якщо навантаження читальне, зосередьтесь на розмірі ARC, кількості vdev, recordsize і продуктивності пристроїв під читання — а не на SLOG.
Помилка 4: Налаштування без вимірювання хвостової латентності
Симптоми: Середня латентність виглядає нормально; користувачі жаліються на паузи; паузи VM; сплески латентності комітів баз даних.
Виправлення: Вимірюйте і графікивайте перцентилі (p95/p99). Вузькі місця sync часто виявляються як хвостова латентність через черги та шторми flush.
Помилка 5: Змішування «критичних» і «відкиданих» даних під одним політикою
Симптоми: Хтось встановив sync=disabled для кеш-каталогу і випадково застосував його до батьківського набору даних, що використовується реальними даними; або успадкування змінилося після рефакторингу.
Виправлення: Використовуйте окремі набори даних з явними властивостями. Підтверджуйте за допомогою zfs get -r -o name,property,value,source і впровадьте перевірки в процес provision.
Помилка 6: Ігнорування того, що NFS-семантика може нав’язувати sync-поведінку
Симптоми: Клієнти NFS показують високу латентність; CPU/мережа сервера виглядають нормально; пропускна здатність сховища не на максимумі; але операції блокуються.
Виправлення: Перевірте шаблони commit/write клієнтів NFS і переконайтесь, що шлях sync сервера швидкий і безпечний (SLOG + правильні пристрої). Не «виправляйте» це відключенням sync, якщо дані дійсно не підлягають втраті.
Контрольні списки / покроковий план
Контрольний список A: Визначити правильний режим sync для кожного набору даних
- Класифікуйте дані: критичний стан, дані користувачів, база даних, образи VM, кеш, тимчасове, репліковане тимчасове.
- Визначте допустимі втрати при краху: жодні, секунди, хвилини, «не має значення». Запишіть це.
- Встановіть
sync=standardдля більшості реальних даних. - Розгляньте
sync=alwaysтільки коли вам потрібно примусово забезпечувати довговічність незалежно від викликача. - Використовуйте
sync=disabledлише для явно відкиданих наборів даних (і тримайте їх ізольованими).
Контрольний список B: Додавання SLOG безпечно (коли обґрунтовано)
- Доведіть, що ви обмежені sync: виміряйте частоту
fsyncі використання ZIL/SLOG. - Обирайте пристрої з захистом від втрати живлення і передбачуваною латентністю під тривалими записами.
- Дзеркальте SLOG для важливих навантажень.
- Додайте його і валідируйте на реальному навантаженні, а не лише на синтетичному тесті пропускної здатності.
Покроково: Реалізація виділеного набору «безпечний швидкий sync»
Це поширений підхід для NFS-експортів або томів баз даних, де потрібна довговічність з розумною продуктивністю.
cr0x@server:~$ sudo zfs create tank/prod_safe
cr0x@server:~$ sudo zfs set sync=standard tank/prod_safe
cr0x@server:~$ sudo zfs set logbias=latency tank/prod_safe
cr0x@server:~$ sudo zfs set atime=off tank/prod_safe
cr0x@server:~$ sudo zfs set compression=lz4 tank/prod_safe
cr0x@server:~$ zfs get -o name,property,value,source sync,logbias,atime,compression tank/prod_safe
NAME PROPERTY VALUE SOURCE
tank/prod_safe sync standard local
tank/prod_safe logbias latency local
tank/prod_safe atime off local
tank/prod_safe compression lz4 local
Інтерпретація: Це не «гарантує швидкість», але вирівнює поведінку ZFS з низьколатентною sync-стратегією, зберігаючи довговічність.
Покроково: Створити явно відкиданий набір даних (і маркувати його як радіоактивний)
cr0x@server:~$ sudo zfs create tank/scratch_ephemeral
cr0x@server:~$ sudo zfs set sync=disabled tank/scratch_ephemeral
cr0x@server:~$ sudo zfs set compression=off tank/scratch_ephemeral
cr0x@server:~$ sudo zfs set atime=off tank/scratch_ephemeral
cr0x@server:~$ zfs get -o name,property,value,source sync,compression tank/scratch_ephemeral
NAME PROPERTY VALUE SOURCE
tank/scratch_ephemeral sync disabled local
tank/scratch_ephemeral compression off local
Інтерпретація: Зробіть зону ураження очевидною. Тримайте її поза шляхами успадкування, що використовуються реальними даними.
Питання й відповіді
1) Чи означає sync=disabled «я можу втратити останні кілька секунд»?
Може бути гірше. Ви можете втратити дані, які додаток вважав безпечно підтвердженими. Це може спричинити логічну корупцію: база даних або сервіс може підтвердити транзакцію і потім «забути» її після збою. «Кілька секунд» — не надійна межа, якщо весь стек не спроектовано з урахуванням цієї моделі відмови.
2) Якщо у мене є UPS, чи можу я безпечно вимкнути sync?
UPS зменшує ризик, але не усуває його. Kernel panic, скиди контролера, помилки прошивки, випадкові відключення живлення і відмова подвійного джерела живлення все ще трапляються. Також UPS не допоможе, якщо пристрій бреше про завершення flush. Якщо вам потрібні гарантії довговічності, розглядайте UPS як багаторівневий захист, а не як заміну.
3) Чи потрібен SLOG на all-NVMe пулі?
Не завжди. Деякі NVMe-пули мають настільки низьку латентність, що ZIL на пулі — достатньо. Вирішальний фактор — латентність sync-запису під вашим навантаженням і поведінка пристроїв під flush. Виміряйте перед покупкою обладнання.
4) Чи має SLOG бути великим?
Зазвичай ні. SLOG містить короткочасний журнал sync-операцій до коміту TXG. Важливіше стабільність латентності і безпека при відключенні живлення, ніж ємність. Надмірне збільшення розміру — поширене і в більшості випадків безпечне, але рідко воно вирішує вузьке місце.
5) У чому різниця між ZIL і SLOG знову?
ZIL — це механізм: журнал намірів, що використовується для задоволення sync-семантики. SLOG — це пристрій: виділене місце для збереження записів ZIL, ідеально швидше та безпечніше за основний пул для цього сценарію запису.
6) Чому NFS повільний на моєму сервері ZFS, хоча локальні записи швидкі?
Клієнти NFS часто запитують стабільні записи. Локальне тестування часто робить буферизований/асинхронний IO, що не примушує flush. Якщо ваш шлях ZIL/SLOG повільний, латентність NFS буде виглядати жахливо, хоча масова пропускна здатність здається нормальною.
7) Чи sync=always безпечніше за sync=standard?
Може бути, у тому сенсі, що воно примушує довговічність, навіть якщо додаток не просить її. Але воно також може спричинити суттєві штрафи продуктивності. Використовуйте його тоді, коли є конкретна причина не довіряти викликачам — і коли ваш sync-шлях (SLOG або основний пул) може це витримати.
8) Чи можна «полагодити» latency sync зміною recordsize або компресією?
Іноді опосередковано. Латентність sync часто повʼязана з поведінкою flush/коміту і латентністю пристрою. Але якщо коміти TXG створюють зворотний тиск, CPU і ампліфікація записів можуть мати значення. Не гаджуйте: вимірюйте латентність викликів sync, латентність пристроїв і поведінку TXG разом.
9) Якщо я дзеркалю SLOG, чи це подвоїть латентність?
Це може дещо збільшити її, бо записи мають бути підтверджені обома пристроями. Але з належними низьколатентними пристроями дзеркальний SLOG часто все ще значно швидший за лог на повільних основних vdev — і підвищує стійкість проти відмови лог-пристрою.
10) Яке найзручніше для оператора правило «на око»?
Якщо навантаження подало б баг, втративши «підтверджений» запис, не використовуйте sync=disabled. Натомість зробіть sync швидким чесним шляхом: хороші пристрої, належний SLOG (за потреби) і дизайн наборів даних, що враховує профіль навантаження.
Висновок
Властивість ZFS sync — одне з тих налаштувань, що виглядає як чит-код, бо може таким здаватися. Водночас воно може стати пасткою. Ця властивість не про «зробити ZFS швидшим». Вона про те, чи ZFS шануватиме контракт довговічності викликача — або тихо його змінить.
Продакшн-мислення — трактувати sync як політику, а не як хак для налаштування. Почніть із виявлення того, хто просить синхронну семантику і чому. Вимірюйте шлях ZIL/SLOG, а не лише масову пропускну здатність. Якщо вам потрібна продуктивність і правдивість підтверджень, інвестуйте в належний шлях синхронного запису і підтримуйте налаштування у відповідності з бізнес-обіцянками, які дають ваші системи.