Війни кешів рідко виграють у бенчмарках і часто програють в продакшні о 2-й ночі, коли графік сховища схожий на сейсмограф і команда бази даних починає казати «мабуть, проблема в мережі».
ZFS має ARC. Linux має кеш сторінок. Обидва дуже хороші у своїй справі, і обидва можуть зіпсувати вам день, якщо ви припускаєте, що це те саме з різними назвами.
Цей матеріал про практичну правду: що саме кешує кожен механізм, як вони поводяться під навантаженням, чому іноді виникає «подвійне кешування» і як вирішити, хто повинен тримати пам’ять при змішаному навантаженні.
Ви отримаєте історію, механіку, інцидентні історії з реальних сценаріїв експлуатації, конкретні команди та швидкий план діагностики, який можна застосувати, перш ніж хтось запропонує «просто додати RAM».
Два кеші в одній фразі
Кеш сторінок Linux кешує дані файлів так, як їх бачить ядро через VFS — широко і оппортуністично; ZFS ARC кешує об’єкти та метадані ZFS всередині стеку ZFS, агресивно і за своїми правилами.
На практиці: кеш сторінок — це «запам’ятай на всякий випадок» мозок ОС; ARC — це «я знаю, що мені знадобиться наступним» мозок ZFS — іноді розумніший, іноді впертіший.
Жарт #1 (коротко, по суті): питати «який кеш кращий» — це все одно, що питати, чи кращий вилочний навантажувач за пікап. Якщо потрібно перевозити піддони, вилочний навантажувач вразить — поки ви не спробуєте їхати ним по трасі.
Цікаві факти та коротка історія (що дійсно важливо)
Кешування не нове, але деталі того, де і як воно реалізоване, формують операційні режими відмов. Декілька конкретних пунктів, які зазвичай впливають на рішення:
- ZFS виник у світі Solaris, де файлову систему і менеджер томів тісно інтегрували. ARC — частина цієї інтегрованої архітектури, а не пристикований «псевдо-Linux» кеш.
- ARC адаптивний: він спроектований так, щоб балансувати між кешуванням нещодавно використаних і часто використовуваних даних (приблизно MRU vs MFU). Ця адаптивність — особливість і джерело сюрпризів.
- ZFS робить контрольні суми для всього і може самовідновлюватися за допомогою надмірності. Це означає, що читання — це не просто «читання байтів»; є метадані і верифікація, які кешування може або посилити, або зменшити.
- Кеш сторінок Linux старший за багато сучасних файлових систем. Він глибоко вбудований у очікування продуктивності Linux; багато додатків тихо на нього розраховують, навіть якщо не говорять про це.
- Історично ZFS на Linux мусив поєднати двох менеджерів пам’яті: Linux VM і власну поведінку ARC. Сучасний ZoL/OpenZFS значно кращий за ранні дні, але модель «два мозки» досі має значення.
- L2ARC з’явився пізніше разом із тим, як SSD стали життєздатним кешем для читань. Це не «більше ARC»; це розширення з власними витратами, включаючи метадані і час прогріву.
- ZIL і SLOG стосуються синхронних записів, а не кешування читань. Люди іноді купують «швидкий SLOG», щоб поліпшити латентність читань — це як встановити кращу поштову скриньку, щоб покращити акустику в вітальні.
- Direct I/O та шляхи обходу розвивалися разом з базами даних. Багато серйозних СУБД навчилися свідомо обходити кеш сторінок; ZFS має свої підходи у цій сфері, але не всі поєднання працюють гладко.
- Сучасний Linux працює з cgroups повсюдно. ARC історично не завжди поводився як «хороший громадянин» у межах обмежень пам’яті; нові релізи покращили це, але команди опсів досі спускаються на гачок невідповідних очікувань.
Ментальна модель: що де живе
Коли додаток читає файл, уявіть шлях шарів: app → libc → kernel VFS → filesystem → block layer → диск. Кеш сторінок Linux сидить ближче до боку VFS і кешує сторінки файлів, індексовані inode/offset.
ZFS, натомість, має свій конвеєр: DMU об’єкти, dnodes, ARC буфери, vdev I/O планувальник і пул. ARC кешує на рівні ZFS, а не просто «сторінки файлів».
Ця різниця дає три експлуатаційні наслідки:
- Метадані виграють: метадані ZFS (dnodes, indirect блоки, spacemaps) можуть кешуватися в ARC, і кешування метаданих радикально змінює випадкову продуктивність читання. Кеш сторінок Linux теж кешує метадані, але метадані ZFS — це… більше.
- Стиснення/шифрування змінюють економіку: ARC може тримати стиснуті буфери залежно від налаштувань; кеш сторінок зазвичай тримає розпаковані сторінки файлів, як їх бачать додатки.
- Сигнали витіснення і тиск різні: Linux VM може швидко реклеймити кеш сторінок під тиском. ARC може зменшуватись, але його налаштування та евристики можуть не відповідати тому, що решта системи вважає «тиском».
Глибоке занурення в ZFS ARC (що кешується і чому це дивно)
Що насправді кешує ARC
ARC не є «RAM-диском для ваших файлів». Він кешує ZFS буфери: блоки даних і блоки метаданих у тому вигляді, в якому вони існують у конвеєрі ZFS. Це включає дані файлів, але також й інфраструктуру, потрібну щоб знайти дані швидко:
dnode структури, вказівники indirect блоків та інше.
В експлуатаційних термінах, ARC — це причина, чому пул ZFS, який «палав» під час метаданого-інтенсивного сканування, раптом заспокоюється після прогріву: друге проходження — це здебільшого перебір вказівників у RAM замість диска.
Адаптивна політика ARC (MRU/MFU) і чому ви бачите «промахи кешу», які не є відмовами
ARC балансує між «недавно використаними» та «часто використовуваними» буферами. Він також відстежує ghost-списки — те, що було нещодавно витіснено — щоб навчитися, чи було рішення правильним. Це хитро й зазвичай корисно.
Але це означає, що ARC може виглядати ніби він «працює», навіть коли він «працює як задумано».
Оператори часто неправильно читають коефіцієнт попадань ARC як універсальний KPI. Це не так. Низький відсоток попадань може бути нормальним, якщо ваше навантаження — потокове читання великих файлів один раз. Високий відсоток попадань може вводити в оману, якщо ви випадково кешуєте навантаження, яке має бути послідовно стрімоване з мінімальним збереженням.
Розмір ARC: частина, що породжує суперечки
На Linux ARC конкурує з усім іншим: кешем сторінок, анонімною пам’яттю, slab і вашими додатками. ARC має обмеження (zfs_arc_max та інші), і він може зменшуватися під тиском, але час реакції має значення.
Коли тиск пам’яті зростає швидко (стартує пакетна задача, великий сортування, сплеск контейнерів), ARC може не скоротитися достатньо швидко, і ядро почне реклеймити інші області — іноді кеш сторінок, іноді анонімні сторінки — призводячи до стрибків латентності або навіть OOM.
Практичне питання налаштування не в «наскільки великим може бути ARC?», а в «наскільки великим ARC може бути без дестабілізації решти системи?»
ARC і поведінка записів: не те саме, що кеш сторінок
Кеш сторінок Linux тісно пов’язаний з writeback і обліком брудних сторінок. ZFS має свої власні transaction groups (TXGs), ліміти брудних даних і конвеєр, де дані стадіюються, записуються й фіксуються.
ARC переважно стосується читань, але історія пам’яті системи включає брудні дані в польоті та оновлення метаданих.
Саме тому «вільна пам’ять» — неправильна метрика на системах ZFS. Вас цікавить реєстрованість для реклейму і латентність під тиском, а не те, чи виглядає сервер порожнім на дашборді.
L2ARC: SSD-кеш, що поводиться як повільна друга RAM
L2ARC розширює ARC на швидкі пристрої, зазвичай SSD. Він може допомогти при випадкових читаннях, коли робочий набір більший за RAM і коли шаблон доступу має повторне використання.
Але це не магія: L2ARC потрібно наповнити (прогріти), він може збільшити тиск пам’яті через відстеження метаданих і додає I/O навантаження на пристрій кешу.
У продакшні найпоширеніше розчарування L2ARC — очікування, що він виправить навантаження, яке переважно складається з одноразових читань. Ви не можете закешувати шляхом кешування «я прочитав петабайт один раз».
Глибоке занурення в кеш сторінок Linux (що кешується і чому він всюди)
Опис роботи кешу сторінок
Кеш сторінок Linux кешує сторінки, прив’язані до файлів: ті самі байти, які будуть повернуті процесу при читанні файлу (після файлової трансляції). Він також кешує метадані та директрії через dentry і inode кеші.
Його сила в тому, що це значення за замовчуванням: майже кожна файлова система і майже кожен додаток отримують користь автоматично.
Реклейм і writeback: кеш сторінок задуманий як жертвенний
Linux ставиться до кешу сторінок як до підлягаючого реклейму. Під тиском пам’яті ядро може швидко скидати чисті сторінки кешу. Брудні сторінки потрібно записувати, що вводить латентність і I/O.
Саме тому налаштування «dirty ratio» може змінити хвостову латентність у системах з важкими записами.
Кеш сторінок — це екосистема з VM: kswapd, direct reclaim, dirty throttling і облік по cgroup (у багатьох конфігураціях). Саме тому Linux часто відчувається «саморегулюючимся» в порівнянні з системами, де кеші більш ізольовані.
Read-ahead і послідовні навантаження
Кеш сторінок добре розпізнає послідовні шаблони доступу і виконує read-ahead. Це величезний плюс для потокових читань.
Саме тому ваш бенчмарк, який читає файл двічі, виглядає «чудово» вдруге — якщо ви не обходите кеш сторінок або файл не занадто великий.
Direct I/O і рушії баз даних
Багато баз даних використовують direct I/O, щоб уникнути подвійного буферизації і контролювати власне кешування. Це має сенс, коли буфер кешу бази даних зрілий і шаблон доступу випадковий.
Але це також перекладає тягар коректності кешування і налаштування на додаток, що добре, поки ви не запускаєте його у віртуалці з шумними сусідами.
Тож хто перемагає?
Чесна відповідь: ніхто не «перемагає» глобально. Практична відповідь: ARC зазвичай перемагає, коли продуктивність визначається метаданими ZFS і розумом ZFS, тоді як кеш сторінок виграє, коли навантаження орієнтоване на файли, послідовне і добре підпадає під модель VFS.
ARC «перемагає», коли:
- Метадані мають значення: багато дрібних файлів, знімків (snapshots), клонів, обхід директорій, випадкові читання, що вимагають глибоких обходів дерев блоків.
- Активні можливості ZFS: стиснення, контрольні суми, snapshots, налаштування recordsize — ARC кешує «реальні» блоки і метадані в форматі, який потрібен ZFS.
- Ви дозволяєте ZFS приймати рішення: ви приймаєте, що файлова система — активний учасник, а не пасивне сховище байтів.
Кеш сторінок Linux «перемагає», коли:
- Навантаження стрімінгове: великі послідовні читання, медіапайплайни, читання резервних копій, великі ETL-скани.
- Додатки очікують семантику Linux VM: багато софту налаштовані з урахуванням реклейму кешу сторінок і поведінки cgroup.
- Ви не використовуєте ZFS: так, очевидно, але варто сказати — кеш сторінок зірка шоу для ext4/xfs та інших.
Справжній матч — це «хто краще співпрацює під тиском»
Більшість інцидентів у продакшні не про стабільну продуктивність. Вони про те, що відбувається, коли навантаження раптово змінюється:
починається переіндексація, стартує бекап, масштабуються контейнери, вузол починає resilvering, або якась робота читає весь датасет раз.
«Перемагає» той механізм кешування, який деградує більш плавно при таких змінах. На Linux з ZFS це означає зробити ARC хорошим громадянином, щоб VM ядра не доводилося панічно реклеймити в найгірший можливий спосіб.
Пастка «подвійного кешування» (і коли це нормально)
Якщо ви запускаєте ZFS на Linux і працюєте з файлами звичайним способом, ви можете опинитися з кешуванням на кількох рівнях: ARC кешує блоки і метадані ZFS; кеш сторінок Linux також може кешувати сторінки файлів залежно від інтеграції ZFS з VFS.
Деталі залежать від реалізації і конфігурації, але операційна істина послідовна: ви можете витрачати RAM двічі, щоб запам’ятати той самий вміст.
Подвійне кешування не завжди зло. Воно може бути безпечним, якщо RAM достатньо і робочий набір стабільний. Воно може бути корисним, якщо кожен кеш тримає різні «форми» даних (метадані проти сторінок файлів), що допомагають у різних випадках.
Проблемою це стає, коли тиск пам’яті змушує витіснення і реклейм входити в петлю зворотного зв’язку: ARC чіпляється; VM реклеймить кеш сторінок; додатки фолять; відбуваються повторні читання; ARC зростає; повтор.
Жарт #2: подвійне кешування — як роздрукувати той самий звіт двічі «про всяк випадок». Звучить обачливо, поки не закінчиться папір і фінансовий директор не потребуватиме бюджетної таблиці прямо зараз.
Три міні-історії з корпоративного світу
Міні-історія #1: Інцидент через неправильне припущення («Вільна пам’ять означає, що ми в безпеці»)
Команда, з якою я працював, запускала мульти-орендну аналітичну платформу на вузлах Linux з ZFS. Дашборди заспокоювали: використання пам’яті виглядало високим, але стабільним, swap був низьким, і сервіс місяцями працював нормально.
Потім стався квартальний зсув навантаження: клієнт почав ширше сканувати старі розділи, а новий пакетний процес робив агресивну перебірку файлів для звітності з комплаєнсу.
Латентність підскочила. Не трохи — хвостова латентність пішла з «ніхто не скаржиться» до «квитки в саппорт кожні п’ять хвилин». Першою відповіддю було класичне: «Але у нас є RAM. Дивіться, тут ще вільна пам’ять».
Друга відповідь теж була класичною: перезавантажити вузол. Це допомогло на годину, потім усе впало знову.
Неправильне припущення було в тому, що «вільна пам’ять» — провідний індикатор, і кеші чемно поступляться, коли додаткам потрібна пам’ять. Насправді система увійшла в шторм реклейму:
ARC тримав велику частину, кеш сторінок сильно реклеймився, і власний тиск пам’яті додатків спричиняв часті дрібні фолти і повторні читання. Тим часом ZFS робив реальну роботу: обхід метаданих, верифікацію контрольних сум і випадкові I/O, які робили диски підозрілими.
Виправлення не було героїчним. Вони обмежили ARC, щоб залишити запас, стежили за метриками тиску пам’яті замість «вільного», і змінили розклад пакетної задачі, щоб вона не накладалася на інтерактивний пік.
Справжній урок: у змішаному навантаженні «доступна пам’ять» і «поведінка реклейму під тиском» важливіші за абсолютний розмір RAM.
Міні-історія #2: Оптимізація, що відгукнулася бумерангом («Додамо L2ARC, буде швидше»)
Інша організація мала пул ZFS на непоганих SSD, але хотіла більше продуктивності читання для індексу пошуку. Хтось запропонував додати великий L2ARC, бо «більше кешу завжди краще».
Вони встановили великий NVMe як L2ARC і бачили, як коефіцієнти попадань зросли в перший день. Всі почувалися кмітливими.
Через тиждень вони почали бачити періодичні спайки латентності під час пікових годин запитів. CPU не був завантажений. NVMe не був на максимумі. Диски пулу не були завантажені.
Спайки були дивними: короткі, різкі і важко зіставні з однією метрикою.
Відгук стався з двох причин. По-перше, їх робочий набір мав сильний churn: пошукове навантаження мало сплески нових термінів і періодичні повні переранжування. L2ARC постійно наповнювався даними, які більше не використовувалися.
По-друге, система платила затратами пам’яті за відстеження і подачу L2ARC, що звузило маржу пам’яті. Під тиском ARC і VM ядра почали боротися. Симптомом було не «повільно завжди», а «різко і непередбачувано», що найгірше для корпоративних SLA.
Вони видалили L2ARC, збільшили RAM (нудно, але ефективно) і налаштували recordsize та стиснення для макету індексу. Продуктивність покращилась і, що важливіше, стала передбачуваною.
Урок: L2ARC може допомогти, але він не безкоштовний і не врятує навантаження з сильним churn. Якщо ваш кеш-пристрій постійно кешує те, що не буде використано знову, ви побудували дуже дороге нагрівач.
Міні-історія #3: Сумна, але правильна практика, що врятувала день («Виміряйте перед тим як налаштовувати»)
Сервіс у фінансовій області (подумайте: пакетні розрахунки, суворі аудиторські логи) працював на ZFS зі змішаними дрібними синхронними записами і періодичними завданнями на читання для звірки.
У них була культура управління змінами, яку інженери жартома називали «уповільнене кіно», але вона мала одну звичку, яку я полюбив: перед будь-якою зміною продуктивності вони збирали стандартний пакет доказів.
Коли після оновлення ядра вони зіткнулися з повільністю, вони не почали крутити ручки. Вони відкрили свій пакет: ARC stats, VM pressure, затримки блокових пристроїв, статус пулу ZFS і загальні метрики додатку — ті самі команди, ті самі вікна вибірки, що й раніше.
За годину вони мали рідкісну річ в опсах: чистий diff.
Diff показав, що розміри ARC не змінилися, але поведінка кешу сторінок зрушила: таймінги dirty writeback змінилися в новому ядрі, що взаємодіяло з їхнім паттерном синхронних записів і підвищило латентність запису.
Оскільки у них були базові докази, вони могли сказати «це поведінка writeback», а не «сховище повільне», і валідувати виправлення без містичних припущень.
Виправлення було консервативним: підкоригувати налаштування dirty writeback у безпечних межах і перевірити стан SLOG-пристрою (він почав повідомляти про періодичну латентність).
Сервіс залишився стабільним, аудитори заспокоїлися, і нікому не довелося оголошувати war room на три дні. Урок: нудні ритуали вимірювань кращі за захопливі припущення.
Практичні завдання: команди та інтерпретація (принаймні 12)
Мета цих завдань — не «збирати статистику». Це відповісти на конкретні питання: чи домінує ARC в пам’яті? Чи тріпає кеш сторінок? Чи маємо ми вузькі місця через затримки диска, CPU або реклейм?
Команди нижче припускають Linux з встановленим OpenZFS там, де це релевантно.
Завдання 1: Подивіться реальність пам’яті (не міф про «вільну»)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 125Gi 42Gi 2.1Gi 1.2Gi 80Gi 78Gi
Swap: 8Gi 256Mi 7.8Gi
Інтерпретація: «available» — ключова лінія для «скільки додатки можуть отримати без свапінгу», але це спрощення.
Система може показувати багато «available» і все одно потрапити у шторм реклейму, якщо попит на пам’ять стрімко зростає або великі частини не реклеймяться достатньо швидко.
Завдання 2: Підтвердьте розміри, ціль і обмеження ZFS ARC
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c_min|c_max|c)\s'
size 4 68719476736
c 4 75161927680
c_min 4 17179869184
c_max 4 85899345920
Інтерпретація: size — поточний розмір ARC. c — поточна ціль ARC. c_min/c_max — межі.
Якщо size підходить впритул до c_max під час піку і на вузлі з’являється тиск пам’яті, ймовірно, вам потрібен кап або більше RAM — або зміна навантаження.
Завдання 3: Слідкуйте за поведінкою ARC у часі (misses vs hits)
cr0x@server:~$ arcstat 1 5
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
12:00:01 12K 2.4K 19 1.1K 9 1.0K 8 280 2 64G 70G
12:00:02 10K 2.0K 20 900 9 850 8 250 2 64G 70G
12:00:03 11K 2.2K 20 1.0K 9 950 9 260 2 64G 70G
12:00:04 13K 2.5K 19 1.2K 9 1.1K 8 290 2 64G 70G
12:00:05 12K 2.3K 19 1.1K 9 1.0K 8 270 2 64G 70G
Інтерпретація: Відсоток промахів сам по собі не дає вердикту. Дивіться на зміни: чи підскочили промахи при старті задачі? Чи високі промахи даних (стрімінг) або метаданих (обхід дерева)?
Якщо arcsz стабільний, але промахи стрибнули, можливо, ваш робочий набір перевищив ARC або шаблон доступу має низьке повторне використання.
Завдання 4: Визначте тиск пам’яті і шторми реклейму (VM pressure)
cr0x@server:~$ cat /proc/pressure/memory
some avg10=0.12 avg60=0.20 avg300=0.18 total=9382321
full avg10=0.00 avg60=0.01 avg300=0.00 total=10231
Інтерпретація: PSI (Pressure Stall Information) показує, чи завмирають завдання через неможливість швидко виділити пам’ять.
Зростання some підказує про активність реклейму; зростання full означає, що система часто не може продовжити роботу — тут латентність вибухає.
Завдання 5: Швидко виявити симптоми kswapd/direct reclaim
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 0 262144 2200000 120000 78000000 0 0 120 900 3200 6400 12 6 78 4 0
3 1 262144 1900000 115000 77000000 0 0 220 2100 4100 9000 14 9 62 15 0
4 2 262144 1700000 112000 76000000 0 64 450 9800 5200 12000 18 12 44 26 0
2 1 262144 1600000 110000 75000000 0 0 300 6000 4700 10500 16 10 55 19 0
1 0 262144 2100000 118000 77000000 0 0 160 1400 3600 7200 13 7 76 4 0
Інтерпретація: Слідкуйте за si/so (swap in/out), wa (I/O wait) і колонкою «b» (blocked processes).
Шторм реклейму часто проявляється як зростання процесів у стані блокування, підвищення кількості переключень контексту і нестабільний I/O.
Завдання 6: Подивіться кеш сторінок, slab і реклеймовану пам’ять
cr0x@server:~$ egrep 'MemAvailable|Cached:|Buffers:|SReclaimable:|Slab:' /proc/meminfo
MemAvailable: 81654312 kB
Buffers: 118432 kB
Cached: 79233412 kB
Slab: 3241120 kB
SReclaimable: 2015540 kB
Інтерпретація: Великий Cached не обов’язково погано. Великий Slab теж може бути нормою.
Але якщо MemAvailable низький, а ARC — високий, ви можете тиснути VM. Якщо MemAvailable нормальний, але PSI високий, можлива фрагментація, writeback-стали або конфлікт cgroup.
Завдання 7: Перевірте стан пулу ZFS і приховані проблеми (scrub/resilver)
cr0x@server:~$ zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:11:34 with 0 errors on Tue Dec 24 03:14:11 2025
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
errors: No known data errors
Інтерпретація: Пул у стані resilver або scrub під час піку може перетворити «обговорення кешу» на «I/O scheduler firefight».
Завжди перевіряйте це на початку; інакше ви будете налаштовувати ARC під час того, як пул зайнятий виконанням морального еквіваленту ремонту двигуна під час руху.
Завдання 8: Виміряйте затримки диска на рівні блоків
cr0x@server:~$ iostat -x 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
13.22 0.00 7.11 18.90 0.00 60.77
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
sda 220.0 18432.0 2.0 0.90 9.20 83.78 70.0 9216.0 18.40 2.10 88.0
nvme0n1 1600.0 102400.0 120.0 6.98 0.40 64.00 800.0 51200.0 0.60 0.90 35.0
Інтерпретація: Високі r_await/w_await і високе %util вказують на насичення пристрою або чергування.
Якщо диски в порядку, але латентність висока на рівні додатку, дивіться на тиск пам’яті, CPU і внутрішнє контеншн ZFS.
Завдання 9: Перегляньте властивості dataset ZFS, що змінюють динаміку кешування
cr0x@server:~$ zfs get -o name,property,value -s local,default recordsize,primarycache,secondarycache,compression tank/data
NAME PROPERTY VALUE
tank/data compression lz4
tank/data primarycache all
tank/data recordsize 128K
tank/data secondarycache all
Інтерпретація: recordsize формує гранулярність I/O і кешування для файлів. Для баз даних часто потрібні менші recordsize (наприклад, 16K), щоб зменшити read amplification.
primarycache контролює, що потрапляє в ARC (all, metadata, none). Це великий важіль.
Завдання 10: Безпечно обмежити ARC (постійна опція модуля)
cr0x@server:~$ echo "options zfs zfs_arc_max=34359738368" | sudo tee /etc/modprobe.d/zfs-arc-max.conf
options zfs zfs_arc_max=34359738368
cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.0-xx-generic
Інтерпретація: Це обмежує ARC до 32 GiB (значення в байтах). Роблять це, коли ріст ARC загрожує пам’яті додатків або спричиняє шторм реклейму.
Після перезавантаження підтвердьте через arcstats. Не вгадуйте; перевіряйте.
Завдання 11: Змінити primarycache, щоб захистити RAM від потокових читань
cr0x@server:~$ sudo zfs set primarycache=metadata tank/backups
cr0x@server:~$ zfs get -o name,property,value primarycache tank/backups
NAME PROPERTY VALUE
tank/backups primarycache metadata
Інтерпретація: Для цілей резервного копіювання, що в основному записуються один раз/читаються рідко або потокові, кешувати тільки метадані запобігає забрудненню ARC великими, мало повторно використовуваними даними.
Це одне властивість врятувало більше змішаних навантажувальних вузлів, ніж багато «гайдів з продуктивності».
Завдання 12: Спостерігайте I/O і латентність всередині пулу ZFS
cr0x@server:~$ zpool iostat -v 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 4.20T 3.05T 1.20K 650 140M 62.0M
raidz2-0 4.20T 3.05T 1.20K 650 140M 62.0M
sda - - 310 160 36.0M 15.0M
sdb - - 290 170 34.0M 15.5M
sdc - - 300 160 35.0M 15.0M
sdd - - 300 160 35.0M 15.0M
Інтерпретація: Це дає видимість на рівні пулу. Якщо читання високі і відсоток промахів ARC також високий, ймовірно, ви залежите від диска.
Якщо читання високі, але диски ні — можливо, ви скакаєте між кеш- шарами або є інше гальмування.
Завдання 13: Помітити брудний writeback і throttling (Linux VM)
cr0x@server:~$ sysctl vm.dirty_background_ratio vm.dirty_ratio vm.dirty_writeback_centisecs vm.dirty_expire_centisecs
vm.dirty_background_ratio = 10
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
Інтерпретація: Ці параметри впливають, коли ядро починає фонний writeback і коли воно примушує процеси записувати.
На системах ZFS ви балансуєте з власною поведінкою TXG, тому зміни тут слід тестувати обережно. Якщо ви бачите періодичні спайки латентності запису, це підозрювані налаштування.
Завдання 14: Перевірити, чи навантаження потокове або має повторне використання (тест корисності кешу)
cr0x@server:~$ sudo perf stat -e minor-faults,major-faults,cache-misses -a -- sleep 10
Performance counter stats for 'system wide':
482,120 minor-faults
2,104 major-faults
21,884,110 cache-misses
10.002312911 seconds time elapsed
Інтерпретація: Major faults вказують на промахи кешу сторінок, що вимагали I/O на диск. Сплеск під час задачі означає, що кеш сторінок не допомагає (або його реклеймлять).
Це не відокремлює ARC від кешу сторінок самостійно, але підказує, чи система повторно підвантажує дані в пам’ять.
Швидкий план діагностики
Коли продуктивність падає і у всіх є теорія, потрібна коротка послідовність, що сходиться швидко. Це порядок, який я використовую в реальних інцидентах, бо він дозволяє відрізнити «диск повільний» від «пам’ять бореться» за кілька хвилин.
Крок 1: Ми нездорові чи відновлюємося?
Спочатку перевірте стан пулу і фонову роботу. Якщо ви робите scrub/resilver, ви не діагностуєте чисту систему.
cr0x@server:~$ zpool status
cr0x@server:~$ zpool iostat -v 1 5
Рішення: Якщо виконуються resilver/scrub і скарги про латентність, розгляньте перенесення завдання або його обмеження перед тим, як торкатися ручок ARC/кеш сторінок.
Крок 2: Це затримка диска чи тиск пам’яті?
cr0x@server:~$ iostat -x 1 5
cr0x@server:~$ cat /proc/pressure/memory
cr0x@server:~$ vmstat 1 5
Рішення:
Якщо disk await і util високі — ви I/O-bound. Якщо PSI пам’яті високий, а диск ні — ви bound по пам’яті/реклейму.
Якщо обидва високі — можлива петля зворотного зв’язку: реклейм викликає I/O, що викликає блокування, що викликає більше реклейму.
Крок 3: ARC занадто великий або неправильно застосований?
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c|c_min|c_max|memory_throttle_count)\s'
cr0x@server:~$ arcstat 1 10
Рішення: Якщо ARC близький до максимуму і є тиск пам’яті, обмежте ARC або обмежте кешування на потокових dataset-ах (primarycache=metadata), щоб зупинити забруднення кешу.
Крок 4: Чи кешоване навантаження взагалі?
cr0x@server:~$ arcstat 1 10
cr0x@server:~$ zpool iostat -v 1 10
Рішення: Якщо відсоток промахів ARC залишається високим, поки пропускна здатність висока і повторного використання мало, перестаньте намагатися «виграти» кешами. Зосередьтесь на пропускній здатності дисків, recordsize і плануванні.
Крок 5: Перевірте властивості dataset і невідповідність додатку
cr0x@server:~$ zfs get -s local,default recordsize,atime,compression,primarycache tank/data
cr0x@server:~$ ps -eo pid,cmd,%mem --sort=-%mem | head
Рішення: Якщо база даних розташована на dataset з великим recordsize і caching «all», ви можете підсилювати випадкові читання і забруднювати ARC.
Виправлення цього часто ефективніше за дрібне керування параметрами ARC.
Поширені помилки, симптоми, виправлення
Помилка 1: Розглядати коефіцієнт попадань ARC як єдину істину
Симптоми: Команда святкує 95% hit rate, а користувачі все одно бачать стрибки латентності; або ви панікуєте через 20% hit rate під час бекапу.
Виправлення: Класифікуйте навантаження: стрімінг проти повторного використання. Поєднайте arcstat з латентністю дисків (iostat) і тиском пам’яті (PSI). Низький hit rate на потокових читаннях — нормальний; висока латентність — ні.
Помилка 2: Дозволяти потоковим навантаженням забруднювати ARC
Симптоми: Під час бекапів або сканів ARC росте, інтерактивні навантаження сповільнюються, кеш «після цього марний».
Виправлення: Переведіть потокові/бекапні dataset-и на primarycache=metadata (або навіть none для крайніх випадків). Розгляньте окремі пули, якщо контеншн хронічний.
Помилка 3: Сліпо обмежувати ARC і називати це «налаштовано»
Симптоми: Після зменшення ARC метадані-важкі навантаження значно сповільнюються; диски стають більш активними; CPU зростає.
Виправлення: Обмежуйте ARC зі смислом: залиште запас для додатків і кешу сторінок, але не настільки мало, щоб ZFS втратив метаданий робочий набір. Валідуйте через arcstat і наскрізну латентність.
Помилка 4: Вважати L2ARC безкоштовним обідом
Симптоми: Додавання L2ARC покращує синтетичні бенчмарки, але в продукції з’являються спайки; тиск пам’яті зростає; диск кешу постійно активний.
Виправлення: Переконайтеся, що навантаження має повторне використання. Вимірюйте до/після з хвостовими латентностями і читаннями диска. Якщо домінує churn, видаліть L2ARC і витратьте бюджет на RAM або краще первинне сховище.
Помилка 5: Плутати SLOG/ZIL з кешуванням читань
Симптоми: Купуєте швидкий SLOG у надії, що читання прискоряться; нічого не змінюється; ви оголошуєте ZFS «повільною».
Виправлення: Використовуйте SLOG для поліпшення латентності синхронних записів, де це доречно. Для читань зосередьтесь на ARC/L2ARC, recordsize і затримках пристроїв.
Помилка 6: Ігнорувати сигнали тиску пам’яті ядра
Симптоми: Періодичні паузи, активність kswapd, випадкові OOM, але «available memory» виглядає ок.
Виправлення: Використовуйте PSI (/proc/pressure/memory), vmstat і логи для OOM/reclaim. Обмежте ARC, виправте runaway-процеси і перегляньте обмеження cgroup, якщо залучені контейнери.
Чеклісти / покроковий план
Чекліст A: Новий хост ZFS-on-Linux (змішані навантаження)
- Визначте бюджет пам’яті. Скільки RAM треба зарезервувати для додатків і скільки можна віддати файловому кешу? Якщо ви не можете відповісти — ви делегуєте архітектуру дефолтним евристикам.
-
Встановіть початковий кап ARC (консервативний, регулюйте пізніше). Підтвердіть після перезавантаження через
/proc/spl/kstat/zfs/arcstats. -
Класифікуйте dataset-и за патерном доступу: інтерактивні, база даних, бекап/стрімінг, образи VM. Встановіть
primarycacheвідповідно. - Встановіть recordsize для dataset відповідно до навантаження (великий для послідовних файлів, менший для випадкових DB-патернів).
-
Заведіть базовий пакет доказів:
free,meminfo, PSI,arcstat,iostat -x,zpool iostatі хвостові латентності додатку.
Чекліст B: Коли хтось каже «ZFS їсть всю мою RAM»
- Перевірте PSI пам’яті і активність swap. Якщо тиску немає, ARC не ваш злочинець — це невикористана RAM, що робить корисну роботу.
- Підтвердіть розмір ARC vs max і чи зменшується ARC при зміні навантаження.
- Виявте забруднююче навантаження (часто бекапи, скани або аналітика). Застосуйте
primarycache=metadataдо цього dataset-а. - Якщо тиск триває, обмежте ARC. Потім перевірте, чи ключові навантаження не погіршилися через метадані-промахи.
Чекліст C: Регрес продуктивності після зміни
- Перевірте здоров’я пулу, статус scrub/resilver і помилки пристроїв.
- Порівняйте затримки диска (
iostat -x) до/після. Якщо латентність зросла, ще не сперечайтеся про кеші. - Порівняйте тиск пам’яті (PSI) до/після. Зміни в ядрі можуть зрушити поведінку реклейму/writeback.
- Порівняйте поведінку ARC (size, target, misses). Якщо ARC стабільний, але додаток повільніший, дивіться вище (CPU, блокування, конфігурація додатку) або нижче (пристрої).
Питання та відповіді
1) Чи ARC — це просто «ZFS page cache»?
Ні. ARC кешує ZFS буфери (дані і метадані) всередині стеку ZFS. Кеш сторінок Linux кешує сторінки файлів на рівні VFS.
Вони можуть частково перекриватися, але це не один і той же шар чи політика.
2) Чому Linux показує «майже немає вільної пам’яті» на здоровому ZFS вузлі?
Тому що RAM призначена для використання. ARC і кеш сторінок будуть споживати пам’ять, щоб зменшити майбутні I/O.
Метрика, яка має значення — чи система може задовольнити виділення без затримок або свапінгу — використовуйте «available», PSI і спостережувану латентність.
3) Чи варто завжди обмежувати ARC на Linux?
На виділених storage-апаратах часто дозволяють ARC бути великим. На серверах зі змішаним використанням (бази даних, контейнери, JVM, build-агенти) кап зазвичай виправданий.
Правильний кап специфічний для навантаження: залиште достатньо для додатків і VM, але також достатньо ARC, щоб кешувати метадані і гарячі блоки.
4) Чи додавання RAM завжди краща за додавання L2ARC?
Часто — так. RAM зменшує латентність і складність і допомагає і ARC, і решті системи.
L2ARC може допомогти, коли робочий набір більший за RAM і має повторне використання, але він додає накладні витрати і не виправить workloads з сильним churn.
5) Якщо моя база даних використовує direct I/O, чи ARC все одно має значення?
Може. Навіть якщо читання даних користувача обходять деякі шляхи кешування, метадані ZFS все одно важливі, і ZFS управляє блоковим I/O, контрольними сумами і макетом.
Крім того, не всі доступи БД завжди чисто direct I/O; і фонова робота може зачіпати файлову систему у кешований спосіб.
6) Який найшвидший спосіб сказати, чи я I/O-bound чи memory-pressure-bound?
Дивіться iostat -x для await/util пристроїв і PSI (/proc/pressure/memory) плюс vmstat для реклейму/swap.
Високий await/util диска вказує на I/O-bound; високий PSI пам’яті — на тиск пам’яті. Якщо обидва високі, підозрюйте петлю зворотного зв’язку.
7) Коли варто встановити primarycache=metadata?
Коли dataset в основному обслуговує потокові читання/записи (бекапи, медіа-архіви, холодні логи) і кешувати дані файлів в ARC означало б витіснення гарячих навантажень.
Це особливо корисно на мульти-орендних системах, де одна задача «прочитати все один раз» може викинути гарячі блоки всіх інших.
8) Чому мої бенчмарки виглядають чудово після першого прогону?
Бо кеші прогрілися. Це може бути кеш сторінок Linux, ARC або обидва. Другий прогін часто вимірює швидкість пам’яті, а не сховища.
Якщо ви намагаєтесь виміряти сховище, спроектуйте бенчмарк так, щоб контролювати ефекти кешування, а не робити вигляд, що їх немає.
9) Чи можна безпечно «скинути кеші» для тесту?
Ви можете скидати кеш сторінок Linux, але робити це в продакшні руйнівно і зазвичай погана ідея.
Також скид кешу Linux не обов’язково скидає ARC так само; ви можете все ще вимірювати прогріту поведінку ZFS. Краще використовувати контрольовані тестові хости або синтетичні навантаження з чіткою методологією.
10) Яка найкраща одинична метрика для довгострокового моніторингу?
Для користувацького досвіду: хвостові латентності додатку. Для здоров’я системи: PSI пам’яті і затримки диска.
Статистика ARC корисна як допоміжні докази, але не як головна.
Висновок
ZFS ARC і кеш сторінок Linux не конкуренти в спрощеному сенсі; це системи кешування, побудовані на різних шарах, з різними припущеннями і різними режимами відмов.
ARC чудово кешує світ ZFS — блоки, метадані і механіку, що робить snapshots і контрольні суми швидкими. Кеш сторінок — це стандартний підсилювач продуктивності ядра Linux, задуманий бути реклеймабельним і широко корисним.
Те, що вам варто цікавити, — не ідеологічна чистота («ZFS має все робити» проти «Linux має все робити»), а операційна стабільність під час змін.
Якщо ви запускаєте змішані навантаження, залишайте запас, запобігайте забрудненню кешу, вимірюйте тиск замість «вільної пам’яті» і налаштовуйте з доказами, а не з фольклору.
Ось як ви виграєте війну кешів: не роблячи її війною.