13-redis — Redis

☐ Опциональный. Быстрое хранилище «ключ-значение» в памяти: ставит Redis, привязывает его к localhost и защищает паролем.

Redis — сверхбыстрое хранилище данных в оперативной памяти (кэш, сессии, очереди, счётчики). Термины: bind — на каких сетевых адресах служба принимает подключения (localhost = только с этого же сервера); requirepass — пароль, который Redis требует у клиента перед выполнением команд; PING → PONG — простейшая проверка «жив ли сервер» (клиент шлёт PING, сервер отвечает PONG).

Зачем нужен

Redis держит данные в памяти и отдаёт их за микросекунды — идеален для кэша, пользовательских сессий, rate-limiting, лёгких очередей задач. Модуль ставит Redis из репозитория дистрибутива, сразу закрывает его на localhost и включает пароль, чтобы «из коробки» его нельзя было прочитать снаружи.

Когда включать и когда не нужен

Зависимости и требования

Что именно делает

Пошагово, функция module_install в modules/13-redis.sh:

  1. Самолечение dpkg. redis_repair_statoverride: если прошлое неудачное удаление оставило «висячую» запись dpkg-statoverride на пользователя redis, которого уже нет (это блокирует любые apt/dpkg-операции на всём сервере), пользователь пересоздаётся.
  2. Ставит пакет redis-server и делает резервную копию /etc/redis/redis.conf.
  3. Привязывает к localhost. Если REDIS_BIND не задан — по умолчанию bind 127.0.0.1; ::1 (IPv6-loopback) добавляется, только если он реально есть на интерфейсе lo. Причина осторожности — ниже.
  4. Ставит пароль (requirepass). Если пароль ещё не настроен — генерирует случайный, вписывает в конфиг и сохраняет в /root/.mitdev-credentials. Если пароль уже есть — не перетирает его (идемпотентность: повторный запуск не сбросит рабочий пароль).
  5. Настраивает systemd-таймауты (svc_set_timeouts) — убирает предупреждение Redis про TimeoutStartSec/TimeoutStopSec.
  6. Включает overcommit памяти (vm.overcommit_memory=1) — постоянно (файл /etc/sysctl.d/99-mitdev-redis.conf) и сразу.
  7. Включает и перезапускает службу. Если Redis не поднялся — печатает последние строки его лога и завершается с ошибкой.
  8. Проверяет PING → PONG (с паролем, если только что его задал). Нет ответа — установка неуспешна.

Файлы, службы и порты

Путь / юнит / порт Назначение Права / примечание
Служба redis-server (Debian) / redis (RHEL и др.) systemd-юнит Redis mitdev redis status
Порт 6379/tcp приём подключений по умолчанию только 127.0.0.1
/etc/redis/redis.conf конфигурация (bind, requirepass) правится модулем, есть .mitdev-bak.*
/var/lib/redis/ данные (dump.rdb) владелец redis
/var/log/redis/redis-server.log (Debian) лог сервера смотреть при сбое запуска
/etc/sysctl.d/99-mitdev-redis.conf vm.overcommit_memory=1 системный параметр
/root/.mitdev-credentials пароль (requirepass) 0600, только root

Учётные данные

Пароль Redis (requirepass) хранится в /root/.mitdev-credentials (0600, только root). Посмотреть:

sudo grep '^redis:' /root/.mitdev-credentials

Пример:

redis: password=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6

Если при установке пароль не был настроен, mitdev сгенерировал случайный и записал его сюда же. Если Redis был установлен ранее и уже имел requirepass, mitdev его не менял — актуальный пароль ищите в самом /etc/redis/redis.conf (строка requirepass …).

Настройка

Переменная Значения По умолчанию Влияние Когда менять
REDIS_BIND список адресов через пробел, например 127.0.0.1 пусто (автоопределение) на каких адресах Redis слушает почти никогда вручную — см. предупреждение ниже

