ZFS arcstat: найшвидший спосіб дізнатися, чи допомагає кеш

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

Ваше сховище «працює нормально», поки не настане понеділок вранці. Латентність стрибає, CPU виглядають нудьгуючими, диски зайняті, і хтось каже: «але у нас купа RAM». Саме тоді ARC у ZFS стає або вашим найкращим другом, або тим самим тихим ворогом, який краде ваш обід.

arcstat — це найшвидша перевірка реальності, яку я знаю. Воно перетворює розмити легенди про кеш на числа, з якими можна сперечатися в рев’ю змін,
і робить це за секунди — без перезавантаження, без бенчмарків і без звичного інтерпретаційного танцю навколо «коефіцієнтів потрапляння».

Що таке arcstat (і чим воно не є)

arcstat — це крихітний скрипт, що знімає статистику ZFS ARC і виводить її як живу панель моніторингу. Запустили — спостерігаєте —
перестаєте гадати. Воно нічого не «налаштовує». Воно нічого не виправляє. Воно просто каже, що кеш робить зараз:
попадання, промахи, розміри і іноді форму вашого навантаження.

Якщо ви намагаєтеся відповісти на питання «чи допомагає кеш?», є щирий тест:
якщо коефіцієнт попадань ARC низький і ваші диски перевантажені, кеш вам не допомагає.
Якщо коефіцієнт попадань ARC високий і диски спокійні, ARC виконує корисну роботу.

Пастка: люди ставлять статистику ARC як показник статусу. «Подивіться на той 99% hit ratio!» Чудово — а на що саме? Метадані? Дрібні файли? Prefetch?
Ваше завдання — зіставити числа з реальною точкою болю: латентністю та пропускною здатністю там, де додаток чекає.

ARC простими операційними словами

ARC (Adaptive Replacement Cache) — це кеш у пам’яті у ZFS. Це не «просто page cache». Він конкурує з кешем ОС, з пам’яттю додатків
і з вашим відчуттям спокою. Він кешує блоки даних і метадані і працює агресивно, бо диск повільний, а RAM — швидка.

ARC «адаптивний», бо намагається балансувати дві категорії об’єктів у кеші:
недавно використані і часто використовувані. На практиці це означає, що ARC намагається пережити навантаження, які зруйнували б прості LRU-кеші:
потокові читання, змішані випадкові навантаження і операції, що інтенсивно зачіпають метадані.

Але ARC не порушує фізики. Якщо ваш робочий набір не поміщається в пам’ять, коефіцієнт попадань постраждає. Якщо навантаження — переважно стрімінгові читання,
кешування може бути нейтральним або навіть шкідливим. Якщо ви обмежені пам’яттю і ARC виростає занадто великим, ви обміняєте очікування на диску на своп-шторми —
угода, яку ніхто не має приймати.

Одна цитата, яку варто мати поруч під час змін:
Сподівання — це не стратегія. — Gene Kranz

Цікаві факти й історія, які можна використати на нарадах

  • ARC не був винайдений для ZFS. Алгоритм ARC опублікований у 2003 році й пізніше адаптований у ZFS, бо добре адаптується під змінні навантаження.
  • Кеш ZFS блочно-орієнтований, а не файловий. Він кешує блоки з DMU-шару, тому інтуїції про «файловий кеш» часто підводять.
  • ARC агресивно кешує метадані. Для багатьох середовищ (хости VM, збірки, Git-репозиторії) попадання по метаданих — це різниця між «все гаразд» і «чому ls повільний?»
  • L2ARC не є write-cache. Це розширення ARC на швидкі пристрої, але воно все ще потребує ARC для індексації, тож «більше кешу» коштує RAM.
  • L2ARC раніше був летким між ребутами. Ранні реалізації починали холодними; пізніші версії зробили можливим часткове збереження L2ARC у деяких реалізаціях.
  • У ZFS є окремий шлях для журналу намірів (ZIL/SLOG). ARC допомагає читанням; затримки синхронного запису часто більше про ZIL, ніж про ARC.
  • Prefetch може бути тихим агресором ARC. Для послідовних навантажень ZFS prefetch може заповнити ARC даними, які ви ніколи не будете повторно використовувати, витісняючи корисні блоки.
  • Стиснення змінює арифметику кешу. ARC зберігає стиснуті блоки (у багатьох реалізаціях), тому стиснення може ефективно збільшити місткість кешу для стиснутіх даних.
  • Коефіцієнт попадань ARC може виглядати «добре», поки користувачі страждають. Бо промахи, що мають значення, можуть бути на критичному шляху (наприклад, дрібні випадкові читання), тоді як попадання — по дешевих операціях.

