Куда девается «свободная» память сервера и почему это правильно
Заходите на свежекупленный сервер, набираете 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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →