Сколько памяти жрет Redis? Формула, примеры и точный калькулятор

💻 IT и кодОбновлено: 13 июля 2026 г.6 мин чтения
Redis в памяти — быстро, но каждый килобайт на счету. Неправильный расчёт ведёт к OOM-киллам и падению продов. Даю точную формулу, примеры и ссылку на онлайн-калькулятор, чтобы вы не гадали.
⚡ Коротко: главное
  • Redis расходует на каждую строку минимум 80 байт служебных данных, не считая полезных полей.
  • Для 1 млн ключей с 50-байтовыми значениями Redis потребуется ~300 МБ ОЗУ.
  • Использование типов данных, отличных от строк, может увеличить расход памяти в 2-5 раз.
  • Наибольший прирост дают хеши с малым числом полей (ziplist даёт до 70% экономии).
  • Команда MEMORY USAGE — ваш главный инструмент отладки.

Базовая формула расхода памяти Redis

Redis хранит данные в оперативной памяти, и каждый ключ/значение обрастает служебными структурами. Минимальный расход на одну строку (ключ+значение) можно оценить как:

overhead = 64 + 8 + len(key) + len(value) в байтах

Где 64 байта — служебная нагрузка на запись (тип, флаги, срок жизни), 8 байт — указатель на словарь, плюс фактические строки. Для целых чисел (int) значение может храниться в самом указателе (до 2^31). На 2026 год это правило не изменилось: Redis продолжает использовать словарь с 64-байтной записью.

Пример: ключ "user:123" (9 байт), значение "active" (6 байт). Реальный расход ≈ 64 + 8 + 9 + 6 = 87 байт. Но это без учёта выравнивания и фрагментации аллокатора памяти (jemalloc), который может дать ещё 10-30% сверху.

Подробная формула с учётом типов данных

Для точного расчёта нужно учитывать тип данных Redis. Ниже — основные варианты:

Тип RedisБазовая структураДоп. расход на элементПример (1 тыс. элементов)
String (raw)64 + len(k) + len(v)0~87 тыс. байт
String (int, до 2^31)64 + len(k) + 0 (value внутри указателя)0~73 тыс. байт
Hash (ziplist, до 512 полей)64 + len(k) + сумма размера всех пар2 байта на элемент~64 + 9 + 2*1000 = 2073 байт
Hash (hashtable, больше 512 полей)64 + len(k) + таблица entries32 байта на entry~64 + 9 + 32*1000 = 32073 байт
List (quicklist)64 + len(k) + узлы quicklist24 байта на элемент~64 + 9 + 24*1000 = 24073 байт
Set (intset, до 512 целых)64 + len(k) + массив int4 байта на элемент~64 + 9 + 4*1000 = 4073 байт
Set (hashtable)64 + len(k) + таблица32 байта на элемент~64 + 9 + 32*1000 = 32073 байт
Sorted Set (ziplist, до 128 эл.)64 + len(k) + сумма пар(member+score)2 байта на элемент~64 + 9 + 2*1000 = 2073 байт
Sorted Set (skiplist)64 + len(k) + таблица + уровни~68 байт~64 + 9 + 68*1000 = 68073 байт

Все цифры — на 2026 год. Важно: Redis использует jemalloc, который выделяет память блоками по степени двойки (16, 32, 48, 64, 80 и т.д.). Поэтому реальный расход может быть округлён вверх до ближайшего блока.

Пошаговый пример расчёта для 1 миллиона ключей

Рассчитаем память для типового сценария: кэш сессий. 1 млн ключей вида "session:uuid" (36-символьный UUID + префикс, всего 45 байт), значение — JSON 200 байт. Тип — String.

  1. Расход на ключ: 64 (запись) + 8 (указатель) = 72 байта.
  2. Плюс длина ключа: 45 байт = 117 байт.
  3. Плюс длина значения: 200 байт = 317 байт на запись.
  4. Учитывая jemalloc, округляем каждый "запись+данные" до ближайшего блока: 317 → 320 байт.
  5. На 1 млн записей: 320 * 1 000 000 = 320 000 000 байт ≈ 305 МБ.
  6. Добавляем служебный словарь: Redis хранит все ключи в глобальном словаре (ещё ~4 байта на ключ) = 4 МБ.

Итого: ~309 МБ. Плюс replication buffers, slowlog, client-буфера — может быть до 350 МБ.

Для проверки используйте Калькулятор расхода памяти Redis — он автоматически учтёт типы данных и аллокацию.

Подводные камни: что может неожиданно сожрать память

