MAATRIX / Блог / Куда девается «свободная» память сервера и почему это правильно

Куда девается «свободная» память сервера и почему это правильно

MAATRIX

Заходите на свежекупленный сервер, набираете free -h — и видите, что «свободной» памяти почти не осталось, хотя вы ещё ничего не разворачивали. Первая мысль — что-то сожрало RAM, надо брать тариф побольше. Стоп: в девяти случаях из десяти это нормальное поведение ядра Linux, и сейчас разберём, почему.

Что на самом деле показывает free -h

Возьмите сервер, который уже пожил хотя бы пару дней, и посмотрите на вывод:

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           4.0Gi       412Mi       2.1Gi        12Mi       1.5Gi       3.4Gi
Swap:          2.0Gi          0B       2.0Gi

Путаница почти всегда возникает из-за того, что человек складывает used и free и не понимает, куда делась разница — а разница это buff/cache, обычно самая большая колонка.

  • total — сколько физической RAM видит ядро.
  • used — память, которую реально держат процессы.
  • free — память, вообще ничем не тронутая; на живом сервере она стремится к нулю, и это нормально.
  • shared — tmpfs и разделяемые сегменты.
  • buff/cache — буферы и page cache: данные с диска, оставленные в памяти, потому что место было свободно.
  • available — оценка ядра, сколько памяти реально можно выделить новому процессу без ухода в своп; это не free и не прямая сумма free + buff/cache.

Если free маленький, а buff/cache большой — сервер здоров. Тревожиться стоит, когда маленькие сразу оба: и free, и available.

Что такое page cache и зачем ядру забирать всю память

Чтение с диска на порядки медленнее чтения из RAM, поэтому ядро устроено просто: прочитал страницу с диска — оставил копию в памяти, в page cache. Повторный запрос тех же данных отдаётся из RAM, без обращения к диску. С записью то же самое: изменённые (dirty) страницы какое-то время живут в памяти и сбрасываются на диск асинхронно — этим управляют vm.dirty_ratio и vm.dirty_background_ratio.

Кеш растёт, пока в системе есть свободная память: простаивающая RAM — бесполезный ресурс, выгоднее занять её данными, которые пригодятся снова. Отсюда типичная картина: сервер погонял через себя логи, статику, базу — и buff/cache съел почти всю свободную память. Это не утечка и не процесс-обжора, это кеш файловой системы делает свою работу.

Отдельная история — Redis, PostgreSQL, MySQL и подобные сервисы с собственным кешированием: они держат данные в памяти самого процесса, это видно в used, а не в buff/cache. Если это ваш случай — тема отдельная: высокое потребление памяти Redis.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Почему это «занятая» память в хорошем смысле

Ключевое свойство page cache — он мгновенно отдаётся любому процессу, которому реально понадобилась память. Если приложению нужно выделить 500 МБ, а свободных страниц нет, ядро вытесняет столько же страниц из кеша (сбросив на диск изменённое, если было) и отдаёт освободившуюся память процессу. Вытеснение чистой страницы кеша — дешёвая операция. Это принципиально отличается от памяти, которую держит процесс: чтобы освободить её, приложение должно само её вернуть или процесс должен быть убит — ядро не может «отобрать» память у работающего процесса так же легко, как у кеша.

Поэтому когда used — 300 МБ, а buff/cache — 3 ГБ, это не «занято 3.3 из 4», а «занято 300 МБ, и почти всё остальное временно используется под кеш, который отдастся по первому требованию». Именно это явление в англоязычных обсуждениях называют «Linux ate my RAM» — старая шутка про новичков, которые пугаются нормального поведения ядра.

available вместо free — как читать правильно

Чтобы понять, хватает ли памяти на сервере, ориентир — колонка available, а не free и не арифметика на глаз. Это эвристическая оценка ядра: сколько памяти реально можно выделить, учитывая реально свободные страницы, часть page cache, которую можно безболезненно вытеснить, и часть reclaimable-структур ядра вроде dentry и inode cache. Те же значения лежат в /proc/meminfo строками MemFree и MemAvailable.

