ZFS дзеркала: конфігурація, яка робить випадкові операції вводу‑виводу схожими на NVMe

Було корисно?

Є певний вид задоволення, який можна відчути лише в продуктивному середовищі: коли робоче навантаження, що раніше відчувалося ніби ви тягнете холодильник по гравію, раптом прокидається. CPU перестає простоювати. База даних перестає скаржитися. Діаграми затримок перестають виглядати як сейсмограф. Ви не купували нові сервери. Ви не переписували додаток. Ви змінили структуру зберігання.

ZFS дзеркала — це часто саме та зміна, більше ніж люди очікують. Не тому, що дзеркала — це магія, а тому, що вони відповідають фізиці дисків і математиці черг. Дзеркала перетворюють випадкові читання на задачу, що допускає паралелізм, і більшість реальних «моє сховище повільне» інцидентів по суті є проблемою затримки випадкових читань. Якщо ви коли‑небудь бачили, як пул RAIDZ чудово справляється з послідовною пропускною здатністю, а база даних все одно таймаутиться — ласкаво просимо. Це пояснення того, чому дзеркала можуть зробити випадкові I/O відчутними як NVMe — без претензій, що вони такими і є.

Чому дзеркала відчуваються швидкими (і коли ні)

Дзеркала перемагають у випадкових читаннях з однієї нудної, але потужної причини: вони дають ZFS вибір. Для кожного блоку, що зберігається на двох (або трьох) дисках, ZFS може обрати, яку копію читати. Це не лише надмірність — це свобода планування. На одному диску випадкові читання стають чергою і чекають своєї черги. У дзеркалі ZFS може відправляти різні читання на різні учасники і може обходити диск, що має поганий день (або просто завантажений).

На практиці vdevи‑дзеркала поводяться як «підсилювачі IOPS» для читань. Пул, побудований з кількох mirror vdev, множить це ще й тому, що ZFS розподіляє дані по vdev. В результаті база даних з великою кількістю дрібних читань може бачити падіння затримок, коли ви переходите від широкого RAIDZ vdev до кількох mirror vdev, навіть якщо загальна кількість дисків залишається тією самою.

Записи — інша історія. Для простого 2‑way mirror кожен запис має записатися на обох членах. Це означає, що запис на дзеркалі не швидший за один диск у тому ж vdev (ігноруючи поведінку ZIL/SLOG). Але паралелізм на рівні пулу все ще допомагає: якщо у вас багато mirror vdev, ваші записи розподіляються між ними. Тому ви можете отримати хорошу пропускну здатність запису від багатьох дзеркал, але один mirror vdev не подвоює записні IOPS магічно.

Ключова ментальна модель: продуктивність ZFS визначається кількістю і типом vdev, а не кількістю дисків. Дзеркала зазвичай розгортають як багато маленьких vdev (2‑дискові дзеркала, іноді 3‑дискові), що збільшує кількість vdev і дає ZFS більше незалежних черг.

А коли дзеркала не відчуваються швидкими? Коли ваш вузький місце не в дисках. Якщо ви насичуєте одну HBA‑чергу, якщо CPU зайнятий контрольними сумами або стисненням з не підходящим алгоритмом, якщо мережа є обмеженням, або якщо навантаження складається в основному з синхронних записів без належного SLOG, дзеркала вам не допоможуть. Вони все одно будуть правильними. Просто не стануть героями.

Жарт №1: Дзеркало — як ротація сторожів: надмірність не робить роботу невидимою, вона просто гарантує, що хтось інший може підняти трубку.

Факти й історія, що знадобляться о 3‑й ранку

Декілька контекстних пунктів, коротких, конкретних і дивно корисних, коли ви аргументуєте проєктну зміну на зустрічі, де хтось все ще вважає, що RAID5 — відповідь на все:

  1. ZFS народився в Sun у середині 2000‑х як цілісна файловa система + менеджер томів, спроєктований для виявлення та виправлення «тихої» корупції з контрольними сумами на кожному рівні.
  2. RAIDZ існує тому, що у традиційного RAID був write hole: RAID на паритеті міг підтвердити запис, який не був повністю зафіксований при втраті живлення, залишаючи мовчазну невідповідність. Транзакційна модель ZFS зменшує цей клас помилок.
  3. «Vdev — одиниця продуктивності» — це не лозунг, а те, як ZFS планує IO. ZFS розподіляє алокації по верхньому рівню vdev, а не по дисках всередині vdev так, як це показують класичні RAID‑контролери.
  4. Дзеркала дають вибір для читань: ZFS може обрати менш завантажену ногу дзеркала і може використовувати історію затримок, щоб віддавати перевагу швидшому члену.
  5. Сучасні диски з 4K‑секторами змінили правила гри: неправильний параметр ashift може назавжди штрафувати дрібні записи через read‑modify‑write. Це б’є й по дзеркалах, але паритетні vdev страждають сильніше.
  6. SSD зробили «випадкові читання» нормою: бази даних і кластери пошуку почали очікувати низької латентності, і HDD‑паритетні масиви стали відставати в таких навантаженнях.
  7. L2ARC ніколи не був магічним SSD‑рівнем: він може допомогти набору читань, що не вміщується в RAM, але споживає RAM для метаданих і не вирішує проблему затримок запису.
  8. SLOG — це не кеш запису: це окремий лог‑пристрій для синхронних записів; він прискорює затримку підтвердження (commit latency), а не масову пропускну здатність.
  9. Поведінка resilver різниться: дзеркала часто пересирають швидше за широкі паритетні vdev, бо можуть копіювати лише виділені блоки (залежно від платформи/функцій) і математика відновлення простіша.

Архітектура дзеркал: vdev, черги та «математика IOPS»

Що насправді робить ZFS, коли ви створюєте дзеркала

Пул ZFS (zpool) складається з одного або кількох топ‑рівневих vdev. Ці vdev можуть бути:

  • одиноким диском (не робіть цього в продакшені, якщо вам не подобається біль),
  • дзеркалом (2‑way, 3‑way …),
  • групою RAIDZ (raidz1/2/3).

Коли ви будуєте пул з кількох топ‑рівневих vdev, ZFS розподіляє алокації між ними. Це те саме, що смуга (stripe). Це не фіксований RAID0‑stripe, як у контролера; це розподіл на основі алокацій, але ефект схожий: більше vdev — більше незалежних IO‑черг.

Чому дзеркала допомагають при випадкових читаннях

Навантаження на випадкові читання (бази даних, образи VM, поштові сервери, CI‑кеші, файлові системи з великою кількістю метаданих) домінуються переміщенням голівок/затримкою на HDD і глибиною черги/затримкою на SSD. У дзеркалі кожне читання може обслуговуватися будь‑яким членом. ZFS може:

  • відправляти одночасні читання на різні гілки дзеркала,
  • віддавати перевагу диску з коротшою чергою,
  • уникати диска, що повертає помилки або займає більше часу, ніж очікувалося.

Якщо у вас N mirror vdev, у вас N незалежних черг vdev. Для випадкових читань у вас також є дві можливі шпинделі на венд‑vdev. Отже з’являються два типи паралелізму: між vdev і всередині кожного vdev (вибір гілки). Поєднаний ефект може виглядати драматично в порівнянні з одним широким RAIDZ vdev, який має одну vdev‑чергу і має зачіпати кілька дисків для кожної операції.

Але чи «подвоюють IOPS» дзеркала?

Для читань дзеркала можуть наблизитися до 2× read IOPS на vdev за правильних умов, бо читання можна розподіляти між гілками. У реальному житті це менш ідеально: кешування, preftech, розміри запитів і те, що деякі читання послідовні, зменшують теоретичний виграш. Проте помітне поліпшення — звичайне явище.

Для записів 2‑way mirror повинен записати двічі. Тому записні IOPS на vdev приблизно рівні одному диску (знову ж таки, ігноруючи ZIL/SLOG). Пропускна здатність на рівні пулу покращується додаванням більшої кількості mirror vdev, а не очікуванням, що один mirror буде писати швидше за фізику.

Порівняння з RAIDZ без теології

RAIDZ чудово підходить для ефективності ємності та послідовної пропускної здатності. Це також простота «одного великого vdev». Але паритетні vdev важче справляються з дрібними випадковими IO, бо:

  • дрібний запис може стати read‑modify‑write по кількох дисках,
  • випадкові читання все одно потребують координації між дисками (навіть якщо іноді їх обслуговує один диск, є більше накладних витрат і менше свободи планування),
  • vdev — це один одиничний блок планування; один широкий RAIDZ2 vdev усе одно залишається одним vdev.

Ось чому пулі з дзеркалами за замовчуванням рекомендуються для затратно‑чутливих навантажень. RAIDZ не «поганий»; він просто краще підходить для інших профілів продуктивності.

Нотатка про порівняння з NVMe

Ні, дзеркала не перетворюють HDD на NVMe. Але вони можуть зробити систему відчутною як NVMe для додатку, який у першу чергу блокується через хвостову затримку випадкових читань, особливо коли ARC‑влучення високі, а залишкові читання по диску добре розподілені. Суб’єктивний досвід змінюється: менше затримок, менше довгих пауз, менше «все гаразд, але база даних повільна».

Жарт №2: Називати HDD‑дзеркала «NVMe» — це як називати велосипед «мотоциклом з відмінною паливною ефективністю». Технічно це рухає вас, але, будь ласка, не влаштовуйте гонки.

Проєктні рішення: ширина, кількість та що купувати

2‑way vs 3‑way дзеркала

2‑way дзеркала — стандарт: хороша надмірність, хороша продуктивність читань, прийнятні втрати ємності.

3‑way дзеркала потрібні, коли ризик відновлення й доступність важливіші за ємність. Вони знижують ймовірність того, що друга відмова вб’є vdev під час resilver, і можуть покращити вибір для читань. Але вони дорого коштують в термінах корисного простору, тому зазвичай виправдані для невеликих «гарячих» пулів (метадані VM, критичні журнали БД тощо) або коли рівень відмов дисків високий і заміни займають час.

Багато маленьких дзеркал краще за одне велике дзеркало

Якщо у вас 12 дисків, розмова про продуктивність зазвичай не про «один 12‑дисковий агрегат», а про «скільки топ‑рівневих vdev я отримаю?»

  • 6 mirror vdev (2‑way) дає вам 6 vdev‑черг і відмінне масштабування випадкових читань.
  • 1 RAIDZ2 vdev дає вам 1 vdev‑чергу і сильну послідовну пропускну здатність з хорошою ємністю.

Якщо ваше навантаження — зберігання VM, бази даних, CI‑кеші, файлові сервери з великою кількістю малих файлів: дзеркала зазвичай перемагають.

Математика ємності, яку слід зробити перед покупкою дисків

Дзеркала «втратили» половину сирої ємності (або дві третини для 3‑way). Але ця втрата не марнотратна: вона купує вам продуктивний запас і операційну свободу. Коли системи повільні, команди роблять дурні речі: вимикають захист, відключають sync, зменшують реплікацію. Платити за дзеркала часто дешевше, ніж оплачувати тиждень інцидент‑реакції.

