Високе використання RAM «ніби без причини»: що нормально, а що несправне

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

Ви заходите в систему, запускаєте free, і в груди щось стискається: пам’ять «використовується» майже повністю. Нічого очевидно не горить. Затримки виглядають нормальними. CPU байдикує. Але дашборд кричить: RAM 92%. Хтось пише: «Витік пам’яті?»

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

Ментальна модель: RAM — це не відро, а ринок

Якщо ви візьмете одну ідею з цього матеріалу — візьміть цю: «високе використання RAM» — це не діагноз. Це спостереження, і часто воно здорове.

Три види пам’яті, які плутають у сповіщеннях

  • Анонімна пам’ять: heap процесів, стеки, malloc-арени, Java heap, Node/V8 heap тощо. Якщо це зростає без меж — можливо витік або неврегульоване навантаження.
  • Файло-підтримувана пам’ять: відображені файли, спільні бібліотеки, memory-mapped бази даних і особливо page cache. Тут Linux зберігає дані файлів, бо читання з RAM швидше, ніж з диска.
  • Пам’ять ядра: slab-кеші, мережеві буфери, dentries/inodes та інші структури ядра. Вона може зростати з причин на користь справи (трафік) або з причин поганих (баги, неправильні налаштування).

Чому «вільна пам’ять» — оманливий показник

Linux прагне, щоб вільної пам’яті було близько нуля. Не тому, що він недбалий, а тому, що проста пам’ять нічого не робить. Ядро опортуністично використовує RAM для кешування і повертає її, коли додаткам потрібні сторінки.

Тож коли хтось каже: «RAM повна», наступне питання має бути: чим саме вона заповнена? Кеш можна звільнити. Протікання heap’у — ні (доки процес не помре).

Два правила, які вбережуть вас від проблем

  1. Якщо затримки стабільні і немає трешу від reclaim — не панікуйте. Система з важким кешем може виглядати «заповненою» і бути цілком здоровою.
  2. Якщо swap росте і різко збільшуються major faults — ви платите відсотки за «дебіти пам’яті». Саме так народжуються продакшен-відмови.

Суха правда: показник «RAM %» на дашборді зазвичай погана абстракція. Вам потрібні сигнали тиску, а не лише заповненість.

Цікаві факти та історія (коротко, конкретно, корисно)

  1. Поводження Linux з «buff/cache» бентежить адміністраторів десятиліттями; сучасний вивід free додав available, щоб зменшити хибні тривоги.
  2. Windows популяризувала термін «standby memory» для відновлюваного кешу; Linux робить те саме, просто з іншими мітками та інструментами.
  3. OOM killer існує тому, що ідеального overcommit пам’яті не існує: коли ядро не може задовольнити виділення, воно вбиває процес замість того, щоб заблокувати систему.
  4. Контейнери не винайшли обмеження пам’яті; це зробили cgroups. Контейнери лише спростили застосування cgroups до всього (включно з вашою БД, яка потім голосно скаржиться).
  5. Ранні Unix-системи були заощадливими з page cache, бо RAM була дорогою; сучасні ядра агресивніші, бо CPU-цикли та I/O wait дорожчі за RAM.
  6. ARC у ZFS — фактично «page cache, але для ZFS» і може зайняти значну частину RAM, якщо дозволити; це не витік, це стратегія.
  7. Transparent Huge Pages (THP) можуть покращити продуктивність — або створити спайки затримки і роздування пам’яті, залежно від навантаження та фрагментації.
  8. Звітування пам’яті в Java заплутане: heap — лише частина; RSS включає нативні алокації, JIT, стеки потоків і відображені файли.
  9. Linux може швидко звільняти чистий page cache, але для брудних сторінок потрібен writeback; якщо writeback повільний, «відновлюване» стає «не прямо зараз».

Як виглядає «нормальне» високе використання пам’яті проти «поламане»

Нормально: RAM використовується як кеш (швидко, тихо і відновлювано)

