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 за пределами кэша: очереди, блокировки, счётчики