ZFS dedup: Прапорець, який їсть ОЗП і руйнує вихідні

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

Дедуплікація ZFS — це еквівалент кнопки «Безкоштовні гроші» у світі зберігання даних. Вона виглядає нешкідливою, добре демонструється й вже не раз закінчувалася провалом на чергуванні у вихідні. Обіцянка спокуслива: зберігати ідентичні блоки один раз, посилатися на них багаторазово, звільнити купи місця й виглядати як чарівник під час бюджетного перегляду.

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

Зміст

Що насправді робить dedup (і чого він не робить)

Дедуплікація ZFS — це дедуплікація на рівні блоків. Коли ви вмикаєте dedup=on для датасету, ZFS хешує кожен блок під час запису. Якщо блок з таким хешем уже існує в пулі, ZFS уникає запису другої копії і замість цього створює ще одне посилання на існуючий блок.

Це не дедуплікація на рівні файлів, не «знайти ідентичні ISO-файли» і не фонове завдання, яке можна призупинити, коли база даних починає вередувати. Dedup — це операція вбудована в шлях запису: вона відбувається inline. Це означає, що кожен запис тепер включає додаткову роботу: обчислити контрольну суму, виконати пошук і, можливо, оновити метадані дедуплікації. Ви не можете «зробити dedup пізніше», якщо тільки не перепишете дані пізніше — про цю неприємність поговоримо нижче.

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

Одне речення, яке варто надрукувати на стікері: ZFS dedup — це проблема метаданих, прихована під рисою економії місткості.

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

Чому dedup «їсть» ОЗП: DDT і податок, якого не уникнути

Серцем dedup є DDT — таблиця дедуплікації. Концептуально це мапа від контрольної суми блоку → вказівник(и) на фізичні блоки та лічильники посилань. При кожному записі в датасет з dedup ZFS має визначити, чи існує ідентичний блок. Це вимагає пошуку в DDT.

Якщо DDT «гаряча» в пам’яті, dedup може бути просто «деяким оверхедом». Якщо DDT не в пам’яті, dedup перетворюється на «випадкові читання метаданих під час спроб записати дані», що й перетворює пристойну систему зберігання на перформанс-арту.

ARC, L2ARC і чому «просто додати SSD» — не план

ZFS використовує ARC (Adaptive Replacement Cache) в ОЗП для кешування. Dedup хоче, щоб DDT була в ARC, бо вона доступна постійно. Коли ARC достатньо великий — життя нормальне. Коли ні — ZFS мусить діставати записи DDT з диска. Це малі, розкидані читання, які найгірші для шпиндельних дисків і все ще дратують SSD під навантаженням.

Деякі середовища намагаються «вирішити» це L2ARC (другорядний кеш на SSD). L2ARC може допомогти, але це не чаклунство. L2ARC повільніший за RAM і має власний оверхед метаданих. Якщо у вас вже мало пам’яті, додавання L2ARC може погіршити становище, споживаючи ще більше ОЗП під заголовки L2ARC і все одно не даючи латентності, як у RAM.

Спеціальні vdev: краще, але не безкоштовно

У новіших версіях OpenZFS special vdev може зберігати метадані (і за бажанням маленькі блоки) на швидких пристроях. Якщо ваш DDT та інші метадані живуть на дзеркальному NVMe special vdev, пошуки dedup набагато менш болючі. Це перший підхід, який більше нагадує справжню архітектуру, а не механізм виживання. Але є гостра грань: якщо ви втрачаєте special vdev, ви можете втратити пул. Ставтесь до нього, як до найсвятішого vdev, бо так воно і є.

Чому існує фольклор «ОЗП на ТБ»

Ви почуєте правилом великого пальця: «1–5 ГБ ОЗП на ТБ дедуплікованих даних». Реальна відповідь залежить від recordsize, навантаження, ступеню дублювання даних і як великою стає DDT. Але фольклор існує, бо режим відмови стабільний: як тільки DDT не вміщується в пам’ять, затримки стрибають, а пропускна здатність падає як зі скелі.

І є ще друга пастка: вам не треба, щоб ARC вміщував весь пул, вам треба, щоб ARC вміщував робочий набір DDT. Якщо ваш робочий набір DDT великий (висока мінливість, багато унікальних блоків), ви можете мати багато ОЗП й усе одно отримати поганий досвід.

Факти та історичний контекст (те, про що люди забувають)