Нормальна ситуація виглядає так:

  • free показує високе «used», але також високе available.
  • Малий використання swap (або стабільний swap, що не зростає).
  • vmstat показує низькі si/so (swap-in/out) і низьке wa (I/O wait).
  • Затримка читання з диска низька, бо кеш-хіти високі.
  • RSS процесів стабільні; нічого не роздувається.

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

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

Поламана ситуація виглядає так:

  • available низьке і падає.
  • Зростає активність swap (si/so ненульові протягом тривалих періодів).
  • Раптово зростають major page faults; затримки поводяться дивно.
  • В журналах з’являються повідомлення OOM killer.
  • Ядро kswapd з’являється у профілях CPU, бо машина зайнята пошуком пам’яті для дихання.

Тоді питання змінюється з «чому RAM висока?» на «хто її споживає і чи можемо безпечно її повернути?»

Три найпоширеніші причини «поламаного» стану

  1. Справжній витік додатку або необмежений ріст пам’яті: накопичення черг у RAM, кешування без евікції, ріст буферів на з’єднаннях тощо.
  2. Неправильно розмірені кеші: буфери бази даних, JVM heap, Redis maxmemory, ZFS ARC, CDN кеш, LRU в додатках, який фактично не LRU.
  3. Зростання пам’яті ядра: slab-кеші, мережеві буфери, таблиці conntrack, метадані файлової системи при інтенсивній зміні.

Жарт №1: Витоки пам’яті схожі на блискітки: спочатку їх не видно, а потім вони раптом всюди у вашому житті.

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

Перший: Визначте, чи це тиск, чи просто заповненість

  1. Перевірте free на available.
  2. Перевірте тренд swap та vmstat на наявність тривалої swap-активності.
  3. Перевірте журнали на OOM-події.

Рішення: Якщо available у нормі і swap не росте, вважайте це нормальним кешуванням, якщо немає симптомів для користувачів.

Другий: Визначте клас пам’яті

  1. Чи це RSS процесів (кілька PID-ів росте)?
  2. Чи це page cache (високий кеш, anon стабільний)?
  3. Чи це slab ядра (високий slab, об’єкти ростуть)?
  4. У контейнерах: чи це проблема обмеження cgroup (RSS нормальний, але cgroup показує наближення до ліміту)?

Рішення: Оберіть правильний інструмент: інспекція по процесах, статистика cgroup або розбір slab — а не «перезапустити все» як метод діагностики.

Третій: Доведіть, хто споживає найбільше, і виберіть найменш ризикове пом’якшення

  1. Отримайте топ-споживачів пам’яті і підтвердіть ріст у часі (не лише знімок).
  2. Перевірте, чи споживач можна налаштувати (обмеження кешу) або він багований (витік).
  3. Пом’якшення: обмежити кеш, виправити запит/навантаження, додати пам’ять або контроловано перезапустити як тимчасовий захід із подальшими діями.

Рішення: Якщо система перебуває під активним тиском, пріоритет — стабільність: запобігти OOM, зупинити треш, потім спокійно шукати корінь проблеми.

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

Це реальні задачі, які ви можете виконати на продакшен-хостах Linux. Кожна містить, що означає вивід і яке рішення він підказує. Використовуйте їх у порядку, а не навмання.

Задача 1: Читайте пам’ять по-дорослому (free -h)

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:            31Gi        26Gi       600Mi       1.2Gi       4.5Gi       3.8Gi
Swap:          4.0Gi       512Mi       3.5Gi

Що це означає: «used» включає кеш і інші відновлювані області. Перш за все дивіться на available (приблизно: скільки можна виділити без swap-у).

Рішення: Якщо available кілька ГіБ і стабільне, швидше за все це нормальне кешування. Якщо воно низьке (<5–10% від загального) і падає — переходьте до перевірок тиску.

Задача 2: Підтвердіть тиск і churn swap (vmstat 1)

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 524288 612000  82000 3920000   0    0     5    22  430  900 12  4 83  1  0
 1  0 524288 598000  82000 3950000   0    0     1    10  420  880 11  4 84  1  0
 3  1 525312 120000  81000 2800000 150  320   800   900 1200 2500 25 12 35 28  0
 2  1 540000  90000  80000 2700000 220  400  1100  1400 1500 3000 22 15 30 33  0
 2  1 560000  70000  79000 2600000 180  380   900  1200 1400 2900 20 14 32 34  0

Що це означає: Тривало ненульові si/so означають свопінг. Зростання wa натякає, що вузол чекає на I/O, часто погіршене свопінгом або writeback.

Рішення: Якщо churn swap триває — це інцидент: зменшіть використання пам’яті або додайте пам’ять/змініть ліміти перед тим, як упаде латентність або станеться OOM.

Задача 3: Перевірте наявність свідчень OOM killer (journalctl)

cr0x@server:~$ journalctl -k -S -2h | egrep -i 'oom|out of memory|killed process' | tail -n 20
Feb 05 09:41:12 server kernel: Out of memory: Killed process 21784 (java) total-vm:9876544kB, anon-rss:2456789kB, file-rss:12345kB, shmem-rss:0kB

Що це означає: Ядро не змогло знайти пам’ять в межах своїх обмежень і вбило процес. Той «хтось» часто не є коренем проблеми — просто нещасливий переможець з неправильним баллом.

Рішення: Якщо бачите OOM kills — припиніть дебати і почніть негайно зменшувати тиск пам’яті. Потім шукайте корінь проблеми.

Задача 4: Подивіться розподіл пам’яті по системі (cat /proc/meminfo)

cr0x@server:~$ egrep 'MemTotal|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|Active|Inactive|AnonPages|Slab|SReclaimable|Dirty|Writeback' /proc/meminfo
MemTotal:       32803520 kB
MemAvailable:    4012340 kB
Buffers:          112340 kB
Cached:          3890120 kB
SwapTotal:       4194300 kB
SwapFree:        3670016 kB
Active:         20123456 kB
Inactive:        8765432 kB
AnonPages:      22123456 kB
Slab:            1456780 kB
SReclaimable:     612340 kB
Dirty:            245600 kB
Writeback:          4200 kB

Що це означає: AnonPages — груба оцінка приватної пам’яті процесів. Cached — page cache. Slab/SReclaimable показують кеші ядра. Dirty/Writeback підказують, чи блокує reclaim запис на диск.

Рішення: Високі AnonPages вказують на процеси/cgroup. Високий Slab — на ріст об’єктів ядра. Високий Dirty — на проблеми з writeback і I/O.

Задача 5: Визначте топ-процеси за RSS (ps)

cr0x@server:~$ ps -eo pid,user,comm,rss,vsz --sort=-rss | head -n 15
  PID USER     COMMAND        RSS    VSZ
21784 app      java        3854120 9876544
10422 app      node        1123400 2456780
 2314 postgres postgres     823000 1024000
 1981 root     dockerd      412000 1650000
 1450 root     systemd-journ 180000  450000

Що це означає: RSS — resident set size: пам’ять фактично в RAM (включно з деякими mapped файлами). VSZ — віртуальний розмір, часто великий і часто неістотний.

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

Задача 6: Проаналізуйте відображення підозрілого процесу (pmap -x)

cr0x@server:~$ sudo pmap -x 21784 | tail -n 5
00007f2c78000000  262144  260000  260000 rw---   [ anon ]
00007f2c88000000  262144  262144  262144 rw---   [ anon ]
00007f2c98000000  262144  262144  262144 rw---   [ anon ]
00007ffd2c1b1000     132      44      44 rw---   [ stack ]
 total kB         9876544 3854120 3720000

Що це означає: Великі анонімні регіони вказують на heap/нативні алокації. Великі файло-підтримувані відображення можуть бути mmap’нутими файлами або спільними бібліотеками.

Рішення: Якщо анонімний RSS роздувається — потрібне розслідування на рівні додатку (дамп heap, профілювання, евікція кешу). Якщо переважає файло-підтримуване — розгляньте поведінку page cache/mmap та шаблон I/O.

Задача 7: Визначте, чи ядро витрачає час на reclaim (sar -B)

cr0x@server:~$ sar -B 1 3
Linux 6.5.0 (server)  02/05/2026  _x86_64_ (16 CPU)

12:01:01 AM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
12:01:02 AM      5.00     22.00   1200.00      0.00   8000.00      0.00      0.00      0.00      0.00
12:01:03 AM    900.00   1400.00   9000.00     85.00  12000.00   4500.00      0.00   3200.00     71.11
12:01:04 AM    850.00   1350.00   8700.00     90.00  11800.00   4700.00      0.00   3100.00     65.96

Що це означає: Major faults (majflt/s) і сканування/вкрадання сторінок вказують на активність reclaim. %vmeff дає приблизну уяву про ефективність reclaim; низька ефективність часто корелює з трешем.

Рішення: Високі major faults + активне сканування = ви під тиском. Виправляйте використання пам’яті або ліміти; не просто «додавайте swap і сподівайтеся».

Задача 8: Розгляньте споживачів slab ядра (slabtop)

cr0x@server:~$ sudo slabtop -o -s c | head -n 15
 Active / Total Objects (% used)    : 812345 / 845000 (96.1%)
 Active / Total Slabs (% used)      : 22000 / 22000 (100.0%)
 Active / Total Caches (% used)     : 95 / 120 (79.2%)
 Active / Total Size (% used)       : 1456780.00K / 1520000.00K (95.8%)
 Minimum / Average / Maximum Object : 0.01K / 0.18K / 8.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
220000 219500  99%    0.19K  11000       20    440000K dentry
180000 179000  99%    0.94K   9000       20    360000K inode_cache
 95000  94900  99%    0.05K   1250       76     47500K kmalloc-64

Що це означає: Великі dentry/inode_cache часто означають інтенсивну роботу з метаданими файлової системи (багато файлів). Це може бути нормальним на build-серверах, log-shipper’ах або системах, що сканують директорії.

Рішення: Якщо slab великий і росте — дослідіть навантаження (file storms), баги ядра або налаштування на кшталт vm.vfs_cache_pressure (з обережністю). Не використовуйте «drop caches» в продакшені як рутину.

Задача 9: Перевірте ліміти пам’яті cgroup (контейнери/systemd)

cr0x@server:~$ cat /sys/fs/cgroup/memory.max
8589934592
cr0x@server:~$ cat /sys/fs/cgroup/memory.current
8422686720

Що це означає: Ви можете мати багато RAM на хості, але все одно отримати OOM всередині cgroup через жорсткий ліміт. memory.current біля memory.max — це тиск, незалежно від вільної пам’яті хоста.

Рішення: Якщо cgroup наближається до ліміту — підвищіть ліміт або зменшіть навантаження/кеші всередині контейнера. Вільна пам’ять хоста вам не допоможе.

Задача 10: Визначте OOM події cgroup (dmesg / журнал ядра)

cr0x@server:~$ dmesg | egrep -i 'memory cgroup out of memory|oom-kill|Killed process' | tail -n 10
[123456.789012] Memory cgroup out of memory: Killed process 10422 (node) total-vm:2456780kB, anon-rss:980000kB, file-rss:12000kB, shmem-rss:0kB

Що це означає: Це OOM в контейнері/cgroup, а не обов’язково OOM хоста. Ремедіація — це робота з лімітами, а не «очистити кеш».

Рішення: Налаштуйте ліміти cgroup і встановіть реалістичні requests/limits. Інакше ви граєте в лотерею, де приз — простій.

Задача 11: Зрозуміти «зниклу пам’ять» через smaps rollup