Жарт №1: ARC схожий на офісні закуски — всі його люблять, поки він не з’їсть бюджет і хтось не почне ховати гранолу в столі.

План швидкої діагностики (перший/другий/третій)

Перший: підтвердьте, що система справді чекає на сховище

Не починайте з ARC. Почніть з «де вузьке місце». Якщо CPU насичені, ARC вам не допоможе. Якщо відбувається свопінг, ARC — частина проблеми.
Якщо диски простоїть, але латентність висока, можливо, блокування чи мережа або однопотокова поведінка додатку.

Другий: використайте arcstat, щоб класифікувати навантаження

Спостерігайте попадання/промахи ARC у часі, поки проблема відбувається. Дивіться на попит на читання і рівень промахів, а не лише на колонку «hit%».
Коефіцієнт попадань без контексту — KPI, створений, щоб вам було приємно.

Третій: вирішіть, який регулятор (knob) справді важливий

На підставі знахідок:

  • Якщо ARC замалий для робочого набору — потрібно більше RAM або змінити робоче навантаження (recordsize, primarycache, патерн доступу).
  • Якщо ARC великий, але трясе (thrashing) — ймовірно, потокові читання, надмірний prefetch або навантаження, що руйнує кеш; дивіться поведінку додатку та властивості dataset.
  • Якщо коефіцієнт попадань ARC хороший, але латентність погана — перестаньте дивитися на ARC і перевіряйте sync-записи, фрагментацію, розклад vdev і глибину черги.

Як читати arcstat ніби ви на чергуванні

arcstat виводить колонки, які трохи відрізняються між реалізаціями, але базові поняття стабільні:
розмір кешу, цільовий розмір, попадання, промахи, demand reads, prefetch reads і часто окремі метрики по метаданих.

Ментальна модель, яка працює в продакшені:

  • Попадання економлять I/O. Промахи створюють I/O.
  • Demand reads — це читання, які запросив додаток. Prefetch reads — це здогад ZFS про майбутнє.
  • Demand misses шкодять латентності. Prefetch misses в основному шкодять пропускній здатності та забруднюють кеш.
  • Розмір ARC повинен бути стабільним при сталому навантаженні. Дикі коливання означають тиск пам’яті або навантаження, що «збиває» кеш.

Припиніть поклонятися hit ratio; почніть корелювати з болем

Hit ratio — це дробове число. Дроби брешуть через упущення. Ви можете мати чудовий hit ratio, поки ваш додаток блокується через кілька промахів,
що торкаються гарячої таблиці або випадкових читань VM. Ви також можете мати посередній hit ratio з прийнятною латентністю,
якщо промахи послідовні й диски вміють їх стрімити.

ARC size проти target: хто перемагає в боротьбі за RAM

ARC зазвичай має «target» і поточний «size». Якщо ARC не може досягти target, хтось інший просить RAM. Якщо ARC постійно зменшується,
ядро повертає сторінки — іноді коректно, іноді жорстко. Режим відмови передбачуваний: тиск пам’яті викликає витіснення ARC,
витіснення ARC збільшує дисковий I/O, дисковий I/O підвищує латентність, латентність збільшує черги, і ви тепер з’ясовуєте не ту шар.

Demand vs prefetch: тест особистості вашого навантаження

Якщо demand hits високі — ARC робить свою роботу. Якщо домінують prefetch reads і prefetch hits низькі — ви, ймовірно, кешуєте сміття.
Тоді дивіться на dataset primarycache, secondarycache, recordsize і вирішуйте, чи варто відключати prefetch для певних навантажень.
Ви не вимикаєте prefetch глобально лише тому, що одна машина мала поганий день.