Практическое правило: если available держится в районе половины total или больше — с памятью всё в порядке, независимо от того, что показывает free. Тревожиться стоит, когда available стабильно низкий, а не разово при пиковой нагрузке.

Когда памяти реально не хватает

Есть два надёжных индикатора настоящей нехватки, и оба не связаны с размером buff/cache.

Своп начинает активно использоваться. Разовое ненулевое Swap: used — не катастрофа, ядро иногда выгружает в своп редко используемые страницы даже при наличии свободной RAM (управляется vm.swappiness). А вот постоянный рост si/so (swap in / swap out) в выводе vmstat 1 — признак, что RAM не хватает и система вынуждена подкачивать данные с диска; растущие из строки в строку значения — сигнал действовать: смотреть, что ест память, добавлять RAM или пересматривать конфигурацию сервисов. Про то, как настроить своп и какого размера файл закладывать — своп-файл: когда нужен и как настроить.

OOM killer убивает процессы. Если памяти не хватает настолько, что не спасает даже своп (или он отключён), в дело вступает OOM killer — механизм ядра, который завершает процесс, чтобы не дать системе зависнуть насмерть: такие записи покажут dmesg -T | grep -i "killed process" или journalctl -k | grep -i oom. Разовый OOM под нагрузочный пик — повод разобраться, что съело память (частая причина — утечка памяти на сервере); систематические OOM — сигнал, что RAM для вашей нагрузки уже не хватает.

Как проверить и настроить на практике

Короткий чек-лист: free -h — смотрите на available; vmstat 1 минуту под нагрузкой — следите за si/so; dmesg -T | grep -iE "oom|killed process" — история инцидентов; ps aux --sort=-%mem | head -15 или htop — кто ест память, если подозреваете конкретный процесс, а не кеш.

Отдельный параметр — агрессивность свопинга, vm.swappiness (по умолчанию обычно 60). Для сервера с базой данных его часто снижают до 10–20 через sudo sysctl vm.swappiness=10, чтобы ядро не спешило выгружать рабочие данные ради кеша; для сохранения после перезагрузки нужна такая же строка в /etc/sysctl.conf.

Кеш можно и сбросить вручную (sync; echo 3 | sudo tee /proc/sys/vm/drop_caches), но это не «лечит» нехватку памяти — освобождённое тут же начнёт заполняться заново, а такой сброс лишь временно замедлит чтение файлов на проде, пока кеш прогревается снова. Используйте это только для диагностики.

Если после проверок available стабильно низкий, своп используется под нагрузкой и в логах есть записи OOM killer — дело не в непонимании вывода free, а в реальном дефиците RAM. Тогда разумный путь — посчитать фактическое потребление под нагрузкой и выбрать тариф с запасом; ориентиры — в материале про запас по оперативной памяти.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Почему free -h после старта сервера показывает много free, а через день — почти ничего?

Ядро постепенно накапливает page cache по мере того, как процессы читают файлы с диска. Это ожидаемый рост, не утечка.

Может ли page cache вызвать нехватку памяти для приложения?

Нет — ядро всегда вытесняет страницы кеша раньше, чем откажет процессу в выделении памяти.

Стоит ли вручную чистить кеш через drop_caches на постоянной основе?

Нет: это временно ухудшит производительность дисковых операций без пользы — освобождённая память тут же снова заполнится кешем.

Как понять, что нужно увеличить объём RAM, а не разбираться с настройками?

Смотрите на устойчивую динамику: available стабильно низкий, si/so в vmstat постоянно ненулевые под обычной нагрузкой, в dmesg регулярно появляются записи OOM killer. Разовый всплеск — не показатель, стабильная картина в течение дней — показатель.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →