- Bump Rust toolchain from 1.87 to 1.88 - Add testcontainers and arbitrary dependencies for property testing - Update router with rendezvous hashing improvements - Fix credential handling in miroir-ctl - Update reshard and migration modules - Add Helm chart scaffolding - Add Redis memory accounting documentation All Phase 0 DoD checks pass: - cargo build --all succeeds - cargo test --all succeeds (103 tests) - cargo clippy --all-targets --all-features -- -D warnings passes - cargo fmt --all -- --check passes - Config round-trip YAML test passes Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5.4 KiB
Redis Memory Accounting (Plan §14.7)
This document validates the Redis memory usage for the Miroir task store when running in HA mode with multiple replicas.
Redis Keyspace Overview
The Redis backend for Miroir's task store uses the following keyspace patterns:
Table Keys (Hash + Index Set)
Each of the 14 tables is stored as:
miroir:<table>:<id>→ Hash containing the serialized recordmiroir:<table>:_index→ Set containing all IDs in the table
Tables:
tasks- Task registrynode_settings_version- Per-(index, node) settings freshnessaliases- Single and multi-target aliasessessions- Read-your-writes session pinsidempotency_cache- Write dedup cachejobs- Background jobsleader_lease- Coordinator leasecanaries- Canary definitionscanary_runs- Canary run historycdc_cursors- CDC cursorstenant_map- API key → tenant mappingrollover_policies- ILM rollover policiessearch_ui_config- Search UI configurationadmin_sessions- Admin UI sessions
Special-Purpose Keys
Rate Limiting (§13.21)
miroir:ratelimit:searchui:<ip>- Per-IP search UI rate limit counter (EXPIRE after window)miroir:ratelimit:adminlogin:<ip>- Admin login rate limit countermiroir:ratelimit:backoff:<ip>- Per-IP backoff flag (EXPIRE after backoff duration)
CDC Overflow (§13.13)
miroir:cdc:overflow:<sink>- CDC overflow buffer (1 GiB per sink default)
Scoped Key Rotation (§13.21)
miroir:search_ui_scoped_key:<index>- Current scoped key for an indexmiroir:search_ui_scoped_key_observed:<pod>:<index>- Pod observation marker
Job Queue (§14.5)
miroir:jobs:enqueued- List of enqueued job IDs
Admin Session Revocation (§13.19)
miroir:admin_session:revoked- Pub/Sub channel for instant logout propagation
Memory Sizing Formula
Per-Record Overhead
Redis has the following per-key overhead:
- Key: ~100 bytes (including key length and overhead)
- Value: varies by type
- Hash entry: ~50 bytes per field
- Set entry: ~50 bytes per member
Estimated Memory per Table
| Table | Avg Record Size | Est. Count | Memory (approx) |
|---|---|---|---|
| tasks | 500 bytes | 10,000 | ~5 MB |
| node_settings_version | 100 bytes | 500 | ~50 KB |
| aliases | 200 bytes | 100 | ~20 KB |
| sessions | 150 bytes | 1,000 | ~150 KB |
| idempotency_cache | 1 KB | 10,000 | ~10 MB (TTL 1h) |
| jobs | 400 bytes | 1,000 | ~400 KB |
| leader_lease | 200 bytes | 1 | ~200 bytes |
| canaries | 300 bytes | 50 | ~15 KB |
| canary_runs | 200 bytes | 10,000 | ~2 MB |
| cdc_cursors | 100 bytes | 100 | ~10 KB |
| tenant_map | 500 bytes | 100 | ~50 KB |
| rollover_policies | 300 bytes | 50 | ~15 KB |
| search_ui_config | 2 KB | 100 | ~200 KB |
| admin_sessions | 150 bytes | 100 | ~15 KB |
| Subtotal | - | - | ~18 MB |
Rate Limiting Memory
Search UI rate limiter (§13.21):
- Per-IP bucket: ~100 bytes
- Active IPs: ~10,000 (production estimate)
- TTL: 60 seconds (configurable via
search_ui.rate_limit.redis_ttl_s) - Memory: ~1 MB (steady state, with TTL)
Admin login rate limiter:
- Per-IP bucket: ~100 bytes
- Active IPs: ~100
- TTL: 300 seconds (5 minutes)
- Memory: ~10 KB
Backoff markers:
- Per-IP backoff: ~100 bytes
- Active backoffs: ~100
- TTL: variable (typically 60-300 seconds)
- Memory: ~10 KB
CDC Overflow Memory
- Per-sink buffer: 1 GiB (configurable via
cdc.buffer.redis_bytes) - Typical sinks: 1-3
- Memory: 1-3 GiB (only when CDC is enabled and overflow occurs)
Scoped Key Rotation Memory
- Per-index key: ~200 bytes
- Indices: ~100
- Per-pod observation markers: 100 bytes × (pods × indices)
- Pods (HPA max): 10
- Memory: ~20 KB + 100 KB = ~120 KB
Total Estimated Memory Usage
| Component | Memory |
|---|---|
| Tables (steady state) | ~18 MB |
| Rate limiting | ~1 MB |
| Scoped key rotation | ~120 KB |
| Subtotal (without CDC overflow) | ~19 MB |
| CDC overflow (per sink) | 1 GiB (optional) |
Production Sizing Recommendation
For a production deployment with CDC disabled:
- Minimum Redis memory: 64 MB (provides headroom for bursts)
- Recommended Redis memory: 128-256 MB (comfortable headroom)
For a production deployment with CDC enabled:
- Per-sink buffer: 1 GiB (configurable)
- Minimum Redis memory: 1 GiB + 64 MB per sink
- Recommended Redis memory: 2 GiB (for single-sink deployments)
Validation Script
The following script can be used to validate Redis memory usage in a running deployment:
# Connect to Redis and get memory info
redis-cli INFO memory
# Get memory usage for all Miroir keys
redis-cli --scan --pattern 'miroir:*' | xargs redis-cli MEMORY USAGE
# Get total memory used by Miroir
redis-cli --scan --pattern 'miroir:*' | xargs redis-cli MEMORY USAGE | awk '{sum+=$1} END {print sum}'
Helm Chart Defaults
The Helm chart (see charts/miroir/values.yaml) sets the following defaults:
redis:
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
These defaults are appropriate for deployments without CDC overflow. For CDC-enabled deployments, increase the memory limit to at least 2 GiB.
References
- Plan §4: Task store schema
- Plan §13.13: CDC cursors and overflow
- Plan §13.19: Admin sessions and Pub/Sub revocation
- Plan §13.21: Search UI rate limiting and scoped key rotation
- Plan §14.7: Deployment sizing matrix