Жарт №2: Увімкнути L2ARC, щоб виправити навантаження — це як купити швидший тостер, бо обслуговування вечері повільне.

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

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

Завдання 1: Запустіть arcstat в реальному часі і визначте demand vs prefetch

cr0x@server:~$ arcstat 1
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:01:01   822    61     7    34    4    27    3     2    0   42.1G  48.0G
12:01:02   910    80     9    52    6    26    3     2    0   42.2G  48.0G

Значення: read — загальна активність читань ARC; miss/miss% — загальні промахи; dmis/dm% — demand промахи; pmis/pm% — prefetch промахи; arcsz — розмір ARC; c — ціль ARC.

Рішення: Якщо demand промахи високі під час видимої для користувача латентності, кеш не покриває робочий набір. Якщо домінують prefetch промахи — можливо, ви забруднюєте ARC read-ahead’ом.

Завдання 2: Підтвердьте, що ARC не змушують зменшуватися (тиск пам’яті)

cr0x@server:~$ arcstat -f time,arcsz,c,avail 1
    time   arcsz      c    avail
12:03:10  39.8G  48.0G    1.2G
12:03:11  38.9G  48.0G  900.0M
12:03:12  37.5G  48.0G  620.0M

Значення: ARC зменшується, поки доступна пам’ять падає. Це ядро просить повернути RAM.

Рішення: Якщо avail низький і ARC зменшується — пріоритет пам’ять: зменшити max ARC, виправити пам’ятевий хог або додати RAM. Не додавайте L2ARC; воно теж коштує RAM.

Завдання 3: Перевірте підсумкові лічильники ARC (Linux)

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(hits|misses|demand_data_hits|demand_data_misses|prefetch_data_hits|prefetch_data_misses|size|c) '
hits                            4 231889442
misses                          4 18122344
demand_data_hits                4 168221991
demand_data_misses              4 12188511
prefetch_data_hits              4 23311233
prefetch_data_misses            4 4932100
size                            4 45188173824
c                               4 51539607552

Значення: Сирі лічильники з моменту завантаження системи. Використовуйте їх, щоб порахувати співвідношення і підтвердити, що показує arcstat.

Рішення: Якщо demand_data_misses швидко зростає під час інцидентів — виправляйте fit робочого набору (RAM, recordsize, політика кешування). Якщо зростають лише prefetch промахи — працюйте з prefetch.

Завдання 4: Швидко порахуйте demand hit ratio (без самообману)

cr0x@server:~$ python3 - <<'PY'
import re
d={}
for line in open("/proc/spl/kstat/zfs/arcstats"):
    m=re.match(r'^(\w+)\s+\d+\s+(\d+)$', line.strip())
    if m: d[m.group(1)]=int(m.group(2))
h=d.get("demand_data_hits",0); m=d.get("demand_data_misses",0)
print("demand_data_hit_ratio = {:.2f}%".format(100*h/(h+m) if (h+m) else 0))
PY
demand_data_hit_ratio = 93.25%

Значення: Суто demand hit ratio, виключаючи шум prefetch.

Рішення: Якщо це високо, а ви все ще повільні — скоріше за все вузьке місце не в кешуванні читань (думаємо про sync-записи, CPU, блокування, мережу).

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

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  1  10488  51200  18000 7230000   12   45   620   130 8200 9100 10  5 70 15  0
 1  1  10520  48900  17920 7215000    0   32  1110   140 7600 8800  9  4 68 19  0

Значення: Ненульові si/so означають swap in/out; wa — I/O wait. Якщо відбувається свопінг, ARC конкурує з усім іншим.

Рішення: Зупиніть тонке налаштування продуктивності й усуньте тиск пам’яті. Зменшіть ARC, зупиніть memory hog або масштабуйтесь. Свопінг разом із ZFS — погана ситком-сцена.

Завдання 6: Перевірте I/O та латентність пулу ZFS (чи диски справжня проблема?)

cr0x@server:~$ zpool iostat -v 1 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
tank        9.12T  3.45T    640    210  82.1M  21.3M
  raidz2    9.12T  3.45T    640    210  82.1M  21.3M
    sda         -      -    110     36  13.8M   3.2M
    sdb         -      -    108     35  13.7M   3.1M
    sdc         -      -    107     34  13.6M   3.0M
    sdd         -      -    109     35  13.7M   3.1M