Почему REDIS_BIND пуст по умолчанию. При пустом значении модуль сам подставляет 127.0.0.1 и добавляет ::1 только когда IPv6-loopback реально присутствует. Это сделано специально: синтаксис необязательной привязки -::1 понимают только Redis 6.2+/7, а на Ubuntu 22.04 идёт Redis 6.0.x, который на нём падает с exit(1) («Cannot assign requested address»), если ::1 нет на хосте. Поэтому не прописывайте ::1 руками, если не уверены в версии Redis — доверьте автоопределению.

Как переопределить настройки

Как подключиться

Из приложения на этом же сервере — строка подключения через localhost с паролем:

redis://:<password>@127.0.0.1:6379

Например в .env:

REDIS_URL=redis://:[email protected]:6379

(двоеточие перед паролем не опечатка — у Redis по умолчанию нет имени пользователя, только пароль).

Из командной строки (redis-cli):

redis-cli -a 'ПАРОЛЬ' ping                 # ожидаемо: PONG
redis-cli -a 'ПАРОЛЬ' --no-auth-warning info server

Флаг --no-auth-warning убирает предупреждение о пароле в аргументах.

С другого сервера — БЕЗОПАСНО. По умолчанию 6379 доступен только локально, и это правильно: Redis без TLS нельзя выставлять в интернет. Правильный путь — приватная сеть:

  1. Соберите mesh-сеть: mitdev net create / join (см. MESH.md).
  2. Привяжите Redis к приватному интерфейсу: sudo mitdev net bind redis private — служба будет слушать приватный IP + 127.0.0.1, но не публичный.
  3. Приложение с соседнего сервера подключается по приватному IP с тем же паролем.

Никогда не делайте bind 0.0.0.0 на публичном сервере — это открывает Redis всему интернету.

Проверка, что всё работает

Проверка модуля (module_verify): служба активна. Вручную:

mitdev redis status

Ожидаемо: блок Redis с role:master; если Sentinel не настроен — строка «redis-sentinel не запущен» (это нормально для одиночного Redis).

redis-cli -a "$(sudo grep '^redis: password' /root/.mitdev-credentials | cut -d= -f2)" ping

Ожидаемо: PONG.

mitdev doctor --deep

В функциональных пробах: Redis — PONG.

Типовые задачи

Записать и прочитать ключ:

redis-cli -a 'ПАРОЛЬ' --no-auth-warning set greeting "hello"
redis-cli -a 'ПАРОЛЬ' --no-auth-warning get greeting        # → "hello"

Сменить пароль Redis:

sudo sed -i -E 's/^\s*requirepass .*/requirepass НОВЫЙ-ПАРОЛЬ/' /etc/redis/redis.conf
sudo systemctl restart redis-server

Затем обновите пароль в .env приложения и в /root/.mitdev-credentials.

Очистить кэш (удалить все ключи текущей БД / всех БД):

redis-cli -a 'ПАРОЛЬ' --no-auth-warning flushdb     # только текущая логическая БД
redis-cli -a 'ПАРОЛЬ' --no-auth-warning flushall    # все базы Redis

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

redis-cli -a 'ПАРОЛЬ' --no-auth-warning info clients
redis-cli -a 'ПАРОЛЬ' --no-auth-warning client list

Использование памяти и статистика попаданий в кэш:

redis-cli -a 'ПАРОЛЬ' --no-auth-warning info memory
redis-cli -a 'ПАРОЛЬ' --no-auth-warning info stats | grep keyspace

Резервная копия данных (снимок dump.rdb):

redis-cli -a 'ПАРОЛЬ' --no-auth-warning save
sudo cp /var/lib/redis/dump.rdb /root/redis-$(date +%F).rdb

Общий бэкап сервера (mitdev backup) тоже включает dump.rdb.

Сколько всего ключей:

redis-cli -a 'ПАРОЛЬ' --no-auth-warning dbsize

