На сервере PostgreSQL почти не остаётся свободной RAM. Так продолжается неделями, но база отвечает быстро, ошибок нет, пропускная способность стабильна. Команда привыкает к красному индикатору и считает его особенностью Linux. Затем в один из дней p99 растёт, хотя аварийного завершения процессов ещё не было. На графике памяти нет заметного нового скачка: она и раньше была занята почти полностью. Изменилось другое — база начала тратить время на борьбу за память вместо обработки запросов. Обычный показатель used не видит эту разницу. Он складывает полезный кэш, память процессов и другие категории, но не отвечает, теряет ли приложение рабочее время. PSI помогает увидеть именно ожидание, которое возникает до крайней ситуации нехватки памяти.
Заполненная RAM может быть нормальным состоянием
Linux старается не оставлять память без дела. Свободный объём используется для page cache — кэша недавно прочитанных файлов. Благодаря ему PostgreSQL может повторно получить нужные данные без нового чтения с накопителя. Поэтому низкий free, то есть полностью незанятая память, сам по себе не доказывает дефицит. Часть кэша можно освободить, если процессу потребуется место. Пока это происходит без заметной цены, заполненная RAM приносит пользу. PostgreSQL использует собственный shared_buffers для блоков таблиц и индексов и одновременно опирается на кэш операционной системы. Суммарная занятость не показывает, какая страница понадобится следующей и насколько дорогим будет её вытеснение.
Авария OOM, или out of memory, происходит, когда системе либо ограниченной группе процессов уже не хватает памяти для продолжения работы и приходится завершать процесс. Но ухудшение сервиса способно начаться раньше: ядро ещё справляется, только тратит на это всё больше времени. Разница между «RAM занята» и «работа остановилась в ожидании RAM» принципиальна для бюджета. Первый случай может означать эффективный кэш. Второй — реальную потерю производительности, которую нужно связать с приложением.
Давление начинается с потерянного времени
Когда новой памяти не хватает, Linux запускает reclaim — освобождение памяти. Ядро вытесняет подходящие страницы, записывает изменённые данные при необходимости и ищет объём, который можно отдать запросившей задаче. Освобождение не всегда заметно пользователю. Если удаляется давно ненужный кэш, приложение продолжает работу. Если вытесняются страницы, которые вскоре снова потребуются, возникают повторные чтения и ожидание. Под давлением задачи могут ждать, пока завершится освобождение или нужная страница вернётся в память. Процесс существует, сервер не упал, но полезная работа временно не продвигается. Именно в этот промежуток растут задержки до OOM.
Meta в проекте TMO использовала PSI как обратную связь, чтобы оценивать влияние давления, а не ориентироваться только на количество page faults. Этот принцип важнее конкретной реализации: результат измеряют по времени, которое нагрузка не могла выполнять полезную работу. Если давление короткое и не затрагивает сервис, оно может быть приемлемым. Если ожидание совпадает с ростом задержки и падением объёма выполненных запросов, заполненная память перестаёт быть безобидным состоянием.
PSI измеряет ожидание, а не гигабайты
PSI расшифровывается как Pressure Stall Information — информация о простоях из-за давления на ресурс. Linux оценивает долю времени, в течение которого задачи не могли продвигаться из-за нехватки процессора, памяти или ввода-вывода. Для памяти PSI не сообщает, сколько гигабайт занято и какая таблица виновата. Он отвечает на другой вопрос: какую часть времени наблюдаемая нагрузка провела в ожидании, связанном с давлением на память. Значение some означает, что в рассматриваемый момент ждала хотя бы часть не простаивающих задач. Другие задачи могли продолжать работу, поэтому сервис ещё сохранял часть производительности.
Значение full означает более тяжёлое состояние: все не простаивающие задачи наблюдаемой группы одновременно не могли продвигаться. Для системы или контейнера это период полной потери полезной работы из-за данного ресурса. PSI полезен именно потому, что добавляет измерение времени к графику ёмкости. Два сервера могут иметь одинаково низкий free, но на одном задачи не ждут, а на другом заметная часть работы уходит на освобождение и возврат страниц.
PostgreSQL и Redis показывают давление по-разному
В PostgreSQL ожидание памяти может удлинить запрос, который читает или изменяет данные. Если транзакция дольше держит блокировку, за ней выстраиваются зависимые операции. Один медленный путь превращается в хвост задержки для группы клиентов. p99 — граница, в которую укладываются все запросы, кроме самого медленного одного процента. Она помогает увидеть редкие провалы, скрытые средним значением. Конкретная допустимая граница зависит от сервиса, а не от Linux. Redis часто обслуживает короткие операции, поэтому неожиданная пауза заметна сразу. Но официальная документация Redis перечисляет много возможных причин: процессор, сеть, накопитель, фоновые операции и среда виртуализации. Один рост задержки не доказывает нехватку RAM.
PSI также не называет конкретный SQL, таблицу или Redis-ключ. Он показывает, что группа задач потеряла время. Причину ищут в контексте: какая фаза нагрузки шла, менялись ли лимиты и совпал ли сигнал с поведением базы. Полезна временная связь. Если memory PSI растёт одновременно с p99, падением пропускной способности и активным освобождением страниц, версия о давлении становится сильнее. Если PSI памяти спокоен, похожую задержку разумнее объяснять процессором, диском, блокировками или сетью.
У системы и контейнера разные границы
Один сервер может обслуживать несколько баз или контейнеров. Общая RAM хоста выглядит достаточной, но отдельный сервис способен упереться в собственный лимит. Возможна и обратная ситуация: контейнер не достиг границы, а соседняя нагрузка создаёт давление на весь узел. Cgroup — механизм Linux, который объединяет процессы для учёта и ограничения ресурсов. Контейнер обычно работает внутри такой группы. PSI можно смотреть как для всей системы, так и для конкретной cgroup. Разделение уровней помогает не смешивать причины. Системный PSI показывает общую конкуренцию хоста. Групповой PSI показывает ожидание внутри выбранного сервиса с учётом его границ. Низкое общее давление не отменяет тесный лимит контейнера.
Это особенно важно в общей инфраструктуре. Redis может работать стабильно, пока соседний PostgreSQL не запускает отчёт. Без разделения команда увидит одновременную задержку, но не поймёт, принадлежит ли давление самому сервису или общему узлу. События cgroup дополняют картину: группа может регулярно достигать мягкой границы, активно освобождать память или подойти к жёсткому пределу. Но перечислять все внутренние поля руководителю не нужно. Важен уровень, на котором сервис начал терять время.
PSI помогает принять решение до аварии
PSI — ранний сигнал потери производительности, но не диагноз. Давление на память может возникнуть из-за роста рабочего набора, слишком тесного лимита, всплеска параллельности или поведения кэша. Похожая задержка без memory PSI имеет другие вероятные причины. Решение поэтому зависит от контекста. Иногда достаточно изменить запрос или ограничить одновременную работу. Иногда нужно скорректировать контейнерный лимит, разнести соседние нагрузки или добавить DRAM. Заполненный кэш без ожидания не требует тех же затрат. Многоуровневая память тоже оценивается по потерянному времени, а не только по освобождённым гигабайтам. Если возврат страниц увеличивает PSI и хвост задержки, дополнительная ёмкость не превращается в полезную работу.
Для прозрачного страничного уровня gigaRAM действует тот же деловой критерий: сохранить работу СУБД и самые медленные ответы, а не просто уменьшить DRAM. PSI может быть одним из сигналов инфраструктурного мониторинга, но не заменяет показатели задержки и выполненной работы. Главный вывод: почти нулевой free и реальный дефицит памяти — разные состояния. PSI показывает переход от полезно занятой RAM к потерянному времени до OOM. В сочетании с задержкой и выполненной работой он помогает выбрать между оптимизацией, лимитом, DRAM и более сложной архитектурой памяти.
Источники. Linux kernel — PSI определяет pressure, some, full и учёт времени.
Linux cgroup v2 Memory описывает давление и события на уровне групп.
Meta Engineering — TMO показывает PSI как обратную связь.
Google SRE Book объясняет хвост задержки и насыщение.
Redis Latency описывает причины задержки Redis.
PostgreSQL 17 подтверждает роль shared_buffers и кэша ОС.
Страница продукта используется только для механики и позиционирования.
