Слогер Создать блог
Разработка

Почему Redis не отдаёт память сразу после удаления ключей и как это проверить

Ключа в базе уже нет, а RSS процесса стоит на месте и проседает только через десятки секунд. Разбираю, кто именно держит байты и по каким метрикам это ловится.

Удалили ключ — Redis вернул ноль байт. Память на графике наконец проседает через полминуты, и непонятно: всё штатно или мы только что нашли утечку. Скорее всего штатно. Дальше — почему так происходит и что реально смотреть.

Две цифры, которые постоянно путают

У Redis есть внутренняя бухгалтерия и есть реальность. used_memory — сколько данных инстанс считает своими по своей же статистике. used_memory_rss — сколько страниц памяти занимает процесс с точки зрения операционной системы.

Первая цифра может упасть в ту же секунду, когда вы сделали DEL. Вторая — нет, и это не баг. Между «Redis забыл про ключ» и «операционная система получила страницы назад» лежат две прослойки: механизм удаления и аллокатор.

Как именно исчезает ключ

Команда DEL работает синхронно: пока Redis освобождает память от значения, он не обслуживает другие запросы. Для строки в 100 байт это незаметно. Для хеша на 4 миллиона полей — заметная пауза в обработке.

Поэтому появился UNLINK: ключ пропадает из пространства имён мгновенно, а освобождение памяти уходит в фоновый поток. Ту же логику можно включить принудительно для обычных команд — параметры lazyfree-lazy-user-del, lazyfree-lazy-expire, lazyfree-lazy-eviction, lazyfree-lazy-server-del.

Отдельная история — ключи с TTL. Redis ищет просроченные двумя путями: пассивно, когда кто-то обратился к ключу, и активно — фоновым циклом, который выбирает случайные ключи с истекающим сроком и вычищает те, что уже протухли. Отсюда и знакомое ощущение «память вернулась сама через двадцать секунд»: ключ физически лежал в базе до того, как до него дошла очередь.

Аллокатор не спешит делиться

Redis по умолчанию работает на jemalloc. Память он берёт у системы крупными кусками и раздаёт под данные сам. Когда вы освобождаете ключ, байты возвращаются не операционной системе, а обратно в пул jemalloc — страницы помечаются как грязные и отдаются наружу позже, по внутреннему таймеру.

Плюс арены: jemalloc заводит отдельные пулы под потоки, чтобы они не толкались за общим локом. Каждая арена держит свою память. Если потоков много, число арен растёт, и освобождённое в одной арене не помогает другой. Ограничивается переменной окружения MALLOC_ARENA_MAX.

И ещё: возврат памяти идёт фоном active defrag (activedefrag yes), который переупаковывает данные, вытаскивая полезное из разбросанных страниц.

Метрики, по которым видно, что происходит

МетрикаЧто показываетНа что смотреть
used_memoryДанные по версии самого RedisРастёт вместе с числом ключей — норма
used_memory_rssСколько занимает процесс для ОССтоит на месте после массового удаления
mem_fragmentation_ratioОтношение rss к used_memory1,0–1,3 — норма; выше 1,5 — смотреть фрагментацию
allocator_frag_ratioФрагментация внутри аллокатораВысокая вместе с ratio — арены и пулы
mem_allocatorКакой аллокатор подключён сборкойРазные сборки ведут себя по-разному

Если mem_fragmentation_ratio меньше единицы, часть памяти ушла в swap. Это хуже, чем фрагментация: отзывчивость инстанса при этом падает куда заметнее.

Что проверить руками

  1. INFO memory — снять used_memory, used_memory_rss, mem_fragmentation_ratio до удаления и через минуту после.
  2. MEMORY DOCTOR — короткий вердикт от самого Redis, часто указывает на конкретную причину.
  3. MEMORY USAGE key — сколько весит один ключ со всеми накладными расходами. Полезно перед чисткой больших коллекций.
  4. redis-cli --bigkeys — находит крупные структуры. Именно они дают паузы при синхронном DEL.
  5. MEMORY STATS — разбивка по потребителям: клиентские буферы, replication backlog, память под осколки.

Типичные ошибки

