Модуль 4. Мониторинг Redis-очереди: метрики, SLOWLOG, Prometheus, алерты
Цель модуля: научиться видеть состояние Redis-очереди по приборам:
какие метрики INFO действительно важны для стримов, как поймать
деградацию памяти до OOM, как поднять redis-exporter с Prometheus
и какие алерты ставить — так, чтобы они не орали по пустякам.
Перед началом: Модули 1–3. Docker, базовое знакомство с Prometheus. Инструменты: стенд
boilerplate(make up-obs),oliver006/redis_exporter, Prometheus, Grafana (опционально). Трудоёмкость: ~8–10 ч (теория 4 ч · практика 4 ч · квиз 1 ч).
📖 4.1. Карта метрик: что смотреть для очереди
У Redis нет «одной метрики здоровья» — есть четыре группы, и для очереди важна каждая по-своему.
Память (INFO memory) — первая причина отказов Redis-очередей:
bashredis-cli INFO memory | grep -E "used_memory_human|used_memory_rss|maxmemory|maxmemory_policy|mem_fragmentation_ratio"
used_memoryvsmaxmemory— сколько осталось до eviction/OOM;mem_fragmentation_ratio(>1.5 — алерт): память, которую ОС не может вернуть аллокатору; типично после пиков больших записей;maxmemory_policy— для очереди должен бытьnoeviction: политики типаallkeys-lruначнут молча удалять ваш стрим, чтобы не умереть.
Ключи и eviction (INFO stats): evicted_keys, expired_keys.
evicted_keys > 0 при noeviction невозможны (записи начнут падать
с ошибкой), а при других политиках — красный флаг: кеш выдавливает данные.
Персистентность (INFO persistence):
bashredis-cli INFO persistence | grep -E "rdb_last_bgsave_status|aof_last_write_status|aof_last_bgrewrite_status"
Статус не ok — ваш «гарант» перестал работать; у очереди это дежурная
тревога: писать продолжаем, а переживём ли рестарт — уже вопрос.
Репликация (INFO replication): master_link_status:up у реплик,
master_last_io_seconds_ago (связь жива?), master_repl_offset и
replica_repl_offset — их разница и есть лаг в байтах.
Стримы — здесь Redis метрики не собирает: состояние очереди живёт
в XINFO:
bashredis-cli XINFO GROUPS orders # name consumers pending last-delivered-id lag # billing 3 12 1712345678901-0 4
lag (новое в Redis 7) — сколько записей ещё не доставлено группе;
pending — «займ» в руках консьюмеров. Но самое важное число XINFO не
отдаёт — возраст хвоста: насколько поздно вы обрабатываете:
bash# ID первой записи содержит unix-миллисекунды — возраст = now - ms(ID) redis-cli XRANGE orders - + COUNT 1
Скрипт-хелпер для экспорта stream_age — в практике.
📖 4.2. SLOWLOG: три команды, которые вы найдёте в нём первыми
bashredis-cli CONFIG SET slowlog-log-slower-than 10000 # порог в микросекундах (10 мс) redis-cli SLOWLOG GET 10
В очереди на Streams чаще всего ловятся:
KEYS/SCANс широким матчем — отладка, забытая в проде;XRANGE/XREADбез COUNT по выросшему стриму — чтение всей истории;XADDв раздувшийся стрим с MaxLen точным (без~) — точная обрезка при каждой записи дороже аппроксимации;- Lua-скрипт, ползающий по большому диапазону — воображаемый «атомарный дедуп», который латентностью валит весь Redis (одна блокирующая операция стопорит всех: Redis однопоточный).
Правило эксплуатации: slowlog-log-slower-than 10000 в проде включён
всегда, SLOWLOG RESET — после разбора (чтобы не привыкать к шуму).
📖 4.3. Поднимаем наблюдаемость: exporter + Prometheus
Специально для этого курса в стенде есть профиль наблюдаемости:
bashmake up-obs # Redis + redis_exporter (:9121) + Prometheus (:9090)
- redis-exporter конвертирует
INFO/XINFOв метрики Prometheus:redis_memory_used_bytes,redis_evicted_keys_total,redis_connected_clients,redis_replication_*, latency-гистограммы (redis_commands_duration_seconds_totalпри-include-system-metrics); - Prometheus скрейпит exporter каждые 15 с (
config/prometheus.yml).
Ключевые метрики в терминах Prometheus (запомните имена — с ними работают дашборды и алерты):
| Метрика | О чём | Порог-ориентир |
|---|---|---|
redis_memory_used_bytes / redis_memory_max_bytes | близость к лимиту | > 70 % — тревога, > 85 % — критика |
redis_mem_fragmentation_ratio | фрагментация | > 1.5 устойчиво |
redis_evicted_keys_total | выдавленные ключи | любое устойчивое увеличение |
redis_rdb_last_bgsave_status | снапшоты | != 1 |
redis_aof_last_write_status | AOF | != 1 |
redis_connected_clients | клиенты | резкий рост = утечка соединений |
redis_blocked_clients | ожидающие блокирующих операций | устойчиво > 0 при XREAD Block |
Для метрик очереди (stream lag/pending/age) exporter из коробки даёт
часть (redis_stream_* в новых версиях), остальное — своим tiny-exporter'ом:
скрипт из §4.1 отдаёт числа в формате Prometheus — в практике подключим его
как третий скрейп-таргет.
📖 4.4. Дашборд: восемь панелей, которых хватит
Минимальный операторский дашборд очереди (порядок панелей = порядок взгляда при инциденте):
- Throughput:
XADD-ы vsXACK-и в секунду (две кривые рядом — разрыв = растущий займ); - Stream age: возраст первой необработанной записи (секунды);
- Pending & lag по группам;
- Память: used/max + fragmentation;
- Evictions & expirations (должны быть нулевые);
- Latency: p50/p99 по командам (
redis_commands_duration_*); - Репликация: link status + лаг;
- Persist: rdb/aof status.
Совет из практики: панели 1–3 — «наша очередь», 4–8 — «наш Redis». При инциденте сначала смотрят 1–3 (проблема обработки), и только потом 4–8 (проблема сервера) — большинство «очередь встала» это первые три.
📖 4.5. Алерты: что ставить и где шуметь нельзя
Правило: алерт ставится на симптом для человека, а не на любую метрику для красоты. Для очереди на Redis работающая пятёрка:
| Алерт | Условие | Почему так |
|---|---|---|
| Stream age растёт | age > 60 с в течение 5 мин | Главный симптом: вы отстаёте по времени, а не по количеству |
| Pending не сбрасывается | pending той же группы > 1000 и не падает 10 мин | Воркеры держат, но не подтверждают: зависший/медленный обработчик |
| Память на подходе | used/max > 85 % 5 мин | До OOM/eviction остались считанные минуты |
| Evictions | rate > 0 5 мин при любой политике | Молчаливое выдавливание данных |
| Persist сломан | rdb/aof status != ok 10 мин | Работаем без страховки |
Анти-примеры (не ставить): «lag > 0» (это норма при живом трафике), «used_memory > 1 ГБ» (абсолютный порог без привязки к maxmemory), «rejected_connections > 0» (нормальный backpressure пула, пока не устойчиво).
💻 Практика
- Поднимите наблюдаемость:
make up-obs, проверьтеhttp://localhost:9090/targets— Redis-таргет должен бытьUP. - tiny-exporter очереди (±40 строк на Go/Python): читает
XINFO GROUPS orders+ первую записьXRANGE, считаетstream_age_seconds,stream_pending,stream_lag, отдаёт на/metrics(порт 9130), добавьте его вconfig/prometheus.ymlкак второй таргет. - Разгон и деградация: продюсер на 200 записей/с и воркер с
искусственной задержкой 200 мс (потолок ~5×200 мс/с); наблюдайте
в Prometheus (
rate()по счётчикам): age растёт, pending растёт. - Ложный и настоящий алерт: сформулируйте PromQL для пятёрки из
§4.5 (черновики — в
config/alerts.yml), проверьте, что «lag > 0» у вас в правилах отсутствует. - Сломайте персистентность: остановите/возобновите AOF-запись
(
CONFIG SET appendonly no, крупныйBGREWRITEAOF) — поймайте изменение статуса на дашборде. Убедитесь, что алерт звонит один раз, а не каждые 15 секунд (for:в правиле).
Артефакт: config/prometheus.yml + config/alerts.yml +
скриншот дашборда из Grafana (или Prometheus graph) с растущим age.
🧩 Quiz "Проверь себя"
✅ Итоги модуля
| Тема | Главное |
|---|---|
| Метрики | Четыре группы: память (noeviction!), stats, persist, репликация; очередь — через XINFO + возраст хвоста |
| SLOWLOG | Включён всегда (10 мс); топ-виновники — KEYS, широкие XRANGE, тяжёлый Lua |
| Стенд | redis_exporter + Prometheus (make up-obs) + tiny-exporter для метрик очереди |
| Дашборд | 8 панелей: throughput, age, pending — первыми; серверные — вторыми |
| Алерты | Пять симптомных алертов с for:; антипример «lag > 0» — не ставить |
🔗 Мостик к Модулю 5
Мы видим систему. Теперь — читаем её в момент боли: инциденты (big/hot keys, eviction под нагрузкой, OOM, лаг реплики, blocked clients): симптом → метрика → причина → лечение, каждый — воспроизводимый на стенде. А закроет курс модуль о том, когда Redis-очередь — осознанное решение, а когда — отложенный инцидент.