Dedup не став «контроверсійним», бо він поламаний. Він став контроверсійним, бо його легко вмикнути й важко експлуатувати безпечно. Кілька контекстних пунктів, які варто знати:

  1. Dedup у ZFS існує давно, і ранні реалізації заробили репутацію за жорстке використання пам’яті, бо системи тоді були меншими, а шари метаданих на SSD були рідкістю.
  2. Dedup налаштовується на датасет, а не на пул, але DDT живе на рівні пулу. Один датасет з dedup=on може накласти оверхед на поведінку всього пулу.
  3. Ви не можете «вимкнути» dedup заднім числом. Встановлення dedup=off впливає лише на нові записи. Існуючі блоки залишаються дедупльованими, поки їх не перепишуть.
  4. Dedup взаємодіє зі снапшотами: дедупльовані блоки можуть посилатися через снапшоти і клони, збільшуючи лічильники посилань і ускладнюючи облік місця.
  5. Dedup уповільнює певні режими відмов: resilver, scrub і деякі операції ремонту тривають довше, бо треба проходити більше метаданих і посилань.
  6. Стиснення часто дає більшість вигоди з меншими ризиками, особливо для лог-файлів, JSON, образів VM і сторінок баз даних, які не ідентичні, але стискаються.
  7. VM «золоті образи» — класичний приклад вигод від dedup, але сучасні VM-стеки часто використовують клонування/linked clones або шарування образів, що вже уникає дублювання.
  8. Ріст DDT може здивувати, якщо recordsize малий або навантаження генерує багато унікальних блоків (бази даних, зашифровані дані, вже стиснуті бінарні блохи).
  9. Шифровані датасети зменшують можливості dedup: шифрування рандомізує блоки, усуваючи патерни ідентичних блоків, якщо лише dedup не відбувається до шифрування на шляху даних (що часто не так).

Коли dedup працює (рідко, реально і специфічно)

Dedup може бути правильним інструментом, коли виконуються всі наступні умови:

  • Ваші дані справді біт-в-біт ідентичні по числу байтів у межах recordsize. Не «схожі», не «стиснювані», а саме ідентичні блоки.
  • Ваш робочий набір стабільний, або принаймні передбачуваний. Dedup ненавидить високий треш, коли робочий набір DDT постійно змінюється.
  • Ви готові платити метаданим: достатньо ОЗП і/або швидкий шар для метаданих (special vdev), щоб DDT-пошуки не падали на диски.
  • Ви тестували на даних, схожих на продакшн. Синтетика бреше; dedup особливо чутливий до того, як дані лежать у реальному житті.

Середовища, де я бачив dedup без драм, зазвичай виглядають так:

1) Мішені для бекапів зі схожими повними копіями (з застереженнями)

Якщо у вас багато повних бекапів, що містять ідентичні блоки (наприклад, ферма схожих машин) і ви пишете великі послідовні потоки, dedup може дати великі заощадження місця. Але якщо ваше ПО для бекапів уже робить дедуплікацію на рівні додатка, ZFS dedup — зайвий шар і іноді шкодить. Також бекапи часто мають пікові, «вибухові» записи — отже DDT має пережити пікові прийоми, а не середній навантаження.

2) VDI / VM шаблони (лише якщо ви не використовуєте клонування)

Сотні десктопів або VM, створені з одного шаблону, можуть ділитися великою кількістю ідентичних блоків. Але багато платформ вже використовують copy-on-write клонування, яке уникає дублювання без ZFS dedup. Якщо ви вже на ZFS, ZFS клони та снапшоти можуть дати більшість вигоди з меншим ризиком.

3) Read-mostly датасети з ідентичними артефактами

Подумайте про великі флоти, що роздають ідентичні контейнерні шари, репозиторії пакетів або артефакти збірки — за умови, що ці артефакти дійсно біт-в-біт ідентичні й не перевиписуються/перепідписуються так, що блоки змінюються. Це рідше, ніж здається.

Коли dedup зазнає невдачі (поширено, дорого, передбачувано)

Dedup зазнає невдачі так, як SRE ненавидять: повільно спочатку, потім одразу, і зазвичай о 2:00 ночі.

1) Бази даних і все з високою мінливістю

Бази даних переписують сторінки. Навіть якщо логічний вміст схожий, блоки відрізняються, і патерн записів тримає метадані в русі. Якщо ваші промахи DDT збільшуються й DDT не може залишатися «гарячою» в ARC, ви побачите стрибки затримок і падіння пропускної здатності. Ви також ризикуєте перетворити рутинне обслуговування (scrub, resilver) на багатоденні справи.

2) Вже стиснуті або зашифровані дані

Стисле відео, архіви, багато бінарних форматів і зашифровані блоби зазвичай мають низьку ймовірність дедуплікації. Ви платите оверхед і повертаєте мало місця. Це найгірша угода в зберіганні: оверхед без користі.

3) Змішані навантаження на спільному пулі

Одна команда вмикає dedup на одному датасеті. DDT пулу росте. Інша команда з чутливими до затримок навантаженнями на іншому датасеті починає писати тікети про «випадкові затримки». Ніхто не пов’язує точки, поки ви не заґрафите пропуски ARC і не побачите, як DDT бореться за пам’ять.

4) «Ми просто додамо ОЗП пізніше»

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

Жарт №2: ZFS dedup — єдина функція, яку я знаю, що може перетворити «ми заощадили 20% диску» у «ми втратили 80% продуктивності» з тим самим ентузіазмом.

Три міні-історії з корпоративного досвіду

Міні-історія 1: Інцидент через неправильне припущення

Середнього розміру підприємство запускало приватний кластер віртуалізації на ZFS. Новий керівник зберігання успадкував дорогий запит на розширення і вирішив «поступити розумно» перед купівлею дисків. Він увімкнув dedup на датасеті з дисками VM, очікуючи великого дублювання шаблонів.

Неправильне припущення: «VM всі схожі, отже dedup буде величезним». Насправді середовище відхилилося від ідеалу. Шаблони були старі, багато VM були патчені роками, і платформа вже використовувала клонування для стартової розгортки. Дублювання було, але далеко не таке, як у таблиці Excel.

Перші симптоми були тонкими: зрідка стрибки затримок під час ранкових логінів. Потім служба підтримки почала скаржитись на «повільні VM» і «випадкові зависання». IOPS у середньому виглядали нормально, але p99 записів був жахливий. Scrub-операції теж почали тривати довше — більше проходів по метаданих, тиск на кеш.

Команда на чергуванні лікувала це як проблему гіпервізора, поки хтось не зв’язав стрибки з промахами кеша DDT на боці зберігання. DDT був значно більший, ніж очікували, ARC постійно витісняв корисні дані, щоб звільнити місце для метаданих dedup, і пул робив малі випадкові читання просто щоб вирішити, як записати.

Вони вимкнули dedup на датасеті, очікуючи миттєвого вирішення. Продуктивність покращилася трохи (менше нових dedup-пошуків), але DDT залишився величезним, бо існуючі дані залишалися дедупльованими. Остаточне рішення — контрольована міграція: реплікація датасетів у новий пул без dedup і переключення. «Економія диску» виявилася коштувати тижнів планування і багатьох зустрічей, на яких нікому не дозволяли говорити «я ж казав».

Міні-історія 2: Оптимізація, яка відкотилась

Компанія SaaS використовувала ZFS для внутрішнього сховища артефактів. Навантаження було в основному записами під час CI-піків і читаннями під час деплоїв. Ріст місця турбував, і хтось помітив, що багато артефактів мають ідентичні базові шари.

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

За місяць система артефактів почала пропускати SLA під час піків. Не через заповнені диски, а через те, що метадані тепер у критичному шляху для кожного запису. ARC був виснажений; система витрачала час на отримання записів DDT. Команда спробувала додати L2ARC, щоб «закешувати таблицю», що лише збільшило тиск на ОЗП і мало вплинуло на пікову латентність.

Остаточне рішення було нудним: відкотити dedup, увімкнути стиснення і переробити політики зберігання. Стиснення дало передбачувані заощадження з меншим метаданим болем. Перегляд політик зберігання скоротив довгий хвіст зростання. Dedup не був злочинцем сам по собі — він був неправильним інструментом для навантаження з високою мінливістю і недостатнім шаром для метаданих.

Міні-історія 3: Нудна, але правильна практика, яка врятувала ситуацію

Фінансова компанія експлуатувала ZFS-базовану платформу бекапів. Їх спокушав dedup, бо бекапи «повні повторів». Інженер зі зберігання — тихий, методичний і алергічний до сюрпризів — наполягав на передпольотному чеклісті перед тим, як щось вмикати.

Вони взяли репрезентативну вибірку: тиждень реальних бекапів, не синтетичних, і помістили її у стендовий пул. Виміряли коефіцієнт стиснення, коефіцієнт dedup, розмір DDT, поведінку ARC і пікову продуктивність прийому. Також вони симулювали scrub і resilver під навантаженням, бо найгірші відмови трапляються, коли обслуговування накладається на трафік.

