Estágio 02 · 02-11
LockedRedis é mais usado errado do que entendido. A maioria dos devs trata como "cache key-value rápido" e ignora 80% do que ele oferece: estruturas complexas, scripts atômicos, streams, pub/sub, locks distribuídos, geo, HyperLogLog. Tratado superficialmente, vira ferramenta de cache só. Tratado bem, é a peça mais versátil de um stack distribuído, rate limit, leaderboards, queues, locks, session store, real-time fan-out, deduplicação, idempotency keys.
Este módulo é Redis fundo: modelo single-thread, comandos por estrutura, persistence (RDB/AOF), replication, cluster, scripting, e os padrões reais (cache-aside, locks, streams como queue, pub/sub limites). Você sai sabendo escolher Redis vs banco, e explorar o que ele realmente faz.
Redis (pre-6) é single-threaded pra comandos. Um core, um thread, sem locks de concorrência. Comandos são atômicos individualmente: você nunca lê estado parcial.
Redis 6+ trouxe I/O threading: I/O (read/write socket) pode usar múltiplas threads pra parsing/serialização. Mas a execução do comando ainda é single-threaded. Beneficia setups com clientes muitos.
Implicação: comandos lentos (ex: KEYS * em DB com milhões de chaves, scripts Lua pesados) bloqueiam tudo. Latência cresce. KEYS é proibido em prod; use SCAN.
Não é só K/V. Cada chave tem um tipo:
Cada estrutura tem comandos específicos. SET, GET são string. HGET, HSET hash. ZADD, ZRANGEBYSCORE zset. Etc.
Toda chave aceita EXPIRE/PEXPIRE. Sem TTL, vive pra sempre.
Redis combina:
Implicação: chaves expiradas que nunca são tocadas ainda ocupam memória até a amostragem pegar. Em general, ok.
Quando atinge maxmemory:
noeviction (default em algumas configs): erro em writes.allkeys-lru / allkeys-lfu: evicta LRU/LFU em qualquer chave.volatile-lru / volatile-lfu: só em chaves com TTL.allkeys-random / volatile-random.volatile-ttl: evicta com menor TTL primeiro.Pra cache: allkeys-lru ou allkeys-lfu. Pra store de session com TTL: volatile-lru. Pra dados sem evict (filas, store crítico): noeviction + monitoramento de memória.
Redis é in-memory mas pode persistir:
dump.rdb periódico (configurável, ex: save 60 10000 = a cada 60s se 10k keys mudaram). Forks processo, parent continua servindo. Snapshot cria gap de RPO.appendfsync everysec (default) flush 1x/s; always cada commit (lento mas durable); no (deixa OS).RPO (recovery point objective): com appendfsync everysec, ~1s. Com always, perto de 0 mas latência maior.
Replication clássica: 1 primary + N replicas. Replicas pegam stream do primary (RDB inicial + comandos subsequentes). Replicas read-only por default.
Failover manual ou via Redis Sentinel: monitora primary, promove replica em falha.
Redis Cluster: sharding nativo. 16384 slots distribuídos por shards. Cliente direciona key → slot → shard. Suporta múltiplos primaries com replicas cada.
{tenant}user:1, {tenant}user:2) força mesmo slot.MOVED responses.Pipelining: cliente manda N comandos sem esperar response de cada um, depois lê todos. Reduz round-trips. Comum em libs.
Transactions via MULTI/EXEC: enfileira comandos, executa atomicamente. Sem rollback se um falhar, Redis entende como erro de cliente. Outros comandos no MULTI ainda rodam.
Optimistic locking via WATCH: marca chaves; se mudarem antes de EXEC, txn aborta. Padrão "check-and-set".
Lua scripts executam atomically server-side via EVAL:
-- decrement only if positive
if tonumber(redis.call('GET', KEYS[1])) > 0 then
return redis.call('DECR', KEYS[1])
else
return -1
end
Garante atomicity em operações multi-comando sem necessitar WATCH. Cuidado: scripts longos bloqueiam server.
Redis 7+ trouxe Functions: scripts persistidos como objetos nomeados, replicados, parte do dataset. Substituem SCRIPT LOAD ad-hoc.
SUBSCRIBE channel / PUBLISH channel message. Fan-out broadcast. Não persiste: subscriber offline perde messages. Sem ack, sem retry, sem replay.
Use cases válidos: sinalização efêmera (cache invalidation pra frota de servers), real-time UI updates onde perda é ok.
Em vez de pub/sub pra "queue", use Streams.
XADD stream id fields... adiciona entry. XREAD, XREADGROUP lêem. Consumer Groups dão semantics tipo Kafka:
<ms>-<seq>).XACK marca como processada.XPEL lista pending (não acked).XCLAIM reatribui pending de consumer morto.Use cases: queue durável, event log, fan-out controlado. Stream é tendência: substitui muitos casos antigos de pub/sub e de Lists como queue.
Limite vs Kafka: Redis Streams cabem no dataset (RAM). Pra eventos ilimitados, Kafka. Pra eventos de janela curta, Streams é mais simples.
get(key)
↓
Redis.get(key) hit? → retorna
↓ miss
db.get(key)
↓
Redis.set(key, value, ttl)
↓
retorna
Issues:
NULL) com TTL curta protege.Lock simples:
SET lock:foo <token> NX EX 10
NX = só se não existe; EX = TTL. Quem ganha tem o lock por 10s. Release: script Lua que checa token e DEL.
Redlock: algoritmo de Redis pra locks com múltiplos nós (redundância). Antonio "antirez" descreveu. Martin Kleppmann criticou famously: locks distribuídos sobre time-based têm fragilidades; pra correctness usar fencing tokens (cada lock retorna número monotônico, recurso protegido valida).
Em workloads tolerantes a failure raro (cron jobs, leader election leve), Redlock funciona. Em workloads que correctness é vital, considere ZooKeeper, etcd, ou banco com SELECT FOR UPDATE.
Algoritmos:
INCR rate:user:1:202604281200, EXPIRE 60. Limite por minuto. Simples mas tem burst no boundary.Lib redis-rate-limiter ou implementação própria com Lua. Em microservices, este é o store comum.
API que aceita Idempotency-Key header pra evitar processamento duplicado:
SET idem:<key> "processing" NX EX 600.NX falha, key já em uso, busca resultado anterior em outra chave ou retorna conflict.SET idem:<key>:result <json>.Stripe, payment gateways, etc. usam.
Express/Fastify session adapters pra Redis. Token (cookie) → key Redis com session blob. TTL = expiration.
Vantagens: stateless app server (pode escalar horizontal), fácil revogar (DEL key).
INFO memory:
used_memory (bytes em uso lógico).used_memory_rss (bytes alocados pelo OS, pode incluir fragmentação).mem_fragmentation_ratio (rss/used).Frag > 1.5 sugere fragmentação. MEMORY DOCTOR dá análise. Reset via restart ou MEMORY PURGE (libs jemalloc).
Reduzir uso:
MONITOR: vê todos comandos em real-time. Custoso, não use em prod.SLOWLOG: comandos > threshold. Critical em prod.LATENCY DOCTOR, LATENCY HISTORY: diagnostico latência.CLIENT LIST: clients conectados.CONFIG GET/SET: configurações.Em managed Redis (Railway, Upstash, ElastiCache, Memorystore, Redis Cloud), parte de tunning fica no provider.
Em 2026, Valkey ganhou tração após mudança da licença Redis. Compat 100% com clientes existentes.
Você precisa, sem consultar:
KEYS * é tóxico em prod e o que fazer em vez.WATCH/MULTI/EXEC como optimistic locking.Adicionar Redis ao Logística API com 4 padrões reais.
ioredis ou node-redis.GET /reports/dashboard agrega pedidos por status (count + sum total).POST /orders/:id/events muda status.POST /orders aceita header Idempotency-Key.POST /courier/location recebe {lat, lng, timestamp} do entregador.courier:<id>:locations.GET /courier/:id/locations?since=<id> lê do stream.XADD ... MAXLEN ~ 1000).cache_hits_total, cache_misses_total no /metrics.KEYS * em código.INFO memory).redis-cli --cluster create) e adapt o cliente.ioredis, evt loop não bloqueia em Redis (todas comandos via socket).Destrava
02-11 é prereq dos seguintes módulos: