Valkey — открытый форк Redis, который развивается независимо, но сохраняет совместимость команд. В повседневной работе команды у valkey-cli и redis-cli одинаковые, поэтому материал подходит для обоих. Ниже — практическая схема кэширования, настройки памяти и персистентности для сервиса, который не должен терять данные при штатном перезапуске.
Что кэшировать и где проходит граница
Кэш не является источником истины. В базе остаются данные, а в памяти — их копия с TTL. Классическая схема cache-aside: приложение читает ключ, при промахе идёт в базу, записывает результат с временем жизни и возвращает ответ. При изменении данных сначала коммитим транзакцию в базу, затем удаляем ключ, а не обновляем его вслепую. Ключи делайте предсказуемыми: user:42:profile или report:2026-10:42, чтобы их можно было найти и инвалидировать.
valkey-cli SET user:42:profile '{"name":"Anna"}' EX 900 NX
valkey-cli GET user:42:profile
valkey-cli TTL user:42:profile
NX здесь защищает от гонки: если ключ уже записан другим процессом, значение не перезапишется. TTL в 15 минут — не догма: для профиля он может быть час, для счётчика на странице — 30 секунд. Добавляйте случайный разброс в несколько секунд, чтобы множество ключей не истекало одновременно и не устраивало лавину запросов в базу.
Память и политика вытеснения
Без maxmemory процесс однажды займёт всю доступную память. Для чистого кэша ставьте allkeys-lru: тогда при переполнении вытесняются давно не использованные ключи. Если в той же базе лежат очереди или сессии, которые нельзя терять, используйте volatile-lru — он удаляет только ключи с TTL, а при отсутствии таких начинает возвращать ошибки записи. noeviction подходит для данных, которые обязаны сохраниться, но требует внешнего контроля заполнения.
valkey-cli CONFIG SET maxmemory 512mb
valkey-cli CONFIG SET maxmemory-policy allkeys-lru
valkey-cli CONFIG REWRITE
valkey-cli INFO memory
CONFIG SET меняет значение до перезапуска, CONFIG REWRITE сохраняет его в конфигурационный файл. В INFO memory смотрите used_memory_human, maxmemory, mem_fragmentation_ratio и evicted_keys. Фрагментация выше 1.5 при стабильной нагрузке — повод проверить характер записи; evicted_keys, растущий постоянно, означает, что памяти мало или TTL слишком велик. Команду KEYS в продакшене не используйте: она блокирует обработку на время обхода всех ключей.
Лавина запросов и прогрев
Когда популярный ключ истекает, десятки процессов одновременно идут в базу. Простое решение — короткая блокировка через SET NX: один процесс обновляет значение, остальные на мгновение ждут или отдают старое. Не храните блокировку без TTL: упавший процесс оставит её навсегда. Снимать её нужно только при совпадении уникального токена, иначе можно удалить чужую.
valkey-cli SET lock:report:42 1 NX EX 10
valkey-cli DEL lock:report:42
После перезапуска пустой кэш также создаёт нагрузку. Прогревайте самые важные ключи фоновым заданием с ограничением параллелизма, а не по первому запросу пользователя. TTL для прогретых ключей задавайте с разбросом, чтобы они не истекли одновременно.
Персистентность: RDB и AOF
RDB — снимок базы целиком. Он компактен и быстро восстанавливается, но между снимками данные теряются. AOF пишет журнал операций и позволяет сократить окно потери до одной секунды при appendfsync everysec. Гибридный режим с aof-use-rdb-preamble yes ускоряет загрузку: в начало AOF пишется RDB-снимок, дальше идут команды. Для кэша часто достаточно RDB, для очередей и важных состояний нужен AOF.
valkey-cli CONFIG SET save "900 1 300 10"
valkey-cli CONFIG SET appendonly yes
valkey-cli BGREWRITEAOF
valkey-cli INFO persistence
Сохранение через fork требует памяти под copy-on-write: при активной записи процесс может временно занять больше maxmemory. Если в логах появляются ошибки bgsave, проверьте свободную память и stop-writes-on-bgsave-error. Для резервной копии делайте BGSAVE, дожидайтесь rdb_bgsave_in_progress: 0 и копируйте dump.rdb на другой носитель. Проверить целостность можно утилитой valkey-check-rdb. Реплика — не бэкап: удаление ключа повторится и на ней.
Репликация и окно потери
Реплика подключается командой REPLICAOF и получает поток изменений. WAIT подтверждает, что указанное число реплик приняло запись, но не делает систему строго консистентной. Параметры min-replicas-to-write и min-replicas-max-lag заставляют мастер отказать в записи, если живых реплик слишком мало. Это защита от потери данных при аварии, но она снижает доступность — выбирайте осознанно.
valkey-cli REPLICAOF 10.0.0.12 6379
valkey-cli WAIT 1 100
valkey-cli INFO replication
Автоматическое переключение требует Sentinel или кластерного режима; ручной REPLICAOF NO ONE на старой реплике без проверки состояния чреват разделением данных. Для небольшого проекта проще поднять Sentinel из трёх узлов, чем писать собственный скрипт аварийного переключения.
Диагностика и безопасность
Медленные команды ищите через SLOWLOG, общую картину — через LATENCY DOCTOR. Утилита valkey-cli —bigkeys показывает крупные ключи, а —scan обходит пространство без блокировки. Один большой список или хеш может стать причиной задержек: операции над ним выполняются в единственном потоке. Дробите такие структуры на части и используйте UNLINK вместо DEL для больших объектов.
valkey-cli SLOWLOG GET 10
valkey-cli --bigkeys
valkey-cli --scan --pattern 'user:*'
valkey-cli INFO stats
Для общей картины смотрите INFO keyspace: количество ключей и средний TTL по базам. Резкий рост числа ключей без роста трафика обычно означает, что где-то забыли TTL или неправильно формируют имена.
По умолчанию сервис должен слушать только localhost: bind 127.0.0.1 ::1, protected-mode yes. Если доступ нужен по сети, ограничьте его файрволом и заведите отдельного пользователя через ACL с минимальными правами. Пароль в конфигурации — не замена сетевой изоляции. Порт 6379, открытый в интернет, находят сканеры за считанные часы.
Чек-лист
- У каждого ключа есть TTL и понятное имя.
- Задан maxmemory и политика вытеснения под характер данных.
- Выбран режим персистентности и известно окно потери.
- BGSAVE проверен, dump.rdb копируется на другой сервер.
- Настроены ACL, bind и файрвол.
- SLOWLOG и bigkeys просматриваются регулярно.
Итог
Valkey и Redis дают простой инструмент, но требуют дисциплины: TTL, лимит памяти и понятная политика вытеснения важнее экзотических команд. Персистентность выбирайте по допустимому окну потери, а не по принципу «включить всё». Реплика помогает пережить отказ узла, но не заменяет резервную копию. И проверяйте поведение на реальной нагрузке: кэш, который экономит миллисекунды на чтении, легко превращается в источник задержек при неудачной схеме ключей.