# arch-09. Контракт Redis > Канонический контракт Redis для всех application VM. > Реализация на конкретной VM — [`module-04-redis-vm1.md`](../VM1_app/documentation/module-04-redis-vm1.md) и [`module-04-redis-vm2.md`](../VM2_services/documentation/module-04-redis-vm2.md). > Compose/сети — [`arch-03-docker-compose-blueprint.md`](arch-03-docker-compose-blueprint.md). Env — [`arch-04-settings-and-content.md`](arch-04-settings-and-content.md). Метрики exporter — [`arch-07-observability.md`](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 + 10–30% 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 (ориентир 70–75%, оставляя 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 Общая формула: ```text 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 ```text 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. Ссылки - ВМ1: [`module-04-redis-vm1.md`](../VM1_app/documentation/module-04-redis-vm1.md). - ВМ2: [`module-04-redis-vm2.md`](../VM2_services/documentation/module-04-redis-vm2.md).