Значення: Якщо диски завантажені операціями читання одночасно з високими demand промахами ARC, ви зв’язані читанням. Якщо диски спокійні, а додаток повільний — ARC не головна причина.

Рішення: Якщо операції читання насичують систему і ARC промахи високі: додайте RAM, додайте vdev, змініть форму навантаження або перегляньте рівні зберігання. Якщо домінують записи: дивіться на синхронні записи й ZIL/SLOG.

Завдання 7: Перевірте I/O по процесу (впіймайте «одну дивну задачу»)

cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 115.62 M/s | Total DISK WRITE: 22.10 M/s
  PID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN  IO>    COMMAND
18234 be/4   backup     98.12 M/s   1.40 M/s  0.00 % 92.00 %  /usr/bin/rsync -a --delete /data /backup
 9121 be/4   postgres   12.40 M/s  10.10 M/s  0.00 %  8.00 %  postgres: checkpointer

Значення: Послідовне сканування або бекап може роздути ARC read-ahead і створити промахи, що шкодять інтерактивним навантаженням.

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

Завдання 8: Перегляньте політику кешування dataset (primarycache/secondarycache)

cr0x@server:~$ zfs get -o name,property,value primarycache,secondarycache tank/vmstore
NAME         PROPERTY        VALUE
tank/vmstore primarycache    all
tank/vmstore secondarycache  all

Значення: primarycache контролює те, що потрапляє в ARC; secondarycache контролює, що йде в L2ARC.

Рішення: Для VM-образів з сильним стрімінговим поведінкою розгляньте primarycache=metadata, щоб захистити ARC для метаданих і дозволити гостевим читанням звертатися до диска передбачувано.

Завдання 9: Змінити primarycache для dataset (хірургічно, зворотньо)

cr0x@server:~$ sudo zfs set primarycache=metadata tank/backup
cr0x@server:~$ zfs get -o name,property,value primarycache tank/backup
NAME        PROPERTY      VALUE
tank/backup primarycache  metadata

Значення: Ви наказуєте ZFS кешувати метадані, але не дані файлів для цього dataset.

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

Завдання 10: Перевірте recordsize (підбір під навантаження важливіший, ніж визнають)

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

Значення: Recordsize впливає на I/O-ампліфікацію і ефективність кешу. Бази даних часто вимагають менших блоків (наприклад, 16K), щоб уникнути читання 128K для задоволення 8K-запиту.

Рішення: Якщо бачите багато дрібних випадкових читань і погану ефективність ARC — розгляньте зміну recordsize для цього dataset (обережно; це впливає на нові записи, не на старі).

Завдання 11: Спостерігайте поведінку prefetch через лічильники ARC

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(prefetch_data_hits|prefetch_data_misses|demand_data_hits|demand_data_misses)'
demand_data_hits                4 168331120
demand_data_misses              4 12194410
prefetch_data_hits              4 23311610
prefetch_data_misses            4 4981044

Значення: Якщо prefetch промахи швидко зростають одночасно з demand промахами, prefetch може витісняти корисні дані. Якщо prefetch промахи ростуть, а demand промахи стоять на місці — можливо, це просто даремний трафік.

Рішення: Якщо prefetch шкодить — ізолюйте проблемний dataset і розгляньте політику кешування або графік виконання. Не відключайте prefetch різко по всій системі.

Завдання 12: Перевірте параметри розміру ARC (Linux OpenZFS)

cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_arc_max
68719476736
cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_arc_min
4294967296

Значення: ARC max/min у байтах. Якщо max завеликий відносно системної RAM і навантаження, можна спричинити тиск пам’яті і своп.

Рішення: Якщо хост запускає додатки, яким потрібна RAM (бази даних, JVM, гіпервізори), обмежте ARC свідомо. Якщо хост — це апаратний storage appliance, дозвольте ARC використовувати більшість RAM, але лишайте запас для ядра і пікових навантажень.

Завдання 13: Тимчасово обмежити max ARC (обережно, але ефективно)

cr0x@server:~$ echo $((32*1024*1024*1024)) | sudo tee /sys/module/zfs/parameters/zfs_arc_max
34359738368
cr0x@server:~$ sudo cat /sys/module/zfs/parameters/zfs_arc_max
34359738368

Значення: Ви зменшили максимум ARC до 32 GiB. ARC поступово адаптується; воно не стане миттєво до нового ліміту.

Рішення: Використовуйте це, коли тиск пам’яті викликає своп або ризик OOM. Після застосування спостерігайте своп і промахи ARC. Якщо промахи різко виростуть і диски наситяться, можливо, ви поміняли одну проблему на іншу; перегляньте архітектуру (більше RAM, розділення ролей, додаткові vdev).

Завдання 14: Перевірте, чи взагалі використовується L2ARC

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(l2_hits|l2_misses|l2_size|l2_asize)'
l2_hits                         4 892331
l2_misses                       4 3211044
l2_size                         4 17179869184
l2_asize                        4 21474836480

Значення: L2ARC hits/misses показують, чи ваш «SSD-кеш» реально віддає читання. l2_size — дані, що збережені; l2_asize — виділено.

Рішення: Якщо l2_hits майже не росте під час навантаження — L2ARC не допомагає. Часті причини: робочий набір вже вміщується в ARC, dataset не допускає secondarycache, або навантаження — орієнтоване на записи чи стрімінгове.

Завдання 15: Корелюйте промахи ARC з реальною латентністю на блочному пристрої

cr0x@server:~$ iostat -x 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          10.12    0.00    4.01   18.55    0.00   67.32

Device            r/s     w/s   rkB/s   wkB/s  aqu-sz  await  svctm  %util
sda             110.0    36.0  14120   3300     9.20   68.2    2.4   35.2
sdb             108.0    35.0  14080   3200     9.10   66.7    2.3   34.8

Значення: await — середній час, який запити проводять у системі (черга + обслуговування). Високий await разом з високими demand промахами ARC — класична картина «кеш не покриває, диски в черзі».

Рішення: Якщо await зростає при зростанні demand промахів — фокусуйтеся на робочому наборі читань, розкладці vdev або додаванні IOPS. Якщо await нормальний, але затримка додатка висока — перевіряйте блокування, CPU, мережу або поведінку sync-записів.

Завдання 16: Перевірте поведінку sync-записів (бо не все залежить від ARC)

cr0x@server:~$ zfs get -o name,property,value sync logbias tank/postgres
NAME          PROPERTY  VALUE
tank/postgres sync      standard
tank/postgres logbias   latency

Значення: Якщо проблема в «повільних записах», ARC не ваш герой. sync і logbias впливають на обробку синхронних записів і поведінку ZIL.

Рішення: Для інцидентів з затримками записів перевірте, чи навантаження синхронне і чи маєте ви відповідний SLOG-пристрій. Не маскуйте проблему міфами про кеш.

Три корпоративні міні-історії (з болем)

Інцидент через хибне припущення: «Більший ARC — швидші бази даних»

Середня компанія запускала кластер PostgreSQL на ZFS з великою кількістю RAM. Команда збереження вважала: «ARC має використовувати якнайбільше пам’яті».
Вони підняли zfs_arc_max і святкували більший показник кешу в дашбордах. Через тиждень, під час місячного звітування, латентність стрибнула.

Команда баз даних звинуватила storage. Storage звинуватив запити. Усі звикли звинувачувати «мережу». Графіки показували гарний hit ratio ARC.
Це був неправильний показник для поклоніння.

Коли ми запустили arcstat під час інциденту, demand промахи не були катастрофічні — але був тиск пам’яті. Доступна пам’ять впала,
ядро агресивно повертало сторінки, і почався своп. База даних мала налаштовані shared buffers з причин, але ARC вторгся і змусив ОС робити некрасиві вибори. Рішення «збільшити ARC» не дало більше попадань; воно створило нестабільну поведінку пам’яті.

Виправлення було нудним: обмежити ARC, лишивши запас для бази та ядра, а потім відрегулювати пам’ять бази даних за наміром. Demand промахи трохи зросли,
але латентність покращилась, бо система перестала свопити. Великий урок: ARC — не «безкоштовна продуктивність». Це орендар у вашій RAM-квартирі, і іншим мешканцям треба залишити місце.

