Caching: ElastiCache, DAX e CloudFront
- ⬜🗃️ Bancos: Multi-AZ, Read Replicas e DynamoDB(AWS Solutions Architect Associate)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Cache é o pattern mais antigo e mais efetivo para reduzir latência e custo de banco. Mas implementar mal resulta em dados stale, invalidação confusa e bugs sutis. O SAA cobra: escolha de produto (Redis × Memcached × DAX × CloudFront), escolha de padrão (cache-aside × write-through × write-behind) e interpretação de métricas.
ElastiCache: Redis vs Memcached
| Dimensão | Redis | Memcached |
|---|---|---|
| Estruturas | Strings, lists, sets, sorted sets, hashes, streams, hyperloglog, geo | Apenas key-value string |
| Multi-thread | Single-threaded (1 core por node) | Multi-threaded (escala vertical melhor) |
| Persistência | RDB snapshots + AOF log | Nenhuma (puramente in-memory) |
| Replicação | Read replicas + cluster mode | Sharding client-side, sem replicação |
| High Availability | Multi-AZ com automatic failover | Não nativo |
| Pub/Sub | Sim | Não |
| Transactions | Sim (MULTI/EXEC) | Não |
| Encryption in-transit / at-rest | Sim (TLS + KMS) | In-transit sim, at-rest não |
| Caso de uso | Session store, leaderboards, filas, geo, pub/sub | Cache puro simples, multi-thread, sem persistência |
Regra prática: na dúvida, escolha Redis. Memcached só ganha se você precisa estritamente de multithread e não liga para persistência/replicação. Exame favorece Redis em quase todo cenário.
Redis: Cluster Mode Disabled vs Enabled
| Feature | Cluster Disabled | Cluster Enabled |
|---|---|---|
| Shards | 1 shard | Até 500 shards |
| Dataset máximo | Limitado ao tamanho de 1 node (~600GB) | Horizontal scaling — petabytes |
| Client | Conexão simples | Precisa de cluster-aware client |
| Primary failover | Auto com Multi-AZ | Auto por shard |
| Backup | Snapshot completo | Snapshot por shard |
| Caso | Sessions, cache de API pequeno-médio | Datasets grandes, high throughput distribuído |
DAX — cache nativo do DynamoDB
DAX é um cache in-memory write-through compatível com a API do DynamoDB. A aplicação troca o endpoint e ganha latência μs (microssegundos). Roda em cluster de nodes na VPC.
DAX ≠ ElastiCache: DAX só fala API DynamoDB. Para RDS/Aurora você usa ElastiCache. Alguns candidatos erram pensando que DAX acelera qualquer query.
CloudFront — cache de borda para HTTP/S
CloudFront não é “o mesmo que ElastiCache mas HTTP”. É CDN global com POPs em ~450 cidades. Cache é controlado por cache policy (TTL + keys baseadas em query string/headers/cookies) e origin request policy (o que forward para a origem).
Padrões de cache — decor e aplique
| Padrão | Como funciona | Prós | Contras |
|---|---|---|---|
| Cache-Aside (Lazy) | App verifica cache; miss → busca DB → popula cache | Simples, cacheia apenas o usado | Primeiro hit é miss; stale data possível |
| Read-Through | Cache é provider: app lê do cache, ele busca do DB automaticamente | Código limpo | Depende de integração suportada |
| Write-Through | App escreve cache, cache escreve DB sincronamente | Consistência forte | Escrita mais lenta; cache cresce com dados nunca lidos |
| Write-Behind | App escreve cache; cache escreve DB async em batch | Escritas muito rápidas | Risco de perda se cache falhar antes do flush |
| Refresh-Ahead | Expira itens quentes pró-ativamente antes do TTL | Hit rate alto | Complexidade de previsão |
# Cache-aside típico (Python + redis + RDS)
def get_user(user_id):
key = f"user:{user_id}"
cached = redis.get(key)
if cached:
return json.loads(cached)
user = db.query("SELECT * FROM users WHERE id = %s", user_id)
redis.setex(key, 300, json.dumps(user)) # TTL 5min
return user
def update_user(user_id, data):
db.execute("UPDATE users SET ... WHERE id = %s", user_id)
redis.delete(f"user:{user_id}") # invalidação explícitaTTL é a chave: TTL curto = mais carga no DB mas menos stale; TTL longo = menos carga mas dados velhos. Regra prática: TTL = tolerância máxima a stale em ms. Para dados mutáveis, combine TTL com invalidação ativa em writes.
Uma API devolve o mesmo resultado de um cálculo pesado para milhares de usuários por minuto. O time quer reduzir latência e carga no banco com o menor esforço. Onde cachear primeiro?
Escolha arquitetural — quando cada um ganha
📋 Sessão de usuário de e-commerce compartilhada entre múltiplas instâncias EC2
Session store requer acesso rápido de múltiplos hosts. Redis é tradicional. DynamoDB on-demand é alternativa serverless mais moderna.
Alt: Sticky sessions no ALB — funciona mas amarra usuário a 1 host e falha em failover.
- → GET
- → só no cache miss
- → consulta primeiro
- → miss → busca no banco
- → miss
- Fora da AWS
- Rede e entrega
- Compute
- Banco de dados
Três camadas, três donos: CloudFront cacheia HTTP na borda, ElastiCache cacheia o que a sua aplicação decidir, DAX cacheia DynamoDB de forma transparente. A questão diz qual problema existe — a camada certa segue disso.
- Cachear o mais perto possível do usuário. Cada camada que a requisição não precisa atravessar é latência e custo economizados. CloudFront atende da borda e a origem nem sabe que houve requisição — é o cache mais barato que existe.
- CloudFront não é só para arquivo. Ele cacheia resposta de API também, respeitando Cache-Control e cache policy. A pegadinha é o oposto: conteúdo personalizado por usuário não deve ser cacheado na borda sem chave de cache adequada, ou um usuário vê dado do outro.
- ElastiCache é o cache que você controla. Sessão, resultado de query caro, rate limit, lock distribuído. Redis para estrutura de dado e persistência; Memcached só para chave-valor simples multi-thread. Se a questão menciona pub/sub, replicação ou sorted set, é Redis.
- DAX é específico do DynamoDB. Cache in-memory transparente: a aplicação usa o SDK do DynamoDB e o DAX intercepta. Leva leitura de milissegundos para microssegundos. Não serve para RDS — e essa troca aparece em alternativa errada com frequência.
- A ordem de aplicação importa. Comece pela borda (mais barato, mais impacto), depois cache de aplicação, e só então cache de banco. Quem começa otimizando o banco costuma estar resolvendo o sintoma da camada errada.
📋 API pública com endpoints /produtos e /categorias acessados 10.000 req/s, dados mudam 1x/dia
CDN absorve 99% dos requests na edge, origem quase nunca é tocada. Invalidação na atualização diária.
Alt: API Gateway com caching — funciona mas fica em 1 região.
📋 Leaderboard de jogo — top 100 jogadores, atualizado a cada partida, consulta por tempo real
ZADD + ZREVRANGE resolve em uma chamada. Nem DynamoDB nem DAX oferecem sorted sets nativos.
Métricas críticas do ElastiCache (CloudWatch)
Q&A estilo exame
❓ Quando usar DAX e quando usar ElastiCache na frente do DynamoDB?
❓ Como escolher entre cache-aside e write-through?
❓ Redis Multi-AZ com auto-failover — RTO típico?
❓ Aplicação começou a retornar dados antigos após deploy. Como diagnosticar?
Perguntas frequentes
❓ Redis ou Memcached no cache gerenciado?
❓ Cache transparente ou cache na aplicação?
❓ Como lidar com dado velho no cache?
Fixando
Qual cenário torna o CloudFront a escolha ERRADA para cache?
O time precisa de cache com estruturas de dados (lista, sorted set), replicação e persistência opcional. Redis ou Memcached?
Armadilhas: (1) Memcached não tem persistência — restart apaga tudo; (2) Redis single-thread, não adianta pegar node de 64 cores; (3) DAX só DynamoDB; (4) CloudFront invalidation custa após 1.000/mês; (5) Cache “thundering herd” — quando muitos clientes refazem cache ao mesmo tempo após expiração (mitigue com jitter no TTL).
Take-aways: cache é o multiplicador de performance mais barato. Escolha: Redis (rico), Memcached (simples), DAX (DynamoDB), CloudFront (HTTP). Padrão default: cache-aside com TTL. Monitore hit rate e evictions. Invalide em writes quando consistência importa.
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…