DevGuideTK
← Trilha Backend

Bancos chave-valor

O modelo mais simples e mais rápido, com o Redis e suas estruturas de dados como referência.

As decisões com um banco chave-valor são cinco: para que usá-lo, como nomear e expirar as chaves, como configurar a persistência e a memória, como fazer operações de vários passos e qual produto escolher.

Para que usar

UsoEstruturaPor que o RedisCuidado
CacheString ou hash, com expiraçãoLeitura rápida, despejo automáticoVer o tópico de cache
SessõesString ou hash, com expiraçãoToda instância lê a mesma sessãoPersistência, ou aceitar deslogar todos numa queda
Contadores e limites de requisiçõesString com INCR e expiraçãoAtômico e rápidoVer o tópico de limite de requisições
PlacaresSorted setOrdenação mantida a cada pontoUm placar por período, com expiração
Travas distribuídasSET chave valor NX PXAtômico, com expiraçãoLiberar só a própria trava; não é garantia absoluta (ver abaixo)
FilasList, ou stream com grupos de consumidoresSimples, já instaladoPara filas sérias, ver o tópico de filas
Contagem de distintosHyperLogLog12 KB por contador, com erro de cerca de 1%Aproximado por definição
Dados de negócio principais——Não: fique no banco relacional

Chaves e expiração

PráticaPor quê
Prefixos com dois-pontos: sessao:abc, placar:2026-46Organização, e SCAN por padrão
Expiração em tudo que é temporário (EX, PX, EXPIRE)Sem ela, a memória só cresce
Variação aleatória na expiração de chaves criadas juntasEvita que expirem todas no mesmo instante
Valores pequenos, divididos em várias chaves se precisoComandos sobre valores enormes travam o servidor
SCAN e UNLINK, nunca KEYS e DEL de chaves gigantesNo teste, o KEYS fez outro cliente esperar 308 ms; o SCAN, 6 ms

Persistência e memória

Configure de acordo com o uso, e não deixe no padrão por acaso:

UsoPersistênciaPolítica de memória
Só cacheNenhuma, ou fotografiasallkeys-lru ou allkeys-lfu: apagar é o comportamento esperado
Sessões, carrinhos, contadoresAOF com everysecnoeviction ou volatile-lru (só chaves com expiração podem sair)
Dados que não podem perder nadaAOF com always, e réplicanoeviction
Cache e dados no mesmo Redis—Evite: separe em duas instâncias com configurações diferentes

Os números do teste do nível Conceito resumem a troca. A configuração padrão perdeu as 10 mil gravações numa queda logo depois delas. O AOF com everysec sobreviveu à queda do processo e custou quase nada (116 mil contra 117 mil gravações por segundo). O always custou cinco vezes menos vazão. E o allkeys-lru, ótimo para cache, apagou 65 mil chaves em silêncio quando a memória encheu.

Réplicas e o Redis Sentinel (ou o Redis Cluster) cuidam da disponibilidade: uma réplica assume se o principal cair. A replicação é assíncrona, então o principal pode confirmar uma gravação e cair antes de passá-la à réplica. O comando WAIT espera a confirmação das réplicas, quando isso importa.

Operações de vários passos

NecessidadeFerramenta
Um comando atômico resolveINCR, HINCRBY, ZINCRBY, SET ... NX, GETDEL: prefira sempre
Vários comandos sem intercalação, sem decisões no meioMULTI e EXEC
Ler, decidir e gravar de forma atômicaScript em Lua (EVAL) ou funções (FCALL)
Gravar só se a chave não mudou desde a leituraWATCH, MULTI e EXEC: a transação falha se a chave mudou
Muitos comandos independentes, rápidoPipeline (sem atomicidade): 7 vezes mais rápido no teste

Travas distribuídas

A trava com SET trava:pedido:981 <id-aleatório> NX PX 30000 é comum e tem dois erros clássicos:

  1. Liberar a trava de outro. Se a trava expirou enquanto o dono ainda trabalhava e outro processo a pegou, um DEL simples apaga a trava do outro. A liberação certa confere o valor antes de apagar, num script em Lua.
  2. Confiar nela para correção absoluta. Uma pausa longa do processo (coletor de lixo, máquina virtual suspensa) pode durar mais que a expiração, e dois processos se acham donos ao mesmo tempo. Para operações em que isso não pode acontecer, combine a trava com uma conferência no próprio banco, como um número de versão crescente gravado junto com o dado.

Qual produto

ProdutoCaracterísticas
RedisO mais completo em estruturas; desde a versão 8, de novo com licença de código aberto (AGPL), além das licenças anteriores
ValkeyDerivado de código aberto do Redis 7.2, mantido pela Linux Foundation; compatível com os clientes do Redis
MemcachedSó chave-valor simples, sem persistência; vários núcleos por processo; bom só para cache
Serviços gerenciados (ElastiCache, MemoryDB, Upstash, Azure Cache)Sem operar servidores; verifique a persistência e o modelo de cobrança
DynamoDBChave-valor e documentos em disco, gerenciado e durável, com escala horizontal; outra categoria de latência e de preço

Resumo da decisão

  1. Redis para o que é acessado pela chave e cabe na memória; dados de negócio principais no relacional.
  2. A estrutura certa para cada caso: hash, set, sorted set, stream.
  3. Comandos atômicos em vez de ler, calcular e gravar.
  4. Pipeline para muitos comandos; SCAN, nunca KEYS.
  5. Expiração em tudo que é temporário.
  6. Persistência e política de memória escolhidas pelo uso: cache e dados em instâncias separadas.

O próximo nível mostra um placar com sorted set nas cinco linguagens, com pontos simultâneos.

Prompts para aprofundar

Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.

  • Usar o Redis no meu sistema

    Quero decidir o que guardar no Redis no meu sistema.
    
    Pergunte o que o sistema faz, quais dados são acessados pela chave, o volume e o quanto cada dado pode ser perdido ou reconstruído.
    
    Para cada uso candidato, recomende se vai para o Redis ou para o banco principal, a estrutura de dados, a expiração, e a configuração de persistência e memória. No final, diga se faz sentido ter mais de uma instância.
  • Travas distribuídas com Redis

    Preciso de uma trava distribuída para garantir que só um processo faça uma tarefa por vez.
    
    Pergunte qual linguagem eu uso, o que a tarefa faz e o que acontece se dois processos a fizerem ao mesmo tempo.
    
    Explique:
    1. A trava com SET NX PX e um identificador aleatório.
    2. A liberação com conferência do dono, num script em Lua.
    3. O que acontece quando o processo demora mais que a expiração.
    4. Por que a trava sozinha não garante correção absoluta, e como um número de versão no banco completa a proteção.
    5. Alternativas: travas consultivas do PostgreSQL e filas com um consumidor só.
  • Redis, Valkey, Memcached ou DynamoDB

    Estou escolhendo um banco chave-valor para o meu sistema.
    
    Pergunte para que ele vai servir, o volume de dados, a necessidade de durabilidade, a nuvem que eu uso e se prefiro operar servidores ou usar um serviço gerenciado.
    
    Compare para o meu caso Redis, Valkey, Memcached, um Redis gerenciado e o DynamoDB quanto a estruturas de dados, durabilidade, escala, licença, operação e custo. Recomende uma opção.