Масштабирование и отказоустойчивость

Одиночный Redis — точка отказа. Для HA mitdev использует Redis Sentinel (набор процессов-наблюдателей, которые следят за master, выбирают нового при отказе и сообщают клиентам актуальный адрес):

Обязательное условие: все узлы видят друг друга на 6379

Sentinel находит реплики, разбирая INFO на master, и сам ходит к каждой из них на 6379. Если узел не может достучаться до соседа на этом порту, он объявляет его недоступным (+sdown) — даже когда сосед жив. Sentinel'ы расходятся во мнении, кто master, и начинают перевыбирать его друг против друга. В журнале это выглядит как непрерывная череда +switch-master и +failover-end-for-timeout, а в кластере оказывается два master сразу.

Поэтому 6379 и 26379 должны быть открыты между всеми узлами в обе стороны — в UFW и в файрволе провайдера. cluster-init и join делают это для известных им узлов; для добавленных позже выполните sudo mitdev redis allow <ip> на каждом узле. После сборки обязательно прогоните на всех узлах:

sudo mitdev redis check

Пока эта проверка не проходит везде, авто-failover работать не будет. Приватная сеть (mitdev net) не обязательна, но желательна: она избавляет от необходимости открывать порты в публичный интернет.

Подробности — COMMANDS.md (раздел «Отказоустойчивый Redis») и HA.md.

Частые ошибки

Симптом: NOAUTH Authentication required при обращении к Redis. Причина: не передан пароль. Решение: используйте redis-cli -a 'ПАРОЛЬ' или укажите пароль в строке подключения приложения.

Симптом: Redis не стартует, в логе Cannot assign requested address. Причина: в bind прописан ::1, а IPv6-loopback на хосте отсутствует (частая беда Redis 6.0.x на Ubuntu 22.04). Решение: уберите ::1 из строки bind в /etc/redis/redis.conf, оставьте bind 127.0.0.1, перезапустите; не задавайте REDIS_BIND вручную с ::1.

Симптом: предупреждение overcommit_memory is set to 0 и падающие фоновые сохранения. Причина: параметр ядра не применился. Решение: sudo sysctl -w vm.overcommit_memory=1 (модуль обычно ставит это сам через /etc/sysctl.d/99-mitdev-redis.conf).

Симптом: любые apt/dpkg на сервере падают с «unknown system user 'redis' in statoverride file». Причина: висячая запись dpkg-statoverride после неудачного удаления. Решение: повторный запуск модуля Redis лечит это автоматически (redis_repair_statoverride); либо вручную пересоздайте пользователя redis.

Симптом: приложение с соседнего сервера не видит Redis. Причина: Redis слушает только localhost. Решение: соберите приватную сеть и выполните sudo mitdev net bind redis private — не открывайте порт наружу.

Симптом: после отказа одного сервера мастер меняется каждые несколько секунд; в journalctl -u redis-sentinel бесконечная череда +switch-master и +failover-end-for-timeout; два узла одновременно в роли master. Причина: узлы не видят друг друга на 6379, поэтому каждый Sentinel объявляет чужого мастера мёртвым и повышает своего. Решение: остановите Sentinel на всех узлах (sudo systemctl stop redis-sentinel), откройте 6379/26379 между узлами, добейтесь, чтобы sudo mitdev redis check проходил везде, затем соберите кластер заново: mitdev redis token на уцелевшем мастере и mitdev redis join <токен> на остальных.

Симптом: mitdev redis status пишет «РАСХОЖДЕНИЕ: локальный redis — master, а Sentinel считает мастером …». Причина: узел не переключился в реплику после failover и живёт отдельным мастером (split-brain). Решение: снимите с него дамп (redis-cli -a <пароль> --rdb /root/backup.rdb), затем mitdev redis join <токен> с действующего мастера — данные узла будут затёрты полной синхронизацией.

Откат и удаление

См. также