cr0x@server:~$ sudo cat /proc/21784/smaps_rollup | egrep 'Rss|Pss|Private|Shared|Swap'
Rss:                3854120 kB
Pss:                3801200 kB
Shared_Clean:         12000 kB
Shared_Dirty:          4000 kB
Private_Clean:        35000 kB
Private_Dirty:      3803120 kB
Swap:                120000 kB

Що це означає: Private_Dirty — сильний сигнал анонімної приватної пам’яті — часто heap. Swap тут означає, що процес активно платить «податок» свопу.

Рішення: Якщо private dirty зростає з навантаженням і не повертається — плануйте виправлення на рівні додатку. Якщо swap росте — перегляньте ліміти пам’яті і досліджуйте «гарячі точки».

Задача 12: Перевірте відкриті дескриптори файлів і mmap-тиск (lsof)

cr0x@server:~$ sudo lsof -p 21784 | wc -l
18234

Що це означає: Багато FD може корелювати з буферами на з’єднання, великими наборами mmap і інколи витоками (витік FD не є витоком RAM, але часто йде поруч).

Рішення: Якщо кількість FD безконтрольно росте — розглядайте це як клас витоків. Виправляйте додаток; підвищення ulimits — лише тимчасове рішення.

Задача 13: Слідкуйте за трендом пам’яті з часом (loop ps)

cr0x@server:~$ for i in {1..5}; do date; ps -p 21784 -o pid,rss,etime,cmd; sleep 60; done
Mon Feb  5 10:00:00 UTC 2026
  PID   RSS     ELAPSED CMD
21784 3720000  01:22:10 java -jar service.jar
Mon Feb  5 10:01:00 UTC 2026
  PID   RSS     ELAPSED CMD
21784 3755000  01:23:10 java -jar service.jar
Mon Feb  5 10:02:00 UTC 2026
  PID   RSS     ELAPSED CMD
21784 3812000  01:24:10 java -jar service.jar
Mon Feb  5 10:03:00 UTC 2026
  PID   RSS     ELAPSED CMD
21784 3899000  01:25:10 java -jar service.jar
Mon Feb  5 10:04:00 UTC 2026
  PID   RSS     ELAPSED CMD
21784 3980000  01:26:10 java -jar service.jar

Що це означає: Тренд росту важливіший за одиночний знімок. Якщо RSS постійно зростає — це не кеш, а накопичення.

Рішення: Ескалюйте до профілювання і виправлення коду; впровадьте запобіжники (ліміти, backpressure), поки виправляєте.

Задача 14: Перевірте затори writeback (grep лічильників vmstat)

cr0x@server:~$ egrep 'nr_dirty|nr_writeback|pgscan|pgsteal|oom_kill' /proc/vmstat | head
nr_dirty 61234
nr_writeback 2100
pgscan_kswapd 987654
pgsteal_kswapd 765432
oom_kill 3

Що це означає: Високе сканування/вкрадання вказує на роботу reclaim. Dirty/writeback підказують, чи заблокований reclaim повільним флешиванням.

Рішення: Якщо writeback підвищений і I/O повільний — виправляйте продуктивність сховища або обмеження dirty; інакше тиск пам’яті буде відчуватися гірше, ніж має.

Три корпоративні міні-історії з пам’ятних окопів

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

Компанія середнього розміру керувала флотом Linux VM за load balancer’ом. Їх інструмент моніторингу мав один головний метрик: «RAM used %». Він сигналив при 85%. Він сигналив часто. Людей навчилося ігнорувати це — чудовий трюк, поки не стає погано.

Одного дня тривога за RAM спрацювала на критичному API-ноді. Оперативний подивився: used 90%, CPU нормальний. Пожвавили плечима — «це лише кеш» — і повернулися до своїх справ.

За 30 хвилин затримки піднялися, а потім впали вниз. Нод почав таймаутитися на health checks і був витягнутий з балансувальника. Другий нод послідував. Потім третій. Вийшов outage.