Оптимізація, що відгукнулась боком: «Додаємо L2ARC SSD скрізь»

Інший магазин стандартизував «два NVMe для L2ARC» на кожному хості, бо хтось прочитав, що «SSD-кеш робить ZFS швидким».
Вони розгорнули це як апаратний шаблон. Виглядало сучасно. Закупівля була щаслива. Людям подобається купувати блискучі речі.

Потім дивність: деякі хости стали повільніші під змішаним навантаженням. Не «трохи». Значно. Пакетна обробка стартувала нормально, а потім деградувала.
Графіки показували зростання використання пам’яті і додаткове ядрове навантаження. Латентність зберігання не завжди покращувалась.

Ми зняли arcstat і перевірили лічильники L2ARC. L2ARC hits були низькими. ARC вже обслуговував гарячий набір у RAM.
Тим часом система платила накладні витрати за наповнення й управління L2ARC, і використовувала RAM для заголовків L2ARC. Під тиском ARC зменшився,
і залишковий кеш став менш ефективним. Додавання «більшого кешу» зменшило ефективність кешу.

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

Нудна, але правильна практика, що врятувала день: «Міряти під час інциденту, а не після»

Великий внутрішній сервіс Git почав таймаути під час тижня релізів. Симптом був «випадкова повільність»: іноді клонування зависало,
іноді веб-інтерфейс гальмував, іноді все виглядало нормально. На чергуванні зробили рідкісну і правильну річ: зібрали живі докази
поки користувачі скаржилися.

Вони запустили arcstat, zpool iostat і iotop одночасно в tmux і зняли п’ять хвилин виводу.
Шаблон став ясний. Demand промахи стрибали синхронно зі специфічною maintenance-задачею, що обходила величезні дерева директорій.
Диски накопичували черги, промахи по метаданих зростали, і латентність слідувала за цим. Нічого магічного — просто зіткнення навантажень.

Оскільки були дані, а не відчуття, пом’якшення було чистим: перенести вікно задачі, ізолювати політику кешування dataset і лишити ARC
орієнтованим на метадані для репозитарію. Інцидент закінчився без зміни апаратури, без звинувачень і без двотижневого «проєкту продуктивності».

Практика не була гламурною. Вона просто полягала у: збирати правильні живі метрики рано, а потім ухвалювати рішення на підставі доказів. Так уникнути рядка в постмортемі «ми не змогли відтворити».

Типові помилки: симптом → корінна причина → виправлення

1) «Коефіцієнт попадань ARC високий, але читання все одно повільні»

Симптом: Гарний hit%, зате латентність користувача все одно погана.

Корінна причина: Попадання — здебільшого по метаданих або по дешевих читаннях; промахи на критичному шляху — небагато, але болісні (дрібні випадкові читання, гарячі сторінки БД). Або вузьке місце — записи/CPU/мережа.

Виправлення: Використовуйте статистику лише по demand і корелюйте з латентністю диска (iostat -x) і I/O пулу (zpool iostat). Якщо диски не обмежують — перемикайтеся: sync-записи, насичення CPU, контенція на рівні додатку.

2) «ARC постійно зменшується і росте; продуктивність нестабільна»

Симптом: arcsz скаче, латентність коливається, іноді своп.

Корінна причина: Тиск пам’яті. ARC витісняється; хост виконує занадто багато ролей (VM + база + ARC) без обмежень.

Виправлення: Обмежте ARC (zfs_arc_max), зменшіть конкуренцію за пам’ять або розділіть ролі по хостах. Перевірте, щоб своп був мінімальним при нормальному навантаженні.

3) «Prefetch промахи величезні; ARC ніби марний»

Симптом: pmis домінує, demand hit rate падає під час сканувань.

Корінна причина: Потокове навантаження (бекапи, scrubs, сканування) і prefetch тягнуть дані, які не повторно використовуються; забруднення кешу.

Виправлення: Ізолюйте це навантаження (планування/обмеження), виставте primarycache=metadata на dataset, що сильно сканується, і підтвердіть поліпшення demand промахів для чутливих до латентності dataset.