Все ж таки, зробіть підрахунок заздалегідь:

  • Плануйте залишатися нижче приблизно ~70–80% використання пулу для затратно‑чутливих навантажень. ZFS сповільнюється при зменшенні вільного простору, оскільки алокація ускладнюється і фрагментація зростає.
  • Бюджетуйте надмірність і запасні диски. Якщо ви не можете швидко замінити вийшовший диск, ваше дзеркало тимчасово стає однодисковим. Це не надмірність; це надія.

Рекомендації щодо дисків і контролерів

Дзеркала виставляють латентність на поверхню. Це добре, доки ваш HBA або експандер не починає робити «креативні» речі з чергами та відновленням помилок. Декілька практичних нотаток:

  • Використовуйте HBAs в IT‑режимі (pass‑through). ZFS хоче бачити диски.
  • Уникайте змішування радикально різних типів дисків в одному mirror vdev. ZFS може маршрутизувати читання, але записи мусять чекати обох, а час resilver слідує за найповільнішим членом.
  • Встановіть адекватне внутрішнє відновлення помилок диска (TLER/ERC) для RAID‑подібних середовищ. Довге внутрішнє відновлення диска може зупинити IO‑черги і викликати таймаути.

Властивості і налаштування, які справді мають значення

ashift: постійне рішення

ashift встановлює вирівнювання секторів пулу. Помилитися — означає приректи себе на write amplification на весь час життя vdev. Для сучасних дисків ashift=12 (4K сектора) зазвичай мінімальний розумний вибір; багато адміністраторів обирають ashift=13 (8K) для деяких SSD, щоб вирівнятися з внутрішніми сторінками. Ви не можете змінити ashift після створення без перебудови.

recordsize (і volblocksize) відповідно до робочого навантаження

Для файлових систем recordsize контролює максимальний розмір блоку, який ZFS використовуватиме для даних файлів. Великі записи (1M) відмінні для послідовної пропускної здатності (бекапи, медіа), але можуть шкодити випадковим IO, якщо ваш додаток читає дрібні шматки з великих блоків.

Для zvol (блокові пристрої для iSCSI/VM) volblocksize встановлюється при створенні і має відповідати файловій системі гостя й навантаженню (зазвичай 8K/16K для баз даних, 16K/32K для загального використання VM). Знову: ви не можете змінити його пізніше без пересоздання zvol.

compression: безкоштовна продуктивність, поки не стане навантаженням

compression=lz4 часто виграшна: менше байтів читати/писати — менше часу диска. Для випадкових читань стиснення може зменшити розмір IO і покращити затримки. Але стиснення споживає CPU, і на системах, що вже завантажені CPU, воно може дати зворотний ефект.

atime: смерть від тисячі метаданихних записів

atime=on оновлює час доступу при читанні, спричиняючи додаткові записи. На навантажених файлових системах це може стати постійним потоком дрібних майже‑синхронних оновлень метаданих. Для більшості серверних навантажень atime=off — просте покращення.

sync writes, ZIL та SLOG

Синхронні записи — це контрактна гарантія: викликач хоче підтвердження, що дані безпечно на стабільному носії. ZFS задовольняє це через ZIL (ZFS Intent Log). Якщо ви додаєте виділений SLOG‑пристрій (швидкий, з низькою латентністю та захистом від втрати живлення), ви можете драматично прискорити затримку підтвердження синхронних записів.

Дзеркала і SLOG часто використовуються разом: дзеркала для IOPS випадкових читань, SLOG для затримки синхронних записів. Але якщо ваше навантаження здебільшого асинхронні записи, SLOG не допоможе суттєво. Якщо навантаження синхронне і у вас немає SLOG, дзеркала не вирішать хвостову затримку.

Практичні завдання з командами (і як читати вивід)

Команди нижче припускають типовий Linux з OpenZFS. Підлаштуйте імена пристроїв і пулів/датасетів. Суть не в сліпому копіюванні команд; суть — звичка перевіряти, що система реально робить.

Завдання 1: Перевірити топологію пулу (переконатися, що це справді дзеркала)

cr0x@server:~$ sudo zpool status -v
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:17:02 with 0 errors on Sun Dec 22 02:17:05 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-WDC_WD80...-part1   ONLINE       0     0     0
            ata-WDC_WD80...-part1   ONLINE       0     0     0
          mirror-1                  ONLINE       0     0     0
            ata-WDC_WD80...-part1   ONLINE       0     0     0
            ata-WDC_WD80...-part1   ONLINE       0     0     0

errors: No known data errors

Інтерпретація: Ви хочете бачити кілька топ‑рівневих mirror‑X vdev. Якщо ви бачите один гігантський RAIDZ vdev, ваша історія випадкових IO буде іншою. Також переконайтеся, що стан — ONLINE, а не DEGRADED.

Завдання 2: Спостерігати IO по vdev в реальному часі (знайти гарячий vdev)

cr0x@server:~$ sudo zpool iostat -v tank 1
                    capacity     operations     bandwidth
pool              alloc   free   read  write   read  write
----------------  -----  -----  -----  -----  -----  -----
tank              3.21T  4.05T    820    210  41.0M  12.3M
  mirror-0        1.60T  2.02T    610    105  30.4M   6.2M
    ata-WDC...      -      -     320     52  15.2M   3.1M
    ata-WDC...      -      -     290     53  15.2M   3.1M
  mirror-1        1.61T  2.03T    210    105  10.6M   6.1M
    ata-WDC...      -      -     110     52   5.3M   3.0M
    ata-WDC...      -      -     100     53   5.3M   3.1M
----------------  -----  -----  -----  -----  -----  -----

