Executando verificação de segurança...
2

Caching em Sistemas Distribuídos: Cache-Aside, Write-Through e Write-Behind

Cache é a solução mais barata para escalar leitura. Mas qual estratégia usar? Descubra as diferenças entre Cache-Aside, Write-Through, Write-Behind e quando cada uma se aplica em arquiteturas distribuídas.

Pontos principais do artigo:

Arquitetura e design patterns aplicados
Exemplos de código prontos para produção
Trade-offs e decisões de engenharia
Quando usar e quando evitar.

Em escala pequena, cache parece atalho.
Em produção, cache vira sistema distribuído.
Ele tem pressão de memória, regras de roteamento, dados stale, comportamento de cliente, falhas parciais, segurança, custo e operação.
O erro comum é tratar Redis ou Memcached como camada mágica de velocidade.
O modelo mental correto é mais rígido:

  • banco de dados guarda a verdade durável,
  • cache guarda aceleração temporária,
  • clientes precisam de fallback cuidadoso,
  • plataforma precisa controlar invalidação, capacidade e visibilidade.

Cache distribuído bom reduz latência e carga no banco sem virar fonte oculta de verdade.
Este artigo desenha esse sistema de ponta a ponta.
Redis e Memcached aparecem juntos porque ambos continuam relevantes.
Redis oferece estruturas ricas, replicação, persistência opcional, Lua/functions, streams, sorted sets e Redis Cluster.
Memcached oferece um cache key-value em memória simples, rápido e normalmente shardado no cliente.
Nenhum deles elimina design.


Sumário


Análise de Requisitos

A primeira decisão em entrevista é escopo.
Não comece por Redis.
Comece pelo workload.

Requisitos Funcionais

  1. Servir objetos lidos com frequência com latência menor que a fonte de verdade.
  2. Reduzir pressão de leitura em bancos primários e APIs downstream.
  3. Suportar leituras e escritas key-value para objetos serializados.
  4. Suportar expiração por TTL.
  5. Suportar invalidação explícita depois de writes.
  6. Suportar fallback seguro em cache miss ou falha do cache.
  7. Suportar escala horizontal entre nós de cache.
  8. Suportar chaves de alta cardinalidade sem posicionamento manual.
  9. Suportar mitigação de hot keys.
  10. Expor métricas de hit rate, latência, memória, evictions e erros.
  11. Suportar controle de acesso e transporte criptografado quando necessário.
  12. Manter comportamento previsível durante deploys, failovers e resharding.

Requisitos Não Funcionais

RequisitoMetaPor que importa
Latência de get< 2ms p99 dentro da regiãocache precisa ganhar do banco
Disponibilidade do cache99,99% no caminho de leiturafalha não pode derrubar app
Hit rate80-95% para objetos cacheáveisabaixo disso custo pode não fechar
Tolerância a staleexplícita por objetocada dado envelhece de forma diferente
Eficiência de memóriamedida por classe de objetomemória é custo principal
Tempo de failoversegundos a poucos minutosincidente longo sobrecarrega banco
Estabilidade de roteamentopouco movimento em mudança de nóresharding não deve esfriar tudo
Clareza operacionalalertas ligados a impactohit rate sozinho engana

Perguntas de Clarificação

  1. Quais dados podem ser cacheados?
  2. Quanto stale cada objeto pode ficar?
  3. Cache é local a um serviço ou compartilhado por vários serviços?
  4. Read-through mora numa biblioteca, proxy ou aplicação?
  5. Qual distribuição de tamanho dos objetos?
  6. Qual QPS de pico e qual QPS de miss?
  7. O que acontece se o cache cair?
  8. Consistência cross-region é obrigatória?
  9. Dados exigem criptografia ou isolamento forte?
  10. Writes são frequentes o suficiente para complicar invalidação?

Premissas Deste Design

Este desenho assume:

  • produto SaaS multi-tenant,
  • workload read-heavy,
  • deploy regional de aplicações,
  • Redis Cluster para casos com recursos ricos,
  • pool Memcached para cache simples de objetos,
  • banco relacional como fonte de verdade,
  • Kafka ou equivalente para eventos de invalidação,
  • meta de p99 abaixo de 150ms em APIs de usuário,
  • budget de staleness de 30 segundos para perfis e catálogo,
  • política de não cachear decisões críticas de autorização sem versionamento explícito.

O Que Este Cache Não É

Cache não é banco primário.
Cache não é log de auditoria.
Cache não é ledger de pagamento.
Cache não é a única cópia de estado de usuário.
Cache pode esquecer.
Esquecer é recurso quando a fonte de verdade continua correta.
Esquecer é incidente quando o cache virou banco sem ninguém admitir.


Cálculos de Envelope

Declare premissas antes de números.
O número exato importa menos que o formato da pressão.

Escala Assumida

Usuários ativos mensais: 80 milhões
Usuários ativos diários: 20 milhões
Requests de API no pico: 1.200.000/s
Requests médios de API: 250.000/s
Percentual de leitura cacheável: 65%
Hit rate alvo: 90%
Tamanho médio de objeto cacheado: 2 KB
P95 de objeto cacheado: 12 KB
Objetos quentes possíveis: 250 milhões de chaves
Objetos alterados por dia: 40 milhões
Regiões: 3 ativas

Carga de Requests

Leituras cacheáveis no pico = 1.200.000 * 0,65
                            = 780.000 leituras/s
Com hit rate de 90%:
cache hits/s = 702.000
cache misses/s = 78.000

78.000 leituras por segundo no banco ainda é muito.
O caminho de miss precisa de proteção.
O cache deve reduzir carga média e limitar amplificação em miss.

Estimativa de Memória

Objetos quentes lógicos: 250.000.000
Payload médio: 2 KB
Overhead de metadados e allocator: 35%
Fator de replicação: 2
Payload bruto = 250M * 2KB
              ~= 500 GB
Com overhead = 500GB * 1,35
             ~= 675 GB
Com uma réplica = 675GB * 2
                ~= 1,35 TB

Essa é estimativa direcional.
Memória real no Redis muda com encoding, tamanho de chave, tipo de objeto, fragmentação, buffers de replicação e buffers de persistência.
Memória real no Memcached depende de slab classes, distribuição de tamanho e espaço desperdiçado em chunks.

Estimativa de Rede

Banda de cache hit no pico ~= 702.000 * 2KB
                           ~= 1,4 GB/s de payload
Com overhead de protocolo, TLS e objetos p95:
planeje múltiplos GB/s dentro da região.

Rede não é detalhe.
Cache pode mover gargalo de CPU do banco para NICs, conexões de cliente ou custo cross-AZ.

Estimativa de Miss Storm

Se deploy limpa 30% das chaves quentes no pico:

novo miss rate = misses normais + chaves frias
miss QPS normal = 78.000
leitura fria extra = 780.000 * 0,30
                   = 234.000
miss QPS total = 312.000

Se cada miss abre 3 queries:

QPS no banco = 936.000

Isso pode derrubar a fonte de verdade.
Warming, request coalescing, TTL com jitter e admission control não são opcionais em escala alta.

Insight Central

Design de cache distribuído é design para limitar dano em miss.
O caminho feliz é simples.
O caminho de miss decide se o sistema sobrevive.

Artigo técnico focado em aplicação prática. Sem enrolação.

Leia completo:
https://lemon.dev.br/pt/blog/distributed-cache-system-design

Carregando publicação patrocinada...
2