4) «Ми додали L2ARC і нічого не змінилося»

Симптом: SSD для кешу встановлено, але l2_hits майже не росте; латентність незмінна.

Корінна причина: Робочий набір уже поміщається в ARC; dataset не допускає secondarycache; або навантаження орієнтоване на записи і не прив’язане до промахів читання.

Виправлення: Спочатку доведіть потребу: стійкі demand промахи під час реальних вікон навантаження. Потім переконайтесь у secondarycache=all де треба й у наявності RAM для накладних витрат L2ARC індексації.

5) «Після зменшення ARC система стала повільнішою»

Симптом: Ви обмежили ARC і латентність читань зросла.

Корінна причина: Навантаження дійсно потребує кешу читань; ARC приховував повільні диски. Ваш ліміт зняв пластир.

Виправлення: Вирішіть свідомо: додайте RAM, додайте vdev/IOPS або змініть навантаження. Якщо хост повинен одночасно запускати додатки й зберігання, плануйте ємність так, щоб обом було комфортно.

6) «Випадкові читання на RAIDZ відчуваються жахливо»

Симптом: Низький hit ARC, велике навантаження read IOPS, черги, погана латентність.

Корінна причина: RAIDZ vdev не призначені для великої кількості IOPS; дрібні випадкові читання карають їх. ARC не виправить невідповідність між навантаженням і розкладкою vdev.

Виправлення: Додайте mirror vdev для IOPS, додайте більше vdev або перемістіть навантаження на пул, спроектований для випадкових I/O. Використовуйте ARC як допоміжний інструмент, а не як замінник архітектури.

7) «Ми налаштували recordsize і кеш виглядає гірше»

Симптом: Після зміни recordsize hit rate змінився непередбачувано; продуктивність мішана.

Корінна причина: Recordsize впливає лише на нові записи; старі дані залишаються з попереднім розміром блоків. Тепер на диску змішаний формат і статистика спантеличує.

Виправлення: Оцінюйте дані, записані після зміни, або перезапишіть дані там, де потрібно. Уникайте змін recordsize без плану міграції і чіткої мети навантаження.

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

Чекліст A: «Чи допомагає ARC зараз?» (5 хвилин)

  1. Запустіть arcstat 1 і спостерігайте demand промахи та стабільність розміру ARC.
  2. Запустіть zpool iostat -v 1, щоб побачити, чи vdev насичені.
  3. Запустіть iostat -x 1, щоб перевірити await і глибину черги.
  4. Якщо demand промахи низькі і диски спокійні: перестаньте звинувачувати кеш.
  5. Якщо demand промахи високі і диски в черзі: кеш не покриває; плануйте RAM/vdev/зміну навантаження.

Чекліст B: «Чи створює ARC проблеми?» (тріаж тиску пам’яті)

  1. Перевірте vmstat 1 на наявність свопінгу (si/so).
  2. Перевірте arcstat -f arcsz,c,avail 1 на предмет зменшення ARC і низької доступної пам’яті.
  3. Якщо свопінг або avail постійно низькі: обмежте ARC і/або зменшіть споживання пам’яті додатками.
  4. Після змін переконайтесь, що своп спокійний і demand промахи не вибухнули.

Чекліст C: «Чи варто додавати L2ARC?» (не купуйте обладнання за відчуттями)

  1. Доведіть стійкі demand промахи під час реальних вікон навантаження.
  2. Доведіть, що диски читацьки насичені (ops і латентність) коли ці промахи відбуваються.
  3. Підтвердіть, що навантаження має повторні читацькі звернення (не одноразовий потік).
  4. Переконайтесь, що у вас є RAM-запас для накладних витрат L2ARC і індексації.
  5. Розгорніть на одному хості, виміряйте зростання l2_hits і вплив на латентність, потім масштабуйтесь.

Чекліст D: «Вносити зміни на рівні dataset безпечно»

  1. Визначте dataset, що забруднює кеш (з iotop + таймінг + поведінка arcstat).
  2. Коригуйте primarycache або recordsize тільки для цього dataset, а не глобально.
  3. Задокументуйте базову картину: п’ять хвилин arcstat, zpool iostat, iostat -x.
  4. Застосуйте зміну, переміряйте під тим самим вікном навантаження.
  5. Якщо гірше — відкатіть негайно. Тримайте своє его осторонь.