Корінь проблеми не був в page cache. Нова деплойка додала необмежену in-memory чергу, коли downstream повільнів. Графік «used %» виглядав як зазвичай, але MemAvailable руйнувався і своп-активність росла. Вони мали проблему тиску, але трактували її як косметичну.

Виправлення було двохрівневим: впровадити backpressure і додати у основні алерти MemAvailable, активність swap і OOM події. Неправильне припущення було не в тому, що «Linux використовує кеш», а в тому, що «високе used означає одне й те саме щоразу».

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

Команда інженерів хотіла зменшити I/O на сервісі обробки логів. Вони значно збільшили внутрішній кеш. У staging це працювало і графіки виглядали відмінно: менше читань, плавніший throughput.

У продакшені та сама зміна спричинила повільну деградацію. Піковий трафік швидко розігрів кеш і RSS піднявся. Саме по собі це було б добре — машини мали запас RAM. Але сервіс працював у контейнерах з консервативними лімітами пам’яті, встановленими місяцями раніше, коли трафік був меншим і «ефективність» була KPI.

Cgroup почав агресивно проводити евікцію. Затримки зросли. Сервіс більше робив retry’ів, що збільшило пам’ять, що посилило евікцію. Потім cgroup OOM killer почав вбивати контейнери. Автоматичний рестарт зробив іще гірше, створивши гурти одночасних «розігрівів кешу».

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

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

Фінансова компанія тримала кластер бази даних і кілька сервісів на тих самих хостах. Не ідеально, але бюджети — це реальний фізичний закон. Один SRE наполягав на щотижневому рутині: фіксувати базовий розподіл пам’яті і мати runbook з «відомими нормами»: page cache, slab, буфери БД і типовий RSS для кожного сервісу.

Це було нудно. Це не давало допаміну. Але коли пам’ять почала поступово рости на кількох нодах, вони не сперечалися, чи це нормально — вони порівняли з базою.

Slab був у межах норми, page cache типовий, але AnonPages був вищим за базу на кілька ГіБ і зростав. Top RSS вказав на сайдкар-процес, який «не мав багато робити». Ця фраза — надійний передвісник майбутніх проблем.

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

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

1) Симптом: «RAM 95% використана, це мусить бути витік»

Корінь проблеми: Трактування «used» як «недоступна». Page cache роздуває «used» і є відновлюваним.

Виправлення: Алертуйте на MemAvailable, активність swap, major faults і OOM події. Навчіть команду правильно читати free.

2) Симптом: «Очищення кешу вирішило проблему» (тимчасово)

Корінь проблеми: Ви скинули page cache і slab, що зменшило used, але також зруйнувало продуктивність і замаскувало справжній ріст.

Виправлення: Не використовуйте drop_caches як рутину. Якщо робите це для діагностики — документуйте та вимірюйте вплив на продуктивність одразу після.

3) Симптом: OOM kills, але хост має «вільну пам’ять»

Корінь проблеми: Досягнуто ліміт cgroup/контейнера. Вільна пам’ять хоста не має значення для цього ліміту.

Виправлення: Перевірте memory.max/memory.current, підвищте ліміти і встановіть адекватні requests/limits. Робіть alerти для cgroup OOM окремо від host OOM.

4) Симптом: Зростання затримок при достатній RAM

Корінь проблеми: Reclaim thrash або THP/compaction-стали. Пам’ять «available» може бути в порядку в середньому, але не в потрібному стані.

Виправлення: Перевірте major faults, статистику reclaim і налаштування THP. Розгляньте відключення THP для затратночутливих до затримки навантажень, де THP шкодить.

5) Симптом: Використовується swap, і починається паніка

Корінь проблеми: Саме по собі використання swap не є зло; зло — постійний swap-in/out. Linux може переміщувати холодні сторінки на своп свідомо.

Виправлення: Подивіться vmstat si/so і major faults. Якщо стабільно — це нормально. Якщо churn — вважайте це тиском.