Інтерпретація: Якщо один mirror vdev виконує більшість роботи, у вас може бути skew (розміщення даних, гарячий датасет або невеликий набір блоків, що живе переважно на одному vdev через вік пулу і історію розширення). Дзеркала дають вам паралелізм, але лише якщо алокації розподілені помірно рівномірно.

Завдання 3: Отримати 30‑секундний сигнал «я закешований чи прив’язаний до диска?»

cr0x@server:~$ arcstat 1
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:01:10  12K  2.1K    17%   890   7%  1.2K  10%     0   0%  96.3G  128G
12:01:11  11K  2.4K    21%   1.1K 10%  1.3K  12%     0   0%  96.3G  128G

Інтерпретація: Високі показники влучень ARC часто маскують відмінності в розміщенні дисків. Коли misses зростають, справжня здатність пулу до випадкових читань має значення. Якщо misses стрибають і разом з ними зростає затримка, ви прив’язані до диска.

Завдання 4: Перевірити властивості датасету, які тихо саботують затримки

cr0x@server:~$ sudo zfs get -o name,property,value -s local,default recordsize,compression,atime,sync tank
NAME  PROPERTY     VALUE
tank  recordsize   128K
tank  compression  lz4
tank  atime        off
tank  sync         standard

Інтерпретація: Датасет бази даних з recordsize=1M — класичний самосаботаж. atime=on на гарячій файловій системі створює фоновий тиск записів. sync=disabled — це звіт про інцидент, що чекає на реалізацію.

Завдання 5: З’ясувати, чи саме синхронні записи — ваша реальна проблема

cr0x@server:~$ sudo zpool iostat -v tank 1 | head -n 20
                    capacity     operations     bandwidth
pool              alloc   free   read  write   read  write
----------------  -----  -----  -----  -----  -----  -----
tank              3.21T  4.05T    120    950  6.0M   38.0M
  mirror-0        1.60T  2.02T     70    480  3.4M   19.2M
  mirror-1        1.61T  2.03T     50    470  2.6M   18.8M
----------------  -----  -----  -----  -----  -----  -----

Інтерпретація: Висока кількість write ops із низькою пропускною здатністю часто означає багато дрібних записів. Якщо додаток вимагає синхронної семантики (завершення транзакцій БД, NFS зі sync, VM‑flush), ваше наступне питання: чи є у вас SLOG і чи він здоровий?

Завдання 6: Підтвердити, чи існує SLOG і що це за пристрій

cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: ONLINE
config:

        NAME                         STATE     READ WRITE CKSUM
        tank                         ONLINE       0     0     0
          mirror-0                   ONLINE       0     0     0
            /dev/sdb1                ONLINE       0     0     0
            /dev/sdc1                ONLINE       0     0     0
          mirror-1                   ONLINE       0     0     0
            /dev/sdd1                ONLINE       0     0     0
            /dev/sde1                ONLINE       0     0     0
        logs
          nvme-SAMSUNG_MZ...-part1   ONLINE       0     0     0

Інтерпретація: Якщо ви дбаєте про затримки синхронних записів, лог‑пристрій має бути з низькою латентністю і захистом від втрати живлення. Споживчий SSD, використаний як SLOG, може відмовляти в способи, що не показуються в бенчмарках, але проявляються як «чому fsync щойно зайняв 800ms?»

Завдання 7: Правильно створити mirror‑пул (з явним ashift)

cr0x@server:~$ sudo zpool create -o ashift=12 tank \
  mirror /dev/disk/by-id/ata-DISK_A /dev/disk/by-id/ata-DISK_B \
  mirror /dev/disk/by-id/ata-DISK_C /dev/disk/by-id/ata-DISK_D

Інтерпретація: Використовуйте стабільні ідентифікатори пристроїв. Явний ashift уникне підстерігаючих платформних значень пізніше. Мета — кілька mirror vdev: ви купуєте черги.

Завдання 8: Додати ще один mirror vdev (масштабувати продуктивність і ємність)

cr0x@server:~$ sudo zpool add tank mirror \
  /dev/disk/by-id/ata-DISK_E /dev/disk/by-id/ata-DISK_F

Інтерпретація: Ось як зростають mirror‑пули: додавайте mirror vdev. Зазвичай ви не можете «перетворити» RAIDZ vdev у дзеркала. Розклад — це вибір на етапі проєктування.

Завдання 9: Замінити диск, що виходить з ладу, у дзеркалі (професійний спосіб)

cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: DEGRADED
config:

        NAME        STATE     READ WRITE CKSUM
        tank        DEGRADED     0     0     0
          mirror-0  DEGRADED     0     0     0
            sdb1    ONLINE       0     0     0
            sdc1    FAULTED     12     0     0  too many errors
          mirror-1  ONLINE       0     0     0
            sdd1    ONLINE       0     0     0
            sde1    ONLINE       0     0     0

cr0x@server:~$ sudo zpool replace tank sdc1 /dev/disk/by-id/ata-NEW_DISK-part1
cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: ONLINE
  scan: resilver in progress since Tue Dec 24 09:12:03 2025
        312G scanned at 1.20G/s, 41.2G issued at 160M/s, 3.21T total
        41.2G resilvered, 1.26% done, 05:22:11 to go

Інтерпретація: zpool replace — це операція життєвого циклу, яку ви хочете. Слідкуйте за швидкістю resilver. Якщо resilver тягнеться, ви можете бути IO‑заблоковані через навантаження, обмеження контролера або проблеми з залишковим диском.

Завдання 10: Offline/online диск для обслуговування (імітувати відмову безпечно)

cr0x@server:~$ sudo zpool offline tank /dev/disk/by-id/ata-DISK_B
cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: DEGRADED
config:

        NAME                       STATE     READ WRITE CKSUM
        tank                       DEGRADED     0     0     0
          mirror-0                 DEGRADED     0     0     0
            ata-DISK_A             ONLINE       0     0     0
            ata-DISK_B             OFFLINE      0     0     0
          mirror-1                 ONLINE       0     0     0
            ata-DISK_C             ONLINE       0     0     0
            ata-DISK_D             ONLINE       0     0     0

cr0x@server:~$ sudo zpool online tank /dev/disk/by-id/ata-DISK_B

Інтерпретація: Корисно для контрольованого обслуговування. Не лишайте дзеркала деградованим довше, ніж потрібно; ви на крок ближче до простою.

Завдання 11: Scrub і перевірка (і чи ваш пул тихо страждає)

cr0x@server:~$ sudo zpool scrub tank
cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: ONLINE
  scan: scrub in progress since Tue Dec 24 10:03:41 2025
        1.20T scanned at 820M/s, 510G issued at 350M/s, 3.21T total
        0B repaired, 15.87% done, 02:22:10 to go

Інтерпретація: Scrub виявляє і виправляє погані блоки, використовуючи надмірність дзеркал. Якщо scrubs регулярно «ремонтують» дані, вашим дискам, кабелям або шляху контролера потрібна увага. Дзеркала прощають багато, але це не дозвіл ігнорувати помилки.

Завдання 12: Перевірити фрагментацію і вільний простір (передбачити майбутнє)

cr0x@server:~$ sudo zpool list -o name,size,alloc,free,frag,capacity,health
NAME  SIZE  ALLOC  FREE  FRAG  CAPACITY  HEALTH
tank  7.25T  3.21T 4.05T   18%      44%  ONLINE

Інтерпретація: Висока фрагментація і велике використання ємності корелюють з гіршою затримкою. Якщо ви вище ~80% і додаток чутливий до затримок, ви зараз платите відсотки за ранній оптимізм.

Завдання 13: Знайти топ‑споживачів IO (облік IO на рівні датасетів)

cr0x@server:~$ sudo zfs iostat -r -v tank 1
                              capacity     operations     bandwidth
dataset                      alloc   free   read  write   read  write
---------------------------  -----  -----  -----  -----  -----  -----
tank                         3.21T  4.05T      0      0      0      0
  tank/db                    820G   1.20T    640    520  32.0M  24.0M
  tank/vm                    1.90T  2.10T    180    310  9.0M   14.0M
  tank/home                  120G   800G      5     18  200K   900K
---------------------------  -----  -----  -----  -----  -----  -----

Інтерпретація: Це показує, звідки походить IO. Якщо «db» гарячий і має неправильний recordsize або sync, у вас є цільове виправлення, а не розмита паніка через сховище.

Завдання 14: Підтвердити ashift на існуючих vdev

cr0x@server:~$ sudo zdb -C tank | grep -E 'ashift|vdev_tree|type: mirror' -n
15:        vdev_tree:
34:            type: 'mirror'
48:                ashift: 12
71:            type: 'mirror'
85:                ashift: 12

Інтерпретація: Підтвердіть вирівнювання. Якщо ви виявите ashift=9 на дисках з 4K секторами, ви знайшли структурну причину затримок. Виправлення — перебудова/заміна vdev, а не підгонка sysctl до кращого настрою.

Завдання 15: Виміряти затримку опосередковано (підказки служби з iostat)

cr0x@server:~$ iostat -x 1
Linux 6.8.0 (server)  12/24/2025  _x86_64_  (32 CPU)

Device            r/s   w/s  rkB/s  wkB/s  await  svctm  %util
sdb              90.0  60.0  4600   5100    7.2   1.1    18.0
sdc              88.0  62.0  4500   5200    8.0   1.2    19.0
sdd              30.0  90.0  1400   7800   25.0   1.3    22.0
sde              28.0  92.0  1300   7900   27.5   1.4    23.0

Інтерпретація: Зростання await при незавершеному %util може вказувати на черги вище рівня пристрою (контролер, файлові системи, блокування через синхронні записи). Одна нога дзеркала з постійно гіршим await — підказка: той диск, шлях або кабель можуть бути деградовані.

Швидкий план діагностики

Це рутина «увійти в кімнату, глянути на три речі і не відволікатися». Вона призначена для простоїв і уповільнень, коли вам потрібна гіпотеза швидко.

По‑перше: це кеш, диск чи sync?

  1. ARC hit rate: запустіть arcstat 1 (або еквівалент). Якщо misses низькі, розклад дисків може наразі не бути проблемою.
  2. Форма IO пулу: запустіть zpool iostat -v tank 1. Шукайте багато дрібних write ops, перекіс навантаження по vdev і чи домінують читання чи записи.
  3. Синхронний тиск: перевірте, чи навантаження синхронне (коміти БД, NFS sync). Підтвердіть, чи є SLOG через zpool status. Якщо немає SLOG і синхронні записи домінують, швидше за все ви знайшли винуватця затримок.

По‑друге: чи одна операція/шлях поводиться неправильно?

  1. Здоров’я і помилки: zpool status -v. Є READ/WRITE/CKSUM помилки? Є vdev у стані DEGRADED?
  2. Підказки по латентності на диск: iostat -x 1. Один диск з високим await або перезапусками часто «проблема», навіть якщо пул — «ONLINE».
  3. Логи ядра: перевірте на лінк‑ресети/таймаути.

По‑третє: чи вам бракує простору або ви потопаєте у фрагментації?

  1. Ємність і frag: zpool list -o size,alloc,free,frag,capacity. Якщо ви вище ~80% і frag високий, біль за випадкові IO очікуваний.
  2. Порушники датасетів: zfs iostat -v 1, щоб знайти гарячі датасети, потім перевірте їх властивості.
  3. Фонова робота: scrubs/resilvers можуть домінувати IO. Перевірте рядок scan у zpool status.