Самая частая — перезапуск инстанса. Он «лечит» симптом на один вечер: после старта RSS аккуратный, а через сутки фрагментация возвращается ровно та же, потому что нагрузка не изменилась. Вторая ошибка — смотреть только на used_memory и радоваться, когда внутренняя цифра упала. Третья — ставить maxmemory без политики вытеснения, а потом удивляться, что запись падает с ошибкой.

И ещё одна, совсем обидная: массово удалять ключи обычным DEL в цикле на боевом инстансе. Лучше сразу UNLINK — или включить ленивое освобождение на уровне конфигурации.

Когда чинить нечего

Ориентир простой: если удалённые данные освобождаются в пределах минуты, а отношение RSS к used_memory держится около единицы, трогать ничего не нужно — это нормальное поведение аллокатора, заложенное в его устройство.

Другой разговор, когда RSS стоит на месте час и растёт линейно вместе с числом ключей. Тогда смотрите на крупные коллекции, клиентские буферы и настройки арен, а не на команду удаления.

По материалам: career. Текст переработан редакцией Слогера.

← На главную

Рекламное место — Конец поста
Реклама · Слогер

Комментарии (0)

Войдите, чтобы комментировать.

Пока нет комментариев. Будьте первым.

Разработка

Как ревьюить pull request и не отпугнуть контрибьютора: ярлык против разбора

Комментарий «похоже, это писал ИИ» и разбор диффа по существу занимают одинаковое время. Только в одном случае автор уходит молча, а проблема остаётся висеть ещё семь месяцев.

Слогер 07.10.2026 ▲ 0
Карьера

Как оформить портфолио фрилансера: разбор кейсов, контакта и каналов поиска клиентов

Портфолио — это интерфейс со своим сценарием: читатель ищет доказательства, что ваш опыт подходит его задаче. Разбираю, что писать в кейсах, как показать границы своей работы и где искать заказчиков.

Слогер 07.10.2026 ▲ 0
Карьера

Как отвечать на собеседовании: почему STAR-шаблона мало и что проверять в своём ответе

Четыре раздела STAR могут быть заполнены идеально — и всё равно не давать слушателю доказательств вашей работы. Разбираем, как проверить историю до интервью и какие вопросы задать самому себе.

Слогер 07.10.2026 ▲ 0
Разработка

Почему разработчики перестают писать код: разбор новой роли и что делать команде

Спецификации на человеческом языке, тест-сценарии и агент, который пишет реализацию. Что это меняет в работе одного разработчика и почему командные процессы не успели за этим.

Слогер 06.10.2026 ▲ 0
Fluxs lenta
Реклама · fluxs.ru
Личный опыт

Имплант, мост или съёмный протез: чем отличаются и как выбрать

Три способа заменить зуб решают одну задачу по-разному, и разница проявляется через годы, а не в день оплаты. Разбираем, что подойдёт именно в вашем случае и о чём спрашивать врача заранее.

Слогер 05.10.2026 ▲ 1
Fluxs lenta
Реклама · fluxs.ru
Разработка

Как японские принципы управления делают код чище и экономнее

5S, канбан, дзидока и ваби-саби родились на производстве, но отлично объясняют, почему один софт летает на слабом железе, а другой тормозит на ровном месте. Разбираем, как эти практики выглядят в репозитории и в голове разработчика.

Слогер 05.10.2026 ▲ 0
Образование

Как закончить бесплатный курс Microsoft по AI: разбор плана обучения и бейджа

Microsoft Learn собрал бесплатный самостоятельный трек по искусственному интеллекту — с модулями, проверками знаний и цифровым бейджем на финише. Разбираем, что внутри и как не бросить на середине.

Слогер 05.10.2026 ▲ 0
Разработка

Как переписать личное портфолио с Angular 12 на Angular 22: разбор прыжка через десять версий

Личный сайт на Angular 12, продакшен на Angular 19 — и решение переписать всё сразу на 22. Что даёт чистая переписка вместо цепочки миграций, и почему инфраструктура и SVG-математика важнее списка логотипов в резюме.

Слогер 04.10.2026 ▲ 0
Fluxs lenta
Реклама · fluxs.ru
Карьера

Как выбрать тренажёр для mock-интервью: разбор AI-сервисов, живых интервьюеров и банков задач с ценами

Собеседование проверяет не только код, но и умение объяснять. Разбираем, какие сервисы для репетиции интервью стоят своих денег, а какие путают с тренажёрами.

Слогер 04.10.2026 ▲ 0