6) Симптом: Пам’ять росте після кожного деплою, потім «стабілізується»

Корінь проблеми: Поведінка warmup (JIT, кеші, connection pools) виглядає як витік, якщо дивитися лише першу годину.

Виправлення: Порівнюйте steady-state після warmup. Налаштуйте алерти на швидкість росту, а не лише на рівень; а також позначайте деплої на графіках.

7) Симптом: «Used memory» росте при інтенсивній роботі з файловою системою

Корінь проблеми: Ріст slab (dentry/inode) при інтенсивній зміні метаданих.

Виправлення: Підтвердіть через slabtop. Зменшіть churn (менше файлів, більші пакети), акуратно налаштуйте і переконайтеся, що ядра оновлені.

8) Симптом: Нод бази даних «з’їдає всю RAM»

Корінь проблеми: Буфер кеш бази + OS cache дають подвійне кешування, або БД свідомо використовує RAM для продуктивності.

Виправлення: Плануйте розмір кешів БД навмисно і залишайте запас для OS та інших сервісів. Не колокуйте пам’яттєво вимогливі сервіси без явних бюджетів.

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

Контрольний список A: Коли вам дзвонять через «високу пам’ять»

  1. Запустіть free -h. Зверніть увагу на available, а не на «used».
  2. Запустіть vmstat 1 10. Шукайте тривалі si/so і високий wa.
  3. Пошукайте OOM-події: journalctl -k -S -2h | egrep -i 'oom|killed process'.
  4. Якщо в контейнерах — перевірте cgroup: memory.current проти memory.max.
  5. Якщо тиск реальний — знайдіть топ-споживачів (ps) і стежте за ростом 5–15 хвилин.
  6. Обирайте пом’якшення: обмежити кеші, зменшити concurrency, скинути навантаження, підвищити ліміти або додати RAM.
  7. Лише після цього розгляньте рестарт — і робіть його як тимчасовий захід з відкритим тикетом на «чому виросло?».

Контрольний список B: Стабілізувати хост під тиском пам’яті (не роблячи жалюгідного)

  1. Зупиніть кровотечу: зменшіть трафік/concurrency або відкочуйте зміну, що підвищила пам’ять.
  2. Захистіть ядро: переконайтеся, що у вас є належно налаштований swap і він не на надто повільному носії; уникайте відключення swap як рефлексу.
  3. Пріоритизуйте критичні сервіси: налаштуйте пріоритети/ліміти cgroup, щоб БД не помирала заради пакетної задачі.
  4. Виміряйте reclaim: major faults, pgscan, pgsteal і churn swap покажуть, чи трешує система.
  5. Робіть по одній зміні: підвищення ліміту кешу і одночасне зменшення concurrency позбавляє вас можливості аналізу.

Контрольний список C: Побудуйте кращі алерти, щоб цього не повторювалося

  1. Алертуйте на низьке MemAvailable тривало (host) і на memory.current близько memory.max (cgroup).
  2. Алертуйте на тривалий swap-in/out, а не на «використаний swap».
  3. Алертуйте на OOM kills як подію рівня інциденту з контекстом жертви/кореня.
  4. Слідкуйте за топ RSS процесами і їх нахилом після деплоїв.
  5. Позначайте деплої та зміни конфігів на графіках пам’яті.

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

Одна цитата, яку варто тримати на стіні (або хоча б у runbook)

Парафразована ідея від Gene Kranz (mission operations): «Tough and competent» — залишайтеся спокійними, дотримуйтеся основ і виконуйте чекліст.

FAQ

1) Чому Linux використовує майже всю RAM, навіть коли наче нічого не працює?

Тому що «нічого не працює» рідко буває правдою (демони, кеші, структури ядра), і тому що Linux використовує вільну RAM для page cache. Цей кеш прискорює майбутні читання і звільняється під тиском.

2) Чи погано, якщо swap ненульовий?