Як тільки у вас є категорія — cache miss, затримка синхронних записів, один поганий диск/шлях або повний/фрагментований пул — ви можете діяти. Без цього ви витратите години на «налаштування» системи, яка просто вийшла за межі проєктного пакета.

Три короткі історії з корпоративного життя

1) Інцидент через неправильне припущення: «Записи на дзеркалі швидкі, правда?»

Команда мігрувала транзакційний сервіс з керованої бази даних на власні інстанси з міркувань економії. План зі сховищем виглядав переконливо: «Ми будемо використовувати ZFS дзеркала, тож буде швидко». Вони побудували пул з кількома mirror vdev на пристойних SSD, увімкнули стиснення і вважали справу завершеною. Ранні тести були чудові — бо тести були в основному читальні й масові. Сервіс пішов у продакшн у понеділок, бо, звичайно, так і сталося.

До вівторка вдень ротація on‑call виявила новий вид втоми від алертів. Сплески затримок збігалися з хвилями транзакцій. База даних не була прив’язана до CPU. Мережа чиста. Диски не були насичені по пропускній здатності. Але коміти зависали достатньо довго, щоб викликати таймаути. Канал інциденту наповнився звичними підозрами: «Може, ZFS повільний?» «Може, потрібні більші інстанси?» «Може, вимкнути fsync?»

Неправильне припущення було тонким: вони думали, що дзеркала прискорюють записи так само, як прискорюють випадкові читання. Але навантаження було доміновано синхронними комітами, а система не мала виділеного SLOG. ZFS робив правильно — дотримувався семантики sync, фіксуючи дані на стабільному носії — але затримки основних пристроїв пулу (і write amplification від дрібних sync записів) зробили це болісним при навантаженні.

Виправлення не полягало у магічному sysctl. Вони додали пристрій з захистом від втрати живлення як mirrored SLOG (бо так, лог‑пристрої теж можуть відмовляти), підтвердили, що затримка sync записів впала, і потестували з реальними патернами транзакцій. Сервіс стабілізувався. Постмортем не стосувався «ZFS повільний». Це було про відповідність структури до форми IO і розуміння, що дзеркала — це зброя проти затримок читань, а не універсальний еліксир продуктивності.

Урок, що залишився: дзеркала дали їм запас для випадкових читань, але без SLOG вони все одно мали хвостову затримку синхронних записів. Вони почали ставити «sync‑heavy» як вимогу першого порядку, а не думати про це потім.

2) Оптимізація, що обернулася проти: «Підтримаємо recordsize і вимкнемо sync»

Ця історія починається так само, як багато трагедій зі сховищами: з картинки на дашборді і впевненого речення. Розробник показав, що додаток робить багато IO, і хтось запропонував «оптимізувати» файлову систему. Пропозиція була проста: збільшити recordsize до 1M «для пропускної здатності» і встановити sync=disabled «бо fsync дорогий». Команда хотіла, щоб графіки виглядали краще. І вони отримали те, що хотіли.

Приблизно на два тижні продуктивність дійсно покращилася. Потім у плановому вікні технічного обслуговування цикл живлення тривав довше, ніж очікувалося. Коли системи повернулися, дані додатка виявилися непослідовними. Не драматична «все пропало» відмова — гірше. Невелика кількість останніх транзакцій була відсутня, а деякі записи частково застосовані. Така корупція, що перетворюється на тиждень примирень і вибачень.

Вимкнення sync забрало контрактну гарантію, на яку покладався додаток. ZFS зробив те, що йому наказали: поставив синхронні записи як асинхронні. Дзеркальна конфігурація не була винуватцем. Оптимізація була. Збільшення recordsize також мало вартість: база даних тепер читала і переписувала більші блоки, ніж потрібно, що зробило випадковий IO ще різкішим під навантаженням, особливо коли ARC не влучав.

План відновлення включав відновлення з бекапів і програвання того, що можна з логів. Тривала зміна була культурна: властивості файлової системи потрапили під контроль змін, а робота з продуктивністю вимагала тест‑плану з реальним навантаженням. Команда навчилася боятися будь‑якої оптимізації, що починається зі слів «можемо вимкнути безпеку; буде нормально».

Дзеркала не врятували їх від їхніх помилок. Але подальший редизайн — так: вони повернули sync до standard, використали правильний SLOG для синхронної частини, налаштували recordsize по датасетах і залишили дзеркала, бо профіль випадкових читань був їхньою довгостроковою потребою.

3) Нудна, але правильна практика, що врятувала день: заміна дисків до «відмови»

У великому корпоративному середовищі найбільш героїчна робота зазвичай тиха. Один флот сховищ мав політику: якщо диск починає логувати середні помилки або показує зростаючий рівень помилок, заміняйте його в робочий час — до того, як він доведе vdev до стану DEGRADED. Це не було драматично. Це іноді було непопулярно, бо виглядало як витрата грошей «раніше».

Одного кварталу вони почали бачити спорадичні сплески затримки в пулі, що підтримував внутрішній CI і зберігання артефактів. Нічого гучного в zpool status. Ніяких DEGRADED vdev. Просто хвостові сплески затримки, які робили білди ненадійними і розробників незадоволеними. Замість того, щоб лаяти мережу чи «Kubernetes», on‑call запустив стандартну триаж‑рутинну: zpool iostat -v показав одну ногу дзеркала з нерівномірним навантаженням і гіршим часом обслуговування. iostat -x натякнув, що один диск час від часу зависає.

Вони витягли SMART‑дані і знайшли ранні ознаки проблем — нічого, що викликало б негайний інцидент, але достатньо, щоб корелювати зі зупинками. Вони замінили диск у запланованому вікні через zpool replace, спостерігали завершення resilver, і сплески затримки зникли. Ніякого простою. Ніякого постмортему. Просто замкнене коло між спостереженням і обслуговуванням.

Через кілька тижнів інший диск у іншому дзеркалі відмовив жорстко. Команда знизала плечима, замінила його і пішла далі. Важливе: бо вони підтримували пул здоровим і мали культуру проактивної заміни, «реальна» відмова не співпала з другим маргінальним диском, backlog‑ом scrubs і повним пулом. Дзеркала виконали свою роль, бо операції виконали свою.

Поширені помилки: симптоми та виправлення

Помилка 1: Побудувати один гігантський RAIDZ vdev для навантаження випадкового IO

Симптоми: Послідовні бенчмарки виглядають нормально. Реальні додатки (DB/VM) показують високу затримку й низькі IOPS. zpool iostat показує один vdev, що робить усе, бо існує лише один vdev.

Виправлення: Для затратно‑чутливого випадкового IO проєктуйте з кількома mirror vdev. Якщо ви вже побудували RAIDZ, виправлення зазвичай — міграція до нового макету пулу (zfs send/receive, реплікація, перебудова). Немає безпечної «перетворити на місці» кнопки, що зберігає той самий vdev.

Помилка 2: Неправильний ashift

Симптоми: Дрібні записи незрозуміло повільні. CPU і пропускна здатність у нормі, але затримка настирлива. Ви бачите сильну read‑modify‑write поведінку на рівні пристрою.

Виправлення: Перевірте за допомогою zdb -C. Якщо неправильно, плануйте перебудову: заміна vdev на правильно вирівняні або міграція в новий пул. Не марнуйте час на «налаштування» для проблеми геометрії.

Помилка 3: Вимкнення sync, щоб «поліпшити» продуктивність

Симптоми: Графіки продуктивності покращуються. Потім нечиста відмова призводить до відсутніх недавніх даних або невідповідностей на рівні додатка.

Виправлення: Тримайте sync=standard, якщо ви не можете довести, що додаток не потребує стійкості (рідко). Якщо потрібна продуктивність sync, додайте правильний SLOG і підтвердіть, що він справді використовується (і має низьку затримку і PLP).

Помилка 4: Використання споживчого SSD як SLOG

Симптоми: Затримка синхронних записів нестабільна; іноді довгі паузи. SLOG показує помилки або ресети. Іноді продуктивність деградує з часом через внутрішнє GC пристрою.

Виправлення: Використовуйте корпоративний, з захистом від втрати живлення пристрій. Розгляньте дзеркалення SLOG. Моніторьте його як щось важливе — бо це важливо.

Помилка 5: Заповнення пулу до краю

Симптоми: Зі зростанням використання пулу затримки ростуть. Алокація ускладнюється. Фрагментація зростає. Все відчувається «м’яким» і непередбачуваним.

Виправлення: Тримайте запас вільного простору (зазвичай 20–30% для гарячих пулів). Додавайте vdev заздалегідь. Якщо ви вже переповнені — мігруйте холодні дані або розширюйте; налаштування не створить вільного простору.

Помилка 6: Ігнорування одного «трохи дивного» диска

Симптоми: Пул ONLINE, але хвостові сплески затримки. Один диск показує вищий await або спорадичні помилки. Scrubs займають більше часу ніж звично.

Виправлення: Слідкуйте за маргінальним обладнанням як за багом продуктивності. Замініть сумнівні диски і виправте бліді кабелі/шляхи. Дзеркала ховають відмови; вони також ховають ранні попередження, якщо не дивитися.

Помилка 7: Змішування розмірів або швидкостей дисків у дзеркалі

Симптоми: Ви отримуєте ємність, рівну найменшому диску в дзеркалі. Resilver і затримки запису слідують за найповільнішим членом. Продуктивність нестабільна.

Виправлення: Дзеркальте «подібне з подібним» коли можливо. Якщо мусите змішувати — робіть це свідомо і приймайте обмеження (і документуйте це, щоб Майбутнє Ви не «оптимізував» у хаос).

Чек‑листи / покроковий план

Покроково: проєктування mirror‑пулу для випадкового IO

  1. Класифікуйте навантаження: випадкові читання (DB/VM), синхронні записи (журнали транзакцій, NFS sync), послідовні (бекапи/медіа), змішані.
  2. Оберіть стратегію топ‑рівневих vdev:
    • Випадкові IO + чутливі до затримки: кілька 2‑way mirror vdev.
    • Крайня вимога доступності: розгляньте 3‑way дзеркала для «гарячого» шару.
    • Перш за все ємність + послідовність: RAIDZ2/3 може бути доречним, але розумійте компроміс випадкових IO.
  3. Вирішіть модель зростання: дзеркала ростуть додаванням mirror vdev. Переконайтеся, що бізнес може купувати диски парами (або трійками) у майбутньому.
  4. Виберіть ashift: зазвичай 12. Ставте явно.
  5. Плануйте синхронні записи: якщо у вас sync‑важке навантаження, проєктуйте SLOG заздалегідь (і закладайте бюджет на PLP‑пристрій).
  6. Встановіть параметри датасетів за замовчуванням: compression=lz4, atime=off, і адекватний recordsize по датасетах (не одне універсальне значення).
  7. Операційна політика: розклад scrub, моніторинг SMART, інвентар запасних, план заміни.

Покроково: валідація, що дзеркала дають очікувану затримку

  1. Підтвердіть топологію за допомогою zpool status і переконайтеся, що є кілька mirror vdev.
  2. Бенчмарк бази: вимірюйте під навантаженням, схожим на реальний додаток, а не тільки синтетичними послідовними тестами.
  3. Спостерігайте розподіл: zpool iostat -v 1 має показувати роботу, розподілену по vdev.
  4. Перевірте поведінку кешу: arcstat, щоб з’ясувати, чи дійсно ви потрапляєте на диск.
  5. Протестуйте режим відмови: відключіть диск у контрольованому вікні, спостерігайте поведінку, потім увімкніть його. Переконайтеся, що моніторинг спрацьовує.
  6. Документуйте «відомо‑хороші» налаштування: recordsize/volblocksize, sync‑семантика, тип SLOG, ashift.

Покроково: якщо у вас вже RAIDZ і ви хочете дзеркала

  1. Признайте: це міграція: ви не «налаштовуєте» в дзеркала. Ви переносите дані.
  2. Побудуйте новий пул з mirror vdev і правильним ashift.
  3. Використовуйте реплікацію: zfs send/zfs receive для датасетів; підтримуйте консистентність снапшотів.
  4. Переключіться у запланованому вікні, провалідуйте, потім виведіть з експлуатації старий пул.

FAQ

1) Чи завжди ZFS дзеркала швидші за RAIDZ?

Ні. Дзеркала зазвичай швидші для випадкових читань і навантажень, чутливих до затримки. RAIDZ може бути відмінним для послідовної пропускної здатності і ефективності ємності. Обирайте за формою IO і операційними обмеженнями.

2) Скільки mirror vdev мені потрібно?

Достатньо, щоб ваше навантаження розподілялося по vdev‑чергах. Орієнтовне практичне правило: більше топ‑рівневих vdev зазвичай значить більше IOPS і менше конкуренції. Але контролери, CPU і мережа можуть стати новим вузьким місцем, тож вимірюйте і не будуйте надмірно без причин.

3) Використовувати 2‑way чи 3‑way дзеркала?

За замовчуванням — 2‑way. Використовуйте 3‑way, коли доступність і ризик відновлення критичні і ви можете дозволити втрату ємності — особливо для невеликих, критичних гарячих датасетів.

4) Чи дзеркала допомагають затримці записів?

Не безпосередньо на рівні одного vdev. Записи мають йти на всі члени дзеркала. Пропускна здатність записів на рівні пулу покращується додаванням mirror vdev, але затримка синхронних записів зазвичай вирішується правильним SLOG, а не лише дзеркалами.

5) Яке одне найважливіше налаштування «не лізь туди»?

ashift. Правильно виставте вирівнювання секторів при створенні пулу. Неправильний ashift може назавжди погіршити продуктивність дрібних записів і важко виправляється.

6) Чи потрібен SLOG для mirror‑пулів?

Ні. Він потрібен лише якщо у вас значне навантаження синхронних записів і вам важлива їхня затримка. Якщо навантаження здебільшого асинхронне, SLOG часто мало дає.

7) Чому мій mirror‑пул швидкий у бенчмарках, але повільний у продакшені?

Бенчмарки часто тестують послідовну пропускну здатність або нереальні глибини черги. Більшість болю в продакшені — хвостова затримка від sync записів, один проблемний диск/шлях, майже повний пул або невідповідність властивостей датасету (recordsize/volblocksize).

8) Чи можу я розширити mirror vdev, додавши третій диск пізніше?

У багатьох OpenZFS середовищах ви можете приєднати додатковий пристрій до дзеркала, зробивши його 3‑way, але підтримка операційно залежить від платформи і політик. Навіть якщо це можливо, ставтеся до такого зміни як до реальної: тестуйте в лабораторії, підтверджуйте моніторинг і переконуйтеся, що процедури заміни працюють з новою топологією.

9) Чи скорочують дзеркала час resilver?

Часто так. Resilver для дзеркал зазвичай простіший, ніж реконструкція паритету. Залежно від фіч і поведінки платформи, ZFS може пересирати лише виділені блоки, що робить відновлення швидшим, ніж «копіювати весь диск». Але швидкість resilver залежить від навантаження, стану дисків і обмежень контролера.

10) Що робити, якщо я хочу і ефективність ємності, і продуктивність випадкових IO?

Розділяйте рівні. Використовуйте дзеркала для гарячих випадкових датасетів і RAIDZ для холодних/послідовних даних — або окремі пули. Намагатися зробити одну конфігурацію універсальною — шлях до середньої продуктивності і надсередніх інцидентів.

Висновок

ZFS дзеркала не обманюють фізику. Вони її використовують. Випадкові I/O — це проблема черг, і дзеркала дають ZFS більше вибору: більше черг, більше паралелізму і більше можливостей оминути той один диск, що тихо псує вашу хвостову затримку. Коли ви будуєте пул з кількох mirror vdev, ви не просто дублюєте дані — ви купуєте свободу планування.

Операційний виграш важливіший за синтетичні бенчмарки. Дзеркала роблять обробку відмов простішою, scrubs — значущими, а продуктивність передбачуванішою при змішаних навантаженнях. Поєднайте їх з розумними властивостями, достатнім вільним простором і (коли потрібно) реальним SLOG, і ви отримаєте еквівалент добре організованої ротації on‑call: не гламурно, але раптом все перестає бути надзвичайною ситуацією.

← Попередня
Електронна пошта: атаки перебору на IMAP/SMTP — захистіть сервер, не заблокувавши себе
Наступна →
Сервери Ubuntu 24.04: Snap проти apt — коли Snap тихо створює проблеми (і що з цим робити)

Залишити коментар