← назад к разделу

Redis — это хранилище в оперативной памяти. Казалось бы, процесс упал — данные пропали. На самом деле Redis умеет сохраняться на диск, выдерживать отказ сервера и масштабироваться на несколько машин. В этой статье разбираем, как это работает и как выбрать нужные настройки.

Персистентность: RDB и AOF

По умолчанию Redis хранит данные только в памяти. Если сервер перезапустится — всё пропадёт. Чтобы этого не было, есть два механизма сохранения.

RDB (Redis Database) — это снапшот: Redis делает полный «снимок» данных на диск в двоичном формате (dump.rdb). Снапшот можно делать по расписанию или вручную командой SAVE / BGSAVE. BGSAVE запускает дочерний процесс и не блокирует Redis.

# Сохранить снапшот вручную (асинхронно, не блокирует)
BGSAVE

# Посмотреть, когда было последнее сохранение
LASTSAVE

Конфигурация в redis.conf:

# Сохранять снапшот если за 60 секунд изменилось хотя бы 1000 ключей
save 60 1000
# Файл снапшота
dbfilename dump.rdb
dir /var/lib/redis

Плюс RDB: компактный файл, быстрый старт после перезапуска. Минус: если сервер упал между снапшотами — данные за этот промежуток теряются.

AOF (Append Only File) — это журнал команд: каждая команда записи дописывается в файл (appendonly.aof). При рестарте Redis просто «воспроизводит» весь файл заново.

# Включить AOF
appendonly yes
appendfilename "appendonly.aof"

# Политика fsync (сброс на диск):
# always  — после каждой команды (максимальная надёжность, медленнее)
# everysec — раз в секунду (хороший баланс, потеря максимум 1 с данных)
# no      — ОС решает сама (быстро, ненадёжно)
appendfsync everysec

Плюс AOF: теряете максимум одну секунду данных. Минус: файл растёт, старт медленнее. Redis умеет периодически «сжимать» AOF (BGREWRITEAOF), убирая лишние команды.

Короткая формула: для важных данных включайте и RDB, и AOF одновременно — Redis умеет работать с обоими. При старте приоритет у AOF.

Память и политики вытеснения

Redis живёт в RAM, значит нужно задать лимит — иначе он съест всю оперативную память сервера.

# Лимит памяти (например, 512 мегабайт)
maxmemory 512mb

# Что делать когда лимит достигнут — политика вытеснения
maxmemory-policy allkeys-lru

Политики вытеснения — что Redis делает, когда памяти не осталось:

ПолитикаПоведение
noevictionОтказывать в записи ошибкой (данные не трогает)
allkeys-lruВытеснять любые ключи по принципу «давно не использовался»
volatile-lruВытеснять только ключи с TTL, по LRU
allkeys-randomВытеснять любые ключи случайно
volatile-ttlВытеснять ключи с наименьшим оставшимся TTL
volatile-randomВытеснять ключи с TTL случайно

Когда что выбирать:

  • Redis как кэш (данные можно потерять) → allkeys-lru. Самый распространённый выбор.
  • Redis как кэш, но только часть ключей с TTL → volatile-lru.
  • Redis как основное хранилище (нельзя терять данные) → noeviction плюс контроль памяти со стороны приложения.

В Spring Boot при использовании @Cacheable политика allkeys-lru работает прозрачно: Spring не знает о вытеснении, просто при следующем обращении к отсутствующему ключу снова вычислит значение.

Репликация: primary и replica

Репликация позволяет держать несколько копий данных на разных серверах. Один сервер — primary (принимает записи), остальные — replica (только чтение, синхронизируются с primary).

# На replica в redis.conf (или в CLI):
REPLICAOF 192.168.1.10 6379

Replica постоянно получает поток изменений от primary. При первом подключении primary делает BGSAVE и отправляет снапшот, затем передаёт накопленные команды — так replica догоняет актуальное состояние.

Что даёт репликация:

  • Горизонтальное масштабирование чтения — приложение читает с replica, снижая нагрузку на primary.
  • Резервная копия — если primary упадёт, replica хранит данные.

Само по себе replica не переключается в режим primary при сбое — для этого нужен Sentinel.

Sentinel: отказоустойчивость

Redis Sentinel — это набор процессов-наблюдателей, которые следят за primary и replica. Если primary стал недоступен, Sentinel голосованием выбирает новый primary из replica и оповещает приложения.

# sentinel.conf — минимальная конфигурация
sentinel monitor mymaster 192.168.1.10 6379 2
# «mymaster» — имя кластера
# 2 — кворум: сколько Sentinel должны согласиться, что primary недоступен
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000

Типичная схема: 3 узла Sentinel (нечётное число для кворума), 1 primary, 1-2 replica. Приложение подключается к Sentinel, тот сообщает актуальный адрес primary.

В Spring Boot Sentinel настраивается через application.yml:

spring:
  data:
    redis:
      sentinel:
        master: mymaster
        nodes:
          - sentinel1:26379
          - sentinel2:26379
          - sentinel3:26379

Cluster: шардирование

Redis Cluster нужен когда данных слишком много для одного сервера или нагрузка на запись слишком высокая. Cluster автоматически распределяет ключи по нескольким primary-узлам — это и есть шардирование.

Cluster делит пространство ключей на 16384 хэш-слота. Каждый primary отвечает за диапазон слотов. Ключ user:42 хешируется в конкретный слот, и Redis знает, какой узел хранит этот слот.

# Минимальный кластер: 3 primary + 3 replica (6 узлов)
# Запуск через redis-cli:
redis-cli --cluster create \
  192.168.1.10:6379 192.168.1.11:6379 192.168.1.12:6379 \
  192.168.1.13:6379 192.168.1.14:6379 192.168.1.15:6379 \
  --cluster-replicas 1

В Spring Boot кластер настраивается аналогично Sentinel:

spring:
  data:
    redis:
      cluster:
        nodes:
          - 192.168.1.10:6379
          - 192.168.1.11:6379
          - 192.168.1.12:6379

Lettuce (драйвер по умолчанию в Spring Data Redis) умеет работать с кластером прозрачно: сам перенаправляет запросы на нужный узел.

Когда что выбирать:

  • Один сервер, перезапуски некритичны → без репликации, только RDB.
  • Нужна отказоустойчивость → Sentinel (primary + replica).
  • Данные не помещаются на один сервер → Cluster.

Мониторинг и типичные проблемы

Команда INFO

INFO возвращает подробную статистику о состоянии сервера:

# Общая информация
INFO

# Только раздел памяти
INFO memory

# Только статистика репликации
INFO replication

Ключевые метрики для мониторинга:

  • used_memory — сколько памяти занято
  • connected_clients — число подключений
  • keyspace_hits / keyspace_misses — попадания и промахи кэша
  • rdb_last_bgsave_status — статус последнего снапшота
  • role — primary или replica

Медленные команды

Redis ведёт журнал медленных команд. Команда KEYS * — классический пример блокирующей операции: она перебирает все ключи и блокирует сервер на время выполнения. Вместо неё используйте SCAN.

# Настроить порог в redis.conf (в микросекундах, 10000 = 10 мс)
slowlog-log-slower-than 10000
slowlog-max-len 128

# Посмотреть медленные команды
SLOWLOG GET 10

# Итерировать ключи без блокировки (вместо KEYS)
SCAN 0 MATCH user:* COUNT 100

Большие ключи

Хранение огромного значения в одном ключе (например, список из миллиона элементов) — распространённая проблема. Такой ключ:

  • долго сериализуется при сохранении в RDB/AOF;
  • блокирует сервер при операциях вроде DEL (удаление большого списка — синхронная операция).

Для удаления больших ключей используйте UNLINK вместо DEL — он выполняет удаление асинхронно в фоне.

# Найти большие ключи (встроенный сканер)
redis-cli --bigkeys

# Асинхронное удаление большого ключа
UNLINK huge_list_key

Коротко

  • RDB — снапшот на диск, быстрый старт, возможна потеря данных между снапшотами.
  • AOF — журнал команд, теряете максимум секунду, файл нужно периодически перезаписывать.
  • maxmemory + allkeys-lru — стандартный выбор для Redis-кэша.
  • noeviction — для хранилища, где данные нельзя терять.
  • Репликация даёт резервную копию и масштабирование чтения; Sentinel добавляет автоматическое переключение при сбое.
  • Cluster нужен при нехватке памяти или записи на одном узле.
  • KEYS * блокирует сервер — используйте SCAN; DEL большого ключа тоже блокирует — используйте UNLINK.

Что почитать дальше

  • Основы Redis: структуры данных и модель работы
  • Redis в Spring Boot: кэширование и RedisTemplate
  • Redis за пределами кэша: очереди, блокировки, счётчики