Не обов’язково. Стабільне використання swap може означати, що холодні сторінки були переміщені. Погано — постійний swap-in/out (vmstat si/so), зростання major faults і затримки для користувачів.

3) Який найшвидший спосіб відрізнити кеш від витоку?

Почніть з free: якщо available у нормі — це, ймовірно, кеш. Потім підтвердьте через /proc/meminfo: високий Cached зі стабільним AnonPages вказує на кеш; зростаючі AnonPages — на ріст пам’яті процесів.

4) Чому той самий сервіс використовує більше RAM з часом, навіть без витоку?

Warm-up кешів, JIT-компіляція (Java), поведінка аллокатора (glibc arenas), connection pools і зміни в навантаженні — усе це може збільшити steady-state пам’ять. Питання — чи стабілізується вона і чи сигнали тиску лишаються спокійними.

5) У Kubernetes чому я отримую OOMKilled, коли на вузлі є вільна пам’ять?

Тому що під поштою досягнуто ліміту пам’яті пода. Ядро примушує cgroup до ліміту; йому байдуже, що на вузлі є запас. Виправте, правильно налаштувавши requests/limits і/або зменшивши кешування всередині контейнера.

6) Чи слід коли-небудь запускати echo 3 > /proc/sys/vm/drop_caches в продакшені?

Майже ніколи. Це інструмент діагностики в найкращому разі і може спричинити раптовий спад продуктивності, змусивши диск читати те, що раніше було в кеші. Якщо робите це — робіть свідомо, під час контрольного розслідування, і очікуйте впливу.

7) А що з ZFS ARC — витік чи кеш?

Зазвичай це кеш. ARC розширюється, щоб використати доступну RAM, якщо його не обмежити. Якщо ARC конкурує з додатками — ви помітите тиск: низьке MemAvailable, свопінг, reclaim. Виправлення — задати розмір ARC під навантаження і залишити запас.

8) Чому «available» відрізняється від «free»?

free — це буквально невикористані сторінки в момент знімка. available оцінює пам’ять, яку можна виділити без swap-у шляхом відновлення кешу та інших відновлюваних областей. Це більш корисний операційний показник.

9) Як вирішити між «додати RAM» і «виправити додаток»?

Якщо зараз тиск реальний, додавання RAM (або підвищення лімітів) може бути найменш ризиковим негайним заходом. Але якщо RSS росте без меж — більше RAM лише відкладатиме аварію. Використовуйте тренд росту і сигнали тиску, щоб вирішити.

10) Чи може ріст slab ядра спричинити outage?

Так. Slab може зайняти багато RAM, особливо при метаданому churn файлової системи або зростанні мережевих таблиць. Підтвердіть через slabtop і дослідіть патерн навантаження та версію ядра перед тим, як чіпати налаштування.

Висновок: практичні наступні кроки (робіть це, а не відчуття)

  1. Виправте ментальну модель: перестаньте трактувати «RAM used» як «RAM недоступна». Використовуйте MemAvailable і індикатори тиску.
  2. Покращіть алерти: сигналізуйте при OOM kills, тривалому churn swap і низькому available, а не при «used %».
  3. Класифікуйте пам’ять: анонімна vs файловий кеш vs slab vs cgroup. Обирайте інструменти відповідно до класу.
  4. Вимірюйте тренди: знімки брешуть. Слідкуйте за топ RSS процесами і їх нахилом після деплоїв.
  5. Зробіть бюджети пам’яті явними: кеші (БД, JVM, Redis, ZFS ARC) потребують запасу. Якщо ви не можете пояснити бюджет — ви граєте в рулетку.
  6. Використовуйте рестарти помірно: вони прийнятні як тимчасовий захід при гострому тиску, але лише якщо ви також відкриєте розслідування «чому воно виросло?».

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

← Попередня
Обмін файлами в Linux: NFS проти SMB — оберіть той, що не зависатиме випадково
Наступна →
SMB: спільні ресурси Windows для Linux — контрольний список сумісності

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