Многие разработчики удивляются, почему Redis ест в 2 раза больше ожидаемого. Типичные ловушки:

1. Срок жизни (TTL). Каждый ключ с TTL добавляет 8 байт на таймер. Если у всех ключей разный TTL — эти 8 байт превращаются в 8 МБ на 1 млн ключей.

2. Хеши со счётчиками. Если в хеше каждое поле — целое число, Redis может хранить его как int, но при превышении порога (512 полей или 64 байт на поле) переключается на hashtable, увеличивая расход в 5 раз.

3. Фрагментация. Redis использует jemalloc, который не дефрагментирует. После многих апдейтов значений разного размера память дробится. Разница занятой и используемой памяти может достигать 30%.

Следите за метриками used_memory и used_memory_rss в INFO. Если RSS > used_memory на 30% — фрагментация критична. Включите activedefrag yes (доступно с Redis 5.0, сейчас 7.x — ещё лучше).

Структура одной записи в Redis (хэш-таблица)
Запись словаря (64 байт)

Содержит ключ, значение, типы, флаги, TTL, указатель на следующую запись.

Указатель на ключ (8 байт)

Ссылка на строку ключа в памяти.

Строка ключа (len(key) байт)

Фактическая строка ключа, например 'user:123' — 9 байт.

Указатель на значение (8 байт)

Ссылка на объект значения.

Объект значения (len(value) + overhead)

Для строк — строка, для хеша — ziplist или hashtable и т.д.

Схема, отображающая служебные поля записи Redis, включая указатели и данные.

Как отлаживать расход памяти: команды и инструменты

Redis предоставляет встроенные команды для точной диагностики:

КомандаЧто показываетПример использования
MEMORY USAGE <key>Реальный размер ключа в байтах с учётом служебных структурMEMORY USAGE session:abc123 → (integer) 320
MEMORY STATSСводку по используемой памяти, фрагментации и т.д.MEMORY STATS → ... overhead.hashtable.main: 4194304
INFO memoryАгрегированные метрики: used_memory, peak, fragmentation ratioINFO memory → # Memory used_memory:524288000... used_memory_rss: 629145600
MEMORY PURGEПринудительно очищает свободные страницы (только Redis 4.0+)MEMORY PURGE → OK
DEBUG OBJECT <key>Показывает внутреннюю кодировку (int, embstr, raw) и ссылочный счётчикDEBUG OBJECT user:1 → Value at:0x7f... refcount:1 encoding:embstr serializedlength:6

Также полезно смотреть bigkeys с помощью redis-cli --bigkeys — найдёт самые прожорливые ключи.

Онлайн-инструменты, такие как Калькулятор расхода памяти Redis, позволяют быстро прикинуть бюджет памяти без запуска Redis.

🧠 Проверьте свои знания о памяти Redis

1. Сколько байт служебной нагрузки (overhead) минимально добавляет каждая запись Redis?

2. Какой тип данных Redis даёт наибольшую экономию при хранении объекта с 10 полями?

3. Какая команда показывает точный размер конкретного ключа в Redis?

4. Что означает, когда used_memory_rss значительно больше used_memory?

5. Какое максимальное количество полей в хеше, при котором он хранится как ziplist (по умолчанию)?

Оптимизация: как уменьшить расход памяти на 30–70%

Несколько проверенных техник:

  • Хеши вместо строк. Если у вас объект с 10-20 полями, храните его как хеш: HSET user:1 name "John" age 30 — при малом количестве полей (до 512) Redis использует ziplist, что даёт экономию до 70% по сравнению с JSON-строкой.
  • Целые ключи. Вместо "user:1000000" используйте просто число 1000000. Redis может хранить int внутри указателя, экономя 9-30 байт на ключе.
  • Выставляйте TTL, если данные не вечные. Сокращает количество мусора, но не забывайте про накладные расходы на таймер.
  • Используйте list вместо set для списков без проверки дубликатов. Set (hashtable) дороже list (quicklist) на 30%.
  • Обновляйте Redis до версии 7.2+. В ней улучшена работа с памятью: compact memory for small keys, новые кодировки.

После оптимизации пересчитайте потребление на калькуляторе.

Типичные ошибки при расчёте памяти Redis