Дані показали, що dedup допоможе, але лише якщо метадані житимуть на швидких пристроях. Тож вони побудували пул зі дзеркальним special vdev, розміреним для зростання метаданих, і ставилися до нього як до критичної інфраструктури (моніторинг, запасні пристрої, суворий контроль змін). Вони також обмежили паралелізм інгесту, щоб уникнути трешу DDT під час піків.

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

Практичні завдання: команди, виводи та як їх інтерпретувати

Нижче — конкретні завдання, які можна виконати на типовій системі OpenZFS (Linux з zfsutils). Деякі команди відрізняються на FreeBSD/Illumos, але ментальна модель лишається. Мета — не зазубрити прапори; мета — зробити поведінку dedup вимірюваною.

Завдання 1: Знайти датасети з увімкненим dedup

cr0x@server:~$ sudo zfs get -r -o name,property,value,source dedup tank
NAME                   PROPERTY  VALUE  SOURCE
tank                   dedup     off    default
tank/vmstore           dedup     on     local
tank/backups           dedup     off    inherited from tank

Інтерпретація: Dedup налаштовується на датасет. Якщо ви бачите навіть один критичний датасет з dedup=on, вважайте, що DDT-оверхед існує на рівні пулу. Відстежуйте, хто це ввімкнув і навіщо.

Завдання 2: Перевірити реальний коефіцієнт dedup на рівні пулу

cr0x@server:~$ sudo zpool list tank
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  54.5T  38.2T  16.3T        -         -    21%    70%  1.08x  ONLINE  -

Інтерпретація: DEDUP 1.08x означає, що ви заощаджуєте ~8% логічного простору через dedup. Це може не виправдовувати оверхед. Якщо менше ~1.2x, варто сумніватися, хіба що є дуже специфічна причина.

Завдання 3: Перевірити розмір DDT і наскільки «гаряча» вона

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

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
            sde     ONLINE       0     0     0
            sdf     ONLINE       0     0     0

dedup: DDT entries 48239124, size 34.1G on disk, 19.6G in core

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
     1    36.2M   9.44T   8.81T   8.81T    36.2M   9.44T   8.81T   8.81T
     2     8.7M   2.31T   2.16T   2.16T    18.1M   4.62T   4.32T   4.32T
     4     1.2M   353G    331G    331G     5.0M   1.38T   1.30T   1.30T

Інтерпретація: Ключовий рядок — «size X on disk, Y in core». Якщо «in core» великий щодо вашої ОЗП, або якщо він не може залишатися в ARC, вас чекають проблеми. Також зверніть увагу, скільки блоків мають refcnt=1: якщо більшість — це одиничні посилання, ви платите за dedup блоки, які фактично не дедуплені.

Завдання 4: Оцінити «марнотратство» dedup через лічильники посилань

cr0x@server:~$ sudo zdb -DD tank | head -n 25
DDT-sha256-zap-duplicate: 48239124 entries, size 34972804096 on disk, 21043748864 in core
DDT histogram (aggregated over all DDTs):

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
     1    36.2M   9.44T   8.81T   8.81T    36.2M   9.44T   8.81T   8.81T
     2     8.7M   2.31T   2.16T   2.16T    18.1M   4.62T   4.32T   4.32T

Інтерпретація: Якщо більшість блоків мають refcnt=1, dedup не виправдовує себе. Якщо у вас великий кластер у вищих refcnt (8, 16, 32), ось коли dedup починає виглядати як вигідна інвестиція.

Завдання 5: Перевірити розмір ARC і сигнали пам’ятного тиску

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c |c_min|c_max|misses|hits|demand_data_misses|demand_metadata_misses) '
size                            4    34325131264
c                               4    36507222016
c_min                           4    4294967296
c_max                           4    68719476736
hits                            4    1183749821
misses                          4    284993112
demand_data_misses              4    84129911
demand_metadata_misses          4    162104772

Інтерпретація: Високі demand_metadata_misses під навантаженням — ознака проблеми з dedup. Dedup — метадантоємний; якщо промахи метаданих ростуть, пул робитиме більше дрібних читань, і затримка підросте.

Завдання 6: Спостерігати реальну латентність і IOPS по vdev

