Files

14 KiB
Raw Permalink Blame History

arch-09. Контракт Redis

Канонический контракт Redis для всех application VM.
Реализация на конкретной VM — module-04-redis-vm1.md и module-04-redis-vm2.md.
Compose/сети — arch-03-docker-compose-blueprint.md. Env — arch-04-settings-and-content.md. Метрики exporter — arch-07-observability.md.

Назначение

Документ фиксирует то, что должно совпасть между ВМ1 и ВМ2: Redis не source of truth, формат ключей, TTL, Lua governance, AOF/RDB, ACL/network, eviction и restore. Карты ключей DB0/DB1 и Redis Safety здесь не детализируются и не копируются в чужой репозиторий.

Этот контракт нельзя независимо кастомизировать так, чтобы Redis стал очередью, OTP store или единственной защитой от дублей.

1. Инварианты

Redis разделён по deployment/security boundary:

  • Redis ВМ1: DB0 (api-backend idempotency/rate) и DB1 (realtime/coordination);
  • Redis Safety ВМ2: отдельный instance для hot cache, rate limiting и optional worker wake-up;
  • legacy DB2 ВМ1 существует только для test stub v1 до cutover и после него удаляется.

Redis не является бизнес-очередью, source of truth сообщений, sync tasks, audit, профилей или delivery checkpoint. Надёжные состояния остаются в managed PostgreSQL/S3. Потеря Redis может ухудшить сервис, но не должна создавать потерю подтверждённых сообщений либо дубль side effect.

OTP counters api-backend в Redis не хранит; они принадлежат Keycloak/SPI. bitrix-sync Redis не использует: sync_queue, leases и durable wake-up — PostgreSQL.

Logical DB — изоляция имён, не security boundary. ACL prefix и разные credentials обязательны.

2. Версия и topology

Redis 7.x, image закреплён по digest. На каждой VM одна нужная primary instance без replica/Sentinel в MVP. Клиенты используют connection pool, bounded timeouts и не выполняют опасные команды.

ВМ2 никогда не использует hostname Redis ВМ1 и наоборот.

3. Общие правила ключей

Формат: han:{domain}:{purpose}:{hashed-or-public-id}:{version}. Только ASCII lowercase separators. Public UUID допустим; IP, phone, email, token, text и filename — только HMAC/SHA-256 с server-side pepper там, где нужна защита dictionary attack.

  • key length желательно ≤ 200 bytes;
  • значения versioned (v=1);
  • timestamps — Unix ms/seconds или RFC3339, формат фиксирован для каждого key;
  • wildcard KEYS production запрещён; только SCAN для ops;
  • каждый non-channel key имеет TTL, кроме явно обоснованных bounded structures;
  • large payload/presigned URL/token/message text запрещены.

Новый key без TTL запрещён contract test, кроме Pub/Sub channel (не key) и ops metadata с явным обоснованием.

4. Serialization и limits

  • простые counters — integer;
  • locks — opaque random 128-bit token;
  • metadata — Redis HASH либо компактный JSON с schema_version;
  • max value target 32 KiB, hard application guard 128 KiB;
  • response cache хранит только allow-listed sanitized JSON;
  • decode error считается cache miss, key удаляется/карантинируется и поднимается metric.

5. TTL policy — реестр

Категория TTL Владелец
idempotency completed 24h по arch-02 ВМ1
idempotency in-progress lock 30s, heartbeat bounded ВМ1
rate limit window + 1030% deterministic jitter ВМ1 / ВМ2 по своим зонам
realtime connection 90s; set membership 120s ВМ1
coordination lock 30s ВМ1
safety file hot cache ≤30d; authoritative row/version в PostgreSQL ВМ2
safety text-rules cache 48h; invalidation by rules version ВМ2
safety stable link policy cache 48h ВМ2
safety DNS cache actual DNS TTL, hard max 900s ВМ2

6. Atomicity и Lua governance

Scripts/functions хранятся в репозитории рядом с клиентом, versioned и тестируются на real Redis. Запрещены unbounded loops/SCAN внутри Lua. Входные массивы ограничены. Script timeout отслеживается; SCRIPT KILL runbook применяется только если нет writes либо после оценки.

Clock в rate/limit scripts — Redis TIME, не client wall clock. Script загружается при startup, SHA кэшируется; после NOSCRIPT выполняется контролируемый reload.

Redis transaction не координирует PostgreSQL/S3/HTTP. Cross-system consistency обеспечивается DB checkpoint/outbox и idempotent finalize.

Карта обязательных scripts — в спецификации VM.

7. Persistence

Решение MVP: AOF appendonly yes, appendfsync everysec плюс RDB snapshots (save 900 1, 300 100, 60 10000 либо tuned). Это ускоряет восстановление ephemeral state, но не превращает Redis в authoritative store.

aof-use-rdb-preamble yes, automatic rewrite с порогами; volume redis-data. При corruption используется redis-check-aof/restore clean instance, а сервисы восстанавливают authoritative state из PostgreSQL.

RPO Redis до ~1 секунды приемлем, потому что бизнес-RPO задаётся PostgreSQL/S3. Backup Redis не обязателен для бизнес-восстановления, но периодическая копия RDB/AOF полезна для ops forensic без secrets.

8. Memory и eviction

maxmemory задаётся относительно container limit (ориентир 7075%, оставляя overhead/fork). Начальная оценка для одной VM — 512 MiB, уточняется load test.