FAQ

1) Яке єдине число arcstat, за яким слід стежити?

Demand промахи під час вікна проблеми. Не загальний hit%. Якщо demand промахи ростуть і разом з ними росте дискова латентність — кеш не покриває.

2) Чи є 90–95% ARC hit ratio «добре»?

Можливо. Це залежить від того, що саме попадає. Високий hit ratio при поганій латентності часто означає, що промахи на критичному шляху, або проблема взагалі не в кешуванні читань.

3) Чому prefetch промахи такі великі, і чи панікувати?

Prefetch промахи можуть бути високими при послідовних навантаженнях. Панікуйте лише якщо активність prefetch корелює з витісненням корисних даних з ARC і зростанням користувацької латентності.

4) Чи кешує ARC записи?

ARC здебільшого є кешем читань. Записи проходять через transaction groups і можуть бути буферизовані в пам’яті, але проблеми з латентністю записів часто пов’язані із синхронними записами і ZIL/SLOG, а не з ARC.

5) Якщо я додам RAM, чи завжди покращиться продуктивність?

Якщо ви обмежені промахами читань і ваш робочий набір піддатливий кешуванню — так, часто суттєво. Якщо ви обмежені синхронними записами, CPU або мережею — RAM не допоможе.

6) Коли L2ARC справді допомагає?

Коли у вас читальне навантаження з робочим набором, більшим за RAM, але з частими повторними читаннями, і ваші диски — вузьке місце. L2ARC — не універсальний прискорювач.

7) Чому система стала повільнішою після додавання L2ARC?

Тому що L2ARC споживає RAM для метаданих і додає роботу на керування кешем. Якщо ARC вже був достатній, ви заплатили накладні витрати без користі і, можливо, підвищили тиск пам’яті.

8) Чи ставити primarycache=metadata для VM-образів?

Часто це хороший крок, коли віртуальні машини виконують багато стрімінгових читань, що «висмикують» кеш. Протестуйте на підмножині; деякі VM-навантаження виграють від кешування даних.

9) Чи покращує стиснення ефективність ARC?

Часто так, бо в кеші зберігаються стиснуті блоки, і логічно більше даних поміщається в ту саму RAM. Але стиснення витрачає CPU — вимірюйте обидва боки.

10) Чому arcstat виглядає по-різному на різних системах?

Різні дистрибутиви й скрипти друкують різні колонки і назви. Основні концепти — попадання, промахи, розмір ARC, demand vs prefetch — це те, до чого треба прив’язуватися.

Висновок: реальні наступні кроки

Якщо ви візьмете одну звичку з цього: запускайте arcstat під час інциденту, а не після. Поєднуйте його з zpool iostat та iostat -x.
За десять хвилин ви зазвичай зможете відповісти на єдине важливе питання: «Чи блокуються ми на дискових читаннях, які кеш міг би обслуговувати?»

Практичні наступні кроки:

  1. Зніміть п’ятихвилинний базовий зріз під нормальним навантаженням: arcstat + zpool iostat + iostat -x.
  2. Під час наступної повільності зніміть той же набір і порівняйте demand промахи й дискову латентність.
  3. Якщо є тиск пам’яті — свідомо обмежте ARC і усуньте своп першочергово.
  4. Якщо demand промахи — оберіть одне: додати RAM, змінити розклад vdev для IOPS або змінити політику кешування dataset/робочого навантаження.
  5. Якщо ARC виглядає здоровим — припиніть налаштування кешу і шукайте реальне вузьке місце (sync-записи, CPU, мережа, блокування).

Кеш — не стратегія продуктивності. Це множник продуктивності — використовуйте його, коли арифметика працює, і ігноруйте, коли ні, а вимірюйте свідомо.

← Попередня
WireGuard full mesh: коли варто робити прямі тунелі між офісами (і коли ні)
Наступна →
Дешеві БЖ: як економія $20 перетворюється на феєрверк

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