Даже опытные DevOps ошибаются. Вот топ-5:
  • Не учитывают служебные данные (overhead). Многие считают только размер value, забывая про 80+ байт на каждый ключ.
  • Путают used_memory и used_memory_rss. Первое — реальное занятое место, второе — выделенное ОС (с учётом фрагментации). Разница может быть 2x.
  • Игнорируют настройки maxmemory-policy. Если политика "allkeys-lru", Redis может вытеснять ключи, увеличивая фрагментацию.
  • Считают 1 байт на символ для Unicode. В Redis строки байтовые, кириллица в UTF-8 занимает 2 байта на символ.
  • Забывают про репликацию и буферы. На master+slave каждая запись дублируется. Plus client output buffer может добавить 10% к памяти.

Используйте команды из предыдущего раздела, чтобы проверить реальное потребление, а не гадать.

Калькулятор и бенчмарки: как проверить свой сценарий

Для точных цифр лучше всего прогнать тесты на ваших данных. Проще всего — написать маленький скрипт на Python, который генерирует 1000 ключей и смотрит used_memory до и после:

import redis
r = redis.Redis()
before = r.info('memory')['used_memory']
for i in range(1000):
    r.set(f'key:{i}', 'x'*200)
after = r.info('memory')['used_memory']
print(f'На 1000 ключей: {(after-before)/1024:.2f} КБ')

Разделите на 1000, умножьте на 1 000 000 — получите примерное потребление для млн. Но аллокатор может вести себя нелинейно, поэтому для серьёзного проекта используйте Калькулятор расхода памяти Redis, который учитывает jemalloc и типы данных.

Также полезно прогнать официальный бенчмарк с вашими данными: redis-benchmark -P 16 -n 100000 -r 100000 -d 200 -t set. Но помните, что бенчмарк не отражает реальную фрагментацию при долгой работе.

Заключение: главные правила экономии памяти в Redis

  • Используйте хеши для объектов — они дают наибольшую экономию.
  • Выбирайте целочисленные ключи, если это возможно.
  • Устанавливайте TTL только когда это действительно нужно, и группируйте одинаковые TTL.
  • Следите за фрагментацией (used_memory_rss / used_memory). Если > 1.5, включите activedefrag.
  • Перед закупкой железа — прикиньте бюджет через калькулятор.

Помните: Redis — не бездонная бочка. 1 ГБ ОЗУ на современном сервере стоит дёшево, но при 10 млрд ключей один только overhead может сожрать 800+ ГБ. Планируйте заранее.

🧮 Посчитайте сами — инструменты по теме

🧭 Разделы по теме

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

Какой минимальный размер ключа в Redis?

Минимальный размер ключа — 1 байт (пустая строка недопустима). Но с учётом служебных данных каждая запись весит не менее 64+8+len(key) байт.

Сколько памяти занимает 1 миллион пустых ключей в Redis?

Каждый ключ без значения занимает ~72 байта (64 служебных + 8 указатель). Для 1 млн ключей: 72 МБ плюс служебный словарь (~4 МБ). Итого ~76 МБ.

Почему Redis использует больше памяти, чем я ожидаю?

Основные причины: фрагментация jemalloc (RSS может быть на 30% выше), служебные структуры (overhead 80+ байт на запись), дублирование при репликации, а также буферы клиентов. Используйте MEMORY STATS для деталей.

Как уменьшить расход памяти Redis без потери данных?

Переходите на хеши для объектов, используйте целочисленные ключи, включайте activedefrag, снижайте hash-max-ziplist-entries, используйте list вместо set. Также можно уменьшить maxmemory и настроить вытеснение.

Что делать, если Redis упал с OOM (Out of Memory)?

Проверьте maxmemory и политику вытеснения. Увеличьте maxmemory или смените политику на allkeys-lru. Удалите большие ключи (команда UNLINK). Включите swap (не рекомендуется) или добавьте память на сервере.

Какая разница между used_memory и used_memory_rss?

used_memory — реально занятая память (сумма всех данных). used_memory_rss — выделенная ОС (с фрагментацией). Если RSS > used_memory на 50% — сильная фрагментация, включите activedefrag.

Как проверить, какой ключ съел больше всего памяти?

Используйте redis-cli --bigkeys или команду MEMORY USAGE для каждого ключа в цикле. На реальных данных — скрипт с SCAN и MEMORY USAGE.

Работают ли эти расчёты для Redis Cluster?

Да, принципы те же, но каждый шард — независимый инстанс Redis. Общий расход — сумма по всем шардам. Плюс служебная память на кластерные узлы (слоты, gossip).

Источники и нормативные документы

  1. Документация Redis по командам MEMORY
  2. Статья Redis memory optimization на официальном сайте
  3. Исходный код Redis (структуры словаря)

Ещё по теме «IT и код»