Eviction MVP: volatile-lru/volatile-ttl, так как все application keys имеют TTL. allkeys-lru опасен для idempotency при memory pressure; noeviction может полностью закрыть writes. Окончательный выбор после нагрузки: предпочтительно volatile-lru + alerts, а при разделении instances DB0 idempotency получает отдельную noeviction policy.

Контролируются used_memory, RSS, fragmentation, evicted_keys, expired_keys, key count/avg TTL по DB. OOM/eviction не должен создавать дубль бизнес-эффекта: это гарантирует PostgreSQL fallback, не Redis.

9. Sizing

Общая формула:

instance working set × 1.5 allocator/fragmentation × 1.3 growth reserve

Состав working set считает спецификация VM. Pub/Sub output buffers и slow consumers имеют hard/soft limits. Load test фиксирует peak RPS, connections, record size и AOF rewrite headroom.

10. Auth, ACL и network boundary

Оба Redis не публикуют 6379 на host и подключены только к local Docker backend своей VM. protected-mode yes, default user отключён.

ACL users (имена общие, credentials разные на каждой VM):

  • application user — только свои key prefixes и command categories;
  • ops_health: PING, ограниченный INFO;
  • redis_exporter — только INFO/PING и безопасные latency/keyspace metrics (arch-07 §8.3).

Redis ACL не ограничивает logical DB напрямую надёжно; key-prefix patterns и разные credentials обязательны. SELECT запрещается, клиент URL сразу задаёт DB, но ACL prefix остаётся основной защитой.

Dangerous/admin commands (FLUSHALL, FLUSHDB, CONFIG, MODULE, broad KEYS, replication changes) запрещены application users; rename-command не считается основной защитой.

Пароли сильные, только env/secret mount, rotation current/new через rolling deploy. Внутри одной VM TLS Redis опционален при закрытой Docker network; при выносе за host/VPC TLS обязателен (rediss://) и plaintext отключается.

11. Docker/runtime

redis/
  docker-compose.yml
  redis.conf
  users.acl.template
  scripts/
  tests/

Compose: pinned Redis image, expose: 6379, без ports, backend network, redis-data:/data, config/ACL read-only, non-root UID, no-new-privileges, dropped capabilities, resource/memory/ulimit settings.

Startup валидирует config и ACL, permissions volume, затем Redis. Healthcheck использует ACL health user и redis-cli --no-auth-warning PING, secret не печатается. Graceful stop timeout позволяет AOF flush.

Credential URL не входит в общий публичный .env как секрет: secret file / arch-06.

12. Health — общие правила

PING проверяет liveness Redis; readiness приложений проверяет auth, correct DB и выполнение малого read/write/expire script без оставления key.

При latency выше threshold clients используют short timeout/circuit, не создают бесконечные retry storms. Reconnect — exponential backoff+jitter.

Degraded policy конкретного сервиса — спецификация VM.

13. Backup и restore

Redis backup не используется для бизнес restore. Runbook:

  1. остановить/изолировать corrupted instance;
  2. при целостном AOF/RDB восстановить на отдельном instance и проверить;
  3. иначе поднять пустой Redis;
  4. приложения прогревают ephemeral state из PostgreSQL / reconnect;
  5. не копировать Redis dump в небезопасное место: keys содержат UUID и hashed identifiers.

Детали прогрева — спецификация VM.

14. Metrics и alerts — общие

  • availability, commands/sec, latency percentiles;
  • connected/blocked clients, rejected connections;
  • memory/RSS/fragmentation, maxmemory ratio;
  • evictions/expirations/keyspace hits/misses;
  • AOF fsync latency/rewrite status/last save;
  • replication metrics зарезервированы;
  • key count/avg TTL по DB без key values;
  • script errors/NOSCRIPT/slowlog;
  • Pub/Sub subscribers/output buffer/slow disconnect.

Alerts: unavailable, p99 latency, >80/90% memory, any sustained evictions, AOF error, no recent persistence, client buffer pressure, unexpected keys without TTL.

Бизнес-метрики rate/idempotency/Safety cache — спецификация VM и arch-07. Keys/values не экспортируются.

15. Общий Definition of Done

  • Lua scripts atomic, bounded, versioned и покрыты real Redis tests;
  • AOF/RDB, volume, restart и clean-instance recovery проверены;
  • maxmemory/eviction/resource limits основаны на load test либо явно TBD;
  • ACL users и network isolation работают, порт не published;
  • все application keys имеют TTL;
  • logs/metrics не содержат secret/value/PII;
  • Redis не используется как sync_queue, delivery queue, message/audit source of truth или OTP store.

Профильный DoD VM дополняет свои prefixes, URL и degraded policy.

16. Решения, допущения и TBD

Решения: по одной primary instance на каждую VM без replica/Sentinel в MVP; AOF everysec + RDB; Pub/Sub best effort; PostgreSQL durable fallback; prefix ACL; все application keys с TTL. Историческая схема «один instance / три DB» заменена разделением ВМ1 DB0/DB1 и Redis Safety ВМ2.

Допущения: Redis loss допустим без потери business truth; bitrix-sync Redis не использует.

TBD:

  • R1: точный maxmemory после load profile — по VM.
  • R2: eviction policy после измерений.
  • R3: credential env names в arch-04.
  • R5: TLS при изменении network topology.
  • R6: момент разделения DB на instances — спецификация ВМ1.
  • R7: RPO/RTO ops target.
  • R4: Safety task TTL/recovery margin — спецификация ВМ2 (PostgreSQL, не Redis).

17. Ссылки