Какие существуют политики вытеснения данных (eviction policies) в Redis и другие способы борьбы с переполнением памяти?

Ответ

Когда Redis достигает лимита памяти (maxmemory), он начинает вытеснять данные согласно заданной политике (maxmemory-policy).

Основные политики вытеснения:

  1. noeviction (по умолчанию): Redis не удаляет данные, а возвращает ошибку на команды записи (SET, LPUSH и т.д.). Команды чтения продолжают работать.

  2. LRU (Least Recently Used) — вытеснение давно неиспользуемых ключей:

    • allkeys-lru: Удаляет наименее используемый ключ из всех ключей.
    • volatile-lru: Удаляет наименее используемый ключ только среди тех, у которых установлен expire (TTL).
  3. LFU (Least Frequently Used) — вытеснение наименее часто используемых ключей:

    • allkeys-lfu: Удаляет ключ с наименьшим количеством обращений из всех ключей.
    • volatile-lfu: Удаляет ключ с наименьшим количеством обращений среди тех, у которых установлен expire.
  4. Другие политики:

    • allkeys-random: Удаляет случайный ключ из всех.
    • volatile-random: Удаляет случайный ключ из тех, у которых установлен expire.
    • volatile-ttl: Удаляет ключ с наименьшим оставшимся временем жизни (TTL) среди тех, у которых установлен expire.

Дополнительные стратегии управления памятью:

  • TTL (Time-To-Live): Проактивно устанавливать срок жизни для ключей, которые не нужно хранить вечно (EXPIRE, SETEX).
  • Шардирование (Sharding): Горизонтально масштабировать данные, распределяя их по нескольким инстансам Redis (например, с помощью Redis Cluster).
  • Сжатие данных: Хранить значения в сжатом виде (например, используя MessagePack или Protobuf вместо JSON), что уменьшает потребление памяти.
  • Оптимизация структур данных: Использовать более эффективные с точки зрения памяти структуры данных Redis, когда это возможно (например, Hashes, Lists, Sorted Sets вместо хранения больших JSON-объектов в строках).

Настройка политики выполняется в конфигурационном файле или через команду CONFIG SET:

# В файле redis.conf (рекомендуемый способ)
maxmemory 2gb
maxmemory-policy allkeys-lru

# Или в рантайме через redis-cli
CONFIG SET maxmemory "2gb"
CONFIG SET maxmemory-policy allkeys-lru

Ответ 18+ 🔞

Ага, слушай, вот сидишь ты такой, настраиваешь свой Redis, всё летает, всё пиздец как быстро. И тут — бац! — память кончилась. И что, думаешь, он тебе вежливо так скажет: «Извините, барин, места нет»? Да хуй там! Он начнёт выкидывать твои данные нахуй, как старые носки, по какому-то своему закону. А закон этот — политика вытеснения, maxmemory-policy. И если её не настроить, будет пиздец.

Ну, и какие у нас варианты, блядь?

  1. noeviction (дефолтная, она же «пошли все нахуй, я не убираюсь»). Redis просто перестаёт записывать что-либо новое и орёт тебе в ответ ошибку на каждую команду вроде SET. Читать-то можно, но писать — нет. Как будто квартира забита хламом, и ты уже не можешь новую тапку занести, пока старую не выкинешь. Но выкидывать он не хочет. Самодур, блядь.

  2. LRU (Least Recently Used) — «Кто давно не трогал — тот и лох».

    • allkeys-lru: Вышвыривает на мороз ключ, до которого дольше всех не доходили руки, из ВСЕХ ключей. Без разбора.
    • volatile-lru: То же самое, но только среди тех ключей, у которых есть срок годности (expire). То есть, которые ты сам пометил как временные. Остальные трогать не будет.
  3. LFU (Least Frequently Used) — «Кто редко звонит — тому и хуй, а не место».

    • allkeys-lfu: Выгоняет того, к кому реже всего обращались. Считает, блядь, обращения. Популярность-конкурс.
    • volatile-lfu: Аналогично, но только среди ключей с TTL.
  4. Прочие художества:

    • allkeys-random: Просто тыкает пальцем в небо и удаляет случайный ключ. Русская рулетка, ебать.
    • volatile-random: То же самое, но из временных.
    • volatile-ttl: Самый справедливый, на мой взгляд. Смотрит на ключи с установленным сроком и первым делом отправляет в утиль того, у кого этот срок вот-вот кончится. Типа «ты всё равно скоро сдохнешь, давай поможем».

А что ещё можно сделать, чтобы не доводить до ручки?

  • TTL (Time-To-Live): Не будь жадиной, ставь ключам срок жизни командой EXPIRE. Зачем тебе вечно хранить кэш сессии пользователя, который зашёл один раз в 2015 году? Самоуничтожится — и память свободна.
  • Шардирование: Если один инстанс не справляется — раскидай данные по нескольким. Redis Cluster тебе в помощь. Это как вместо одной огромной помойки завести несколько аккуратных мусорных баков.
  • Сжатие данных: Не пихай в него сырые JSON-ы размером с «Войну и мир». Сожми их чем-нибудь, типа MessagePack. Места в разы меньше займёт, ёпта.
  • Оптимизация структур: Не храни всё в простых строках (SET). Если данные структурированные — используй Hashes. Они жутко экономят память. Это как вместо того, чтобы каждый носк хранить в отдельной коробке, сложить все носки в один комод.

Ну и главное — как это всё включить. Конфиг файл — твой лучший друг, не ебнись с настройками в рантайме на проде.

# Пишешь в redis.conf и спишь спокойно
maxmemory 2gb
maxmemory-policy allkeys-lru

# Или, если совсем припёрло и надо прямо сейчас, через консоль
CONFIG SET maxmemory "2gb"
CONFIG SET maxmemory-policy allkeys-lru

А то без этого твой Redis превратится в ту самую собаку Муму, которую пришлось топить, потому что места не было. Только топить-то будет он твои же данные, блядь. Думай головой!