cr0x@server:~$ sudo zpool iostat -v tank 2
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        38.2T  16.3T    110    980  11.2M  84.5M
  raidz2-0                  38.2T  16.3T    110    980  11.2M  84.5M
    sda                         -      -     18    165  1.9M  14.2M
    sdb                         -      -     19    164  1.8M  14.0M
    sdc                         -      -     17    162  1.7M  14.1M
    sdd                         -      -     18    163  1.9M  14.1M
    sde                         -      -     19    163  1.9M  14.0M
    sdf                         -      -     19    163  2.0M  14.1M

Інтерпретація: Це показує розподіл навантаження. Якщо dedup змушує робити випадкові читання метаданих, ви можете побачити зріст read IOPS навіть коли застосунок в основному пише. Поєднуйте це з інструментами для вимірювання латентності (нижче), щоб підтвердити.

Завдання 7: На Linux виявляти затримки, спричинені ZFS, через pressure metrics

cr0x@server:~$ cat /proc/pressure/memory
some avg10=0.32 avg60=0.18 avg300=0.07 total=12873631
full avg10=0.09 avg60=0.05 avg300=0.02 total=2219481

Інтерпретація: Тиск пам’яті сильно корелює з болем dedup. Якщо ARC бореться з ядром і застосунками за ОЗП, ви побачите зростання «full» pressure під час піків.

Завдання 8: Перевірити recordsize датасету і чому це важливо для зростання DDT

cr0x@server:~$ sudo zfs get -o name,property,value recordsize tank/vmstore
NAME         PROPERTY    VALUE
tank/vmstore recordsize  128K

Інтерпретація: Менший recordsize означає більше блоків для тих самих даних, що означає більше записів у DDT. Оверхед dedup масштабується з кількістю блоків, а не лише з байтами.

Завдання 9: Виміряти коефіцієнт стиснення перед тим, як тягнути за dedup

cr0x@server:~$ sudo zfs get -o name,property,value,source compression,compressratio tank/vmstore
NAME         PROPERTY       VALUE     SOURCE
tank/vmstore compression    lz4       local
tank/vmstore compressratio  1.52x     -

Інтерпретація: Якщо ви вже отримуєте 1.5x стиснення, приріст від dedup може бути малим — особливо з урахуванням витрат. Якщо стиснення вимкнене, виправте це спочатку, хіба що є вагома причина проти.

Завдання 10: Знайти, чи датасет платить за dedup без вигоди

cr0x@server:~$ sudo zfs get -o name,property,value written,logicalused,usedrefreserv usedbydataset tank/vmstore
NAME         PROPERTY       VALUE
tank/vmstore written        19.3T
tank/vmstore logicalused    27.8T
tank/vmstore usedrefreserv  0B
tank/vmstore usedbydataset  31.1T

Інтерпретація: logicalused проти фактично використаного може допомогти оцінити ефективність простору, але dedup ускладнює облік через спільні блоки. Використовуйте коефіцієнт dedup пулу і гістограми DDT, щоб вирішити, чи dedup «працює», а не тільки дивитися значення датасету.

Завдання 11: Вимкнути dedup для нових записів (і правильно виставити очікування)

cr0x@server:~$ sudo zfs set dedup=off tank/vmstore
cr0x@server:~$ sudo zfs get -o name,property,value dedup tank/vmstore
NAME         PROPERTY  VALUE
tank/vmstore dedup     off

Інтерпретація: Це зупиняє dedup для нових записів лише. Існуючі дедупльовані блоки залишаються. Продуктивність може покращитись, якщо ваше навантаження багато пише і ставка пошуків DDT впаде, але пул все одно несе DDT і його складність.

Завдання 12: Видалити дедупльовані дані єдиним справжнім способом: переписати або мігрувати

cr0x@server:~$ sudo zfs snapshot tank/vmstore@migration-start
cr0x@server:~$ sudo zfs send -R tank/vmstore@migration-start | sudo zfs receive -u tank2/vmstore
cr0x@server:~$ sudo zfs set dedup=off tank2/vmstore
cr0x@server:~$ sudo zfs mount tank2/vmstore

Інтерпретація: Відправлення снапшота реплікує блоки. Чи збережеться dedup — залежить від конфігурації приймача і характеру потоку send/receive. Операційно безпечний підхід: мігрувати до чистого пулу/датасету з dedup вимкненим і валідувати. Якщо ваша мета — «позбутися DDT», зазвичай треба перемістити дані в пул, який ніколи не мав dedup, або переписати їх на місці (що рідко приносить задоволення).

Завдання 13: Підтвердити, чи є у вас special vdev для метаданих

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

        NAME                              STATE     READ WRITE CKSUM
        tank                              ONLINE       0     0     0
          raidz2-0                        ONLINE       0     0     0
            sda                           ONLINE       0     0     0
            sdb                           ONLINE       0     0     0
            sdc                           ONLINE       0     0     0
            sdd                           ONLINE       0     0     0
            sde                           ONLINE       0     0     0
            sdf                           ONLINE       0     0     0
        special
          mirror-1                        ONLINE       0     0     0
            nvme0n1p2                     ONLINE       0     0     0
            nvme1n1p2                     ONLINE       0     0     0

Інтерпретація: Дзеркальний special vdev — великий пом’якшувач латентності метаданих для dedup. Це не усуває потреби в ОЗП, але може тримати систему на плаву, коли ARC під тиском.

Завдання 14: Слідкувати за поведінкою ZFS transaction group (псевдо-індикатор «чи стоїть сховище?»)

cr0x@server:~$ grep -E "txg_sync|txg_quiesce" /proc/spl/kstat/zfs/* 2>/dev/null | head
/proc/spl/kstat/zfs/tank/txgs:txg_sync 4 9123
/proc/spl/kstat/zfs/tank/txgs:txg_quiesce 4 9123

Інтерпретація: Якщо часи txg sync ростуть під час піків dedup, пул бореться з комітом змін. Dedup додає оновлення метаданих, що може погіршити тиск на sync.

Швидкий план діагностики: знайдіть вузьке місце, поки воно не знайшло вас

Ось порядок дій, який я використовую, коли хтось пише «ZFS повільний» і підозрює dedup. Мета — швидко звузити проблему, а не бути філософськи повним.

Крок 1: Чи взагалі увімкнений dedup і чи має він сенс?

  • Перевірте датасети: zfs get -r dedup POOL
  • Перевірте коефіцієнт пулу: zpool list
  • Перевірте розмір DDT: zpool status -D POOL

Рішення: Якщо коефіцієнт dedup низький (< ~1.2x) і DDT великий, у вас, ймовірно, «витрати без вигоди». Плануйте вихід з dedup, а не тюнінг навколо нього.

Крок 2: Чи вміщується DDT у пам’ять (або хоча б залишається гарячою)?

  • ARC-статистика: cat /proc/spl/kstat/zfs/arcstats
  • Подивіться на промахи метаданих і чи ростуть вони з навантаженням.
  • Перевірте тиск ОЗП ОС: /proc/pressure/memory

Рішення: Якщо тиск пам’яті високий і промахи метаданих ростуть, очікуйте, що пошуки dedup упадуть на диск. Оце й ваша латентність.

Крок 3: Чи потрапляють I/O метаданих на повільні пристрої?

  • Підтвердьте special vdev: zpool status
  • Спостерігайте read IOPS під час write-heavy навантаження: zpool iostat -v 2

Рішення: Якщо у вас немає special vdev і ви на HDD, dedup на великому масштабі рідко закінчується щасливо.

Крок 4: Чи прив’язане навантаження до CPU через хешування?

  • Перевірте CPU системи: top / mpstat (залежить від платформи)
  • Корелюйте високий CPU з пропускною здатністю запису і стабільною латентністю.

Рішення: Оверхед хешування існує, але більшість реальних катастроф з dedup пов’язані з пам’яттю/metadata I/O, а не з CPU. Не бігайте за неправильним драконом.

Крок 5: Швидко відсійте «не dedup» проблеми

  • Стан пулу: zpool status -x
  • Сканування/resilver: zpool status
  • Майже повний пул і фрагментація: zpool list (CAP) і дивіться FRAG.

Рішення: Пул на великій заповненості з високою фрагментацією буде працювати погано незалежно від dedup. Dedup може посилити біль, але не завжди є коренем проблеми.

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

Помилка 1: Увімкнути dedup, бо «у нас багато схожих даних»

Симптом: Коефіцієнт dedup залишається близько 1.00x–1.15x, а латентність погіршується.

Виправлення: Увімкніть стиснення (якщо ще не увімкнено), виміряйте реальну можливість дедуплікації на репрезентативній вибірці і розгляньте дедуплікацію на рівні додатка або стратегії клонування. Якщо dedup уже ввімкнено і шкодить — плануйте міграцію/перепис; не очікуйте, що dedup=off відкотить історію.

Помилка 2: Недооцінка росту DDT через малий recordsize

Симптом: Записи DDT вибухають; промахи ARC метаданих ростуть; під час важких записів з’являються випадкові read IOPS.

Виправлення: Перегляньте recordsize для датасету. Для VM-образів і загального зберігання 128K поширений вибір; менші розміри можуть бути необхідні для певних навантажень, але вони приходять з метаданими витратами. Якщо ви мусите використовувати маленькі блоки — dedup стає дорожчим.

Помилка 3: Сподівання, що L2ARC «вирішить» dedup

Симптом: Додаєте SSD-кеш і все одно бачите зупинки; використання ОЗП зростає; система під пік навантаження відчувається гіршою.

Виправлення: Розглядайте L2ARC як доповнення, а не заміну ОЗП. Якщо dedup необхідний, пріоритетом має бути достатня ОЗП і розглянути special vdev для метаданих. Валідируйте на робочому навантаженні.

Помилка 4: Увімкнення dedup на змішаному пулі без ізоляції

Симптом: Одне навантаження змінюється, і несуміжні сервіси бачать стрибки затримок. Люди починають звинувачувати мережу.

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

Помилка 5: Забування, що dedup підвищує операційну складність

Симптом: Scrub/resilver тривають довше, вікна обслуговування зсуваються; відпрацювання відновлення відчувається повільно.

Виправлення: Виміряйте поведінку scrub/resilver у стенді з увімкненим dedup. Моніторте і бюджетуйте час. Якщо RTO/RPO важливі, врахуйте цю вартість серйозно.

Помилка 6: Очікування простого відкату

Симптом: Ви ставите dedup=off і нічого істотно не змінюється; DDT лишається великим.

Виправлення: Прийміть фізику: дедупльовані блоки залишаються дедупльованими, доки їх не перепишуть. Чистий вихід — міграція до пулу без dedup або контрольований перепис даних (зазвичай через send/receive, копіювання типу rsync або реігридування додатком).

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

Чекліст A: «Чи слід вмикати dedup?» (передпольотна перевірка)

  1. Визначте мету: Це відкладення купівлі дисків, зменшення сліду бекапів чи активація специфічної функції?
  2. Спочатку виміряйте стиснення: Увімкніть compression=lz4 у тестовому датасеті і виміряйте compressratio.
  3. Візьміть репрезентативні дані: Використайте підмножину реальних даних (не вибрану папку) і тестуйте dedup у стенді.
  4. Виміряйте коефіцієнт dedup і розмір DDT: Зберіть zpool status -D і zdb -DD.
  5. Смоделюйте найгірший піковий прийом: Проганяйте пік записів, а не середній день.
  6. Протестуйте scrub під навантаженням: Переконайтесь, що ви можете тримати латентність і пропускну здатність у межах вимог.
  7. Визначте шар метаданих: Якщо dedup справді потрібен, плануйте дзеркальний special vdev і достатню ОЗП.
  8. Напишіть план відкату: Включіть, як ви будете мігрувати від dedup, якщо він не виправдає очікувань, і скільки це займе.

Чекліст B: Якщо dedup уже увімкнений і ви страждаєте

  1. Зупиніть кровотечу: Встановіть dedup=off на уражених датасетах, щоб уникнути подальшого росту DDT від нових записів (якщо тільки dedup не є критичним для цих даних).
  2. Квантифікуйте вплив DDT: Використайте zpool status -D і ARC-статистику, щоб підтвердити промахи метаданих і тиск пам’яті.
  3. Тимчасово зменшіть конкурентність: Якщо навантаження дозволяє (запис бекапів, батч-джоби), обмежте паралельних записувачів, щоб зменшити тиск на пошуки.
  4. Додайте ОЗП, якщо можливо: Це найшвидший важіль «стабілізувати зараз», хоча не завжди можливо негайно.
  5. Розгляньте додавання special vdev: Якщо підтримується і ви можете зробити це безпечно, перемістіть метадані на швидкі дзеркальні пристрої. Це може перетворити випадкові читання метаданих з «смерті» на «дратівливі».
  6. Сплануйте реальне виправлення: Мігрируйте датасети в новий пул з dedup вимкненим або перепишіть дані контрольовано.
  7. Валідуйте під навантаженням: Не оголошуйте перемогу після першої тихої години.

Чекліст C: «Dedup, але безпечно» (операційні запобіжні заходи)

  1. Моніторте розмір DDT і «in core» слід регулярно.
  2. Поставте алерти на зростання промахів метаданих і стійкий тиск пам’яті.
  3. Тримайте заповненість пулу в розумних межах; уникайте роботи майже на максимумі.
  4. Плануйте scrub з урахуванням пікових вікон навантаження.
  5. Документуйте, які датасети використовують dedup і навіщо, з відповідальним власником.

FAQ

1) Чи «поганий» ZFS dedup?

Ні. Він спеціалізований. Поганим він є як опція за замовчуванням, бо негативні наслідки гострі, а відкат складний. У правильному навантаженні з правильним залізом (достатньо ОЗП і швидкий шар для метаданих) він може бути відмінним.

2) Скільки ОЗП мені потрібно для dedup?

Достатньо, щоб тримати робочий набір DDT «гарячим». Існують правила великого пальця, але єдино безпечна відповідь: виміряйте «in core» розмір DDT і спостерігайте промахи метаданих під пік навантаження. Якщо система трешить — ОЗП замало.

3) Чи можна вимкнути dedup і повернути ОЗП?

Вимкнення dedup зупиняє нові операції dedup. Воно не видаляє існуючий DDT для вже дедупльованих блоків. Ви зменшуєте майбутнє зростання, але не стираєте минуле без переписування/міграції даних.

4) Чи допомагає dedup для зберігання VM?

Іноді. Якщо у вас багато близько-ідентичних VM-образів і ви не використовуєте ефективно клонування/снапшоти, dedup може зекономити місце. Але VM-навантаження також генерують мінливість, і «схожість» часто зникає з часом. Тестуйте на реальних VM-дисках і реалістичному часовому вікні.

5) Чи стиснення безпечніша альтернатива?

Зазвичай так. compression=lz4 широко використовується, бо часто покращує ефективну пропускну здатність (менше байтів на запис/читання) при мінімальних витратах CPU на сучасних системах. Її легше коригувати і вона не вимагає масивних таблиць метаданих.

6) Чи руйнує шифрування dedup?

Часто. Якщо дані шифруються до того, як ZFS їх бачить, блоки виглядають випадковими і не будуть дедуплюватись. Якщо ZFS шифрує датасет сам, поведінка dedup залежить від деталей реалізації і від того, коли відбувається dedup відносно шифрування. У багатьох практичних сценаріях шифрування суттєво зменшує вигоди від dedup.

7) Чи може special vdev «виправити» dedup?

Він може радикально зменшити біль, тримаючи метадані на швидких пристроях, що допомагає, коли DDT промахується ARC. Це не усуває потреби в ОЗП чи операційній складності. Він також стає критичною інфраструктурою: втратіть його — і ви можете втратити пул.

8) Чому мій пул повільний, хоча коефіцієнт dedup високий?

Високий коефіцієнт означає, що блоки поділяються, але це не гарантує, що DDT вміщується в пам’ять або що шлях метаданих швидкий. Ви можете мати значні економії й усе одно бути обмежені пошуками DDT, тиском txg sync або повільними пристроями для метаданих. Вимірюйте промахи ARC метаданих і «in core» DDT щодо ОЗП.

9) Який найнадійніший спосіб позбутися dedup після ввімкнення?

Міграція в новий пул (або принаймні новий датасет у пулі, який ніколи не мав dedup) з вимкненим dedup, далі валідація і переключення. Очистити in-place зазвичай означає переписування, що операційно складніше контролювати.

10) Чи вмикати dedup на спільному пулі, який використовують багато команд?

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

Висновок

ZFS dedup — це не «гарно мати». Це архітектурне рішення з постійним підписом на метаданих вашого пулу і вашому операційному житті. Якщо ставитись до цього як до галочки, воно ставитиметься до вашої ОЗП як до витраченого ресурсу, а до вашого бюджету затримок — як до пропозиції.

Коли dedup працює, він працює тому, що дані справді дублюються, і система побудована для швидкого обслуговування метаданих — спочатку ОЗП, потім серйозний шар для метаданих. Коли dedup зазнає невдачі, це тому, що хтось припускав, що схожість означає дублювання, або що відкат буде легким, або намагався вирішити проблему ОЗП SSD-пластирем. Ваш найкращий хід — дисципліна: тестуйте на реальних даних, розмірюйте шлях метаданих і майте план виходу перш ніж він знадобиться.

← Попередня
Маршрутний чи політико-базований VPN: що краще для офісів і чому
Наступна →
ZFS: шифрування і стиснення — порядок, що визначає продуктивність

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