📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados em Módulo 08: Bancos de Dados SQL e NoSQL. Recomendado revisar antes de começar.

⚡ Arquitetura de Cache Distribuído com Redis & Invalidação Inteligente

v3.0 — Padrão Cache-Aside, Write-Through, Invalidação e Rate Limiting

Trilha de Engenharia de Dados & Bancos de Dados — Projeto 3 de 4

🎓 Nível Profissional Simulado: Engenheiro de Backend Sênior / Systems Architect. Na computação, existem apenas duas coisas difíceis: invalidação de cache e escolha de nomes. Aqui você aprende como arquitetar um cache resiliente que evita Cache Stampede, Cache Avalanche e Stale Data.


🎯 Objetivo

Implementar uma camada de aceleração em memória com Redis 7.2 aplicando os padrões Cache-Aside (Lazy Loading) e Invalidação Atômica, garantindo latência sub-milissegundo de resposta e protegendo o banco relacional contra picos de tráfego.


🏗️ Diagrama de Sequência — Padrão Cache-Aside & Invalidação

sequenceDiagram
    autonumber
    actor Cliente
    participant App as Backend API
    participant Cache as Redis (In-Memory)
    participant DB as PostgreSQL (Disk)

    Note over Cliente,DB: Cenário 1: Leitura Inicial (Cache MISS)
    Cliente->>App: GET /produtos/101
    App->>Cache: GET produto:101
    Cache-->>App: (nil / Cache MISS)
    App->>DB: SELECT * FROM produtos WHERE id = 101
    DB-->>App: { id: 101, nome: "MacBook", preco: 14999 }
    App->>Cache: SETEX produto:101 60s {json}
    App-->>Cliente: 200 OK (50ms - Disco)

    Note over Cliente,DB: Cenário 2: Leituras Subsequentes (Cache HIT)
    Cliente->>App: GET /produtos/101
    App->>Cache: GET produto:101
    Cache-->>App: { id: 101, nome: "MacBook", preco: 14999 } (Cache HIT)
    App-->>Cliente: 200 OK (< 2ms - RAM)

    Note over Cliente,DB: Cenário 3: Atualização com Invalidação (Evita Stale Data)
    Cliente->>App: PUT /produtos/101 { preco: 13999 }
    App->>DB: UPDATE produtos SET preco = 13999 WHERE id = 101
    App->>Cache: DEL produto:101 (Invalidação Atômica)
    App-->>Cliente: 200 OK (Preço Atualizado)

🧑‍💼 Fase 1 — Levantamento de Requisitos

O Briefing do Cliente (Equipe de Infraestrutura & SRE)

“Nas promoções relâmpago, o mesmo produto recebe 50.000 requisições por segundo. O banco de dados relacional trava porque atinge 100% de CPU rodando o mesmo SELECT repetidamente. Precisamos de uma camada intermediária em memória ultra-rápida que responda instantaneamente e saiba quando atualizar os dados se o preço mudar.”

Requisitos Funcionais (RF) e Não-Funcionais (RNF)

ID Tipo Descrição Origem no Briefing
RF01 Funcional Consultar dados em cache antes de recorrer ao banco relacional (Cache-Aside). “responda instantaneamente”
RF02 Funcional Definir TTL (Time-To-Live) automático para expiração de chaves voláteis. “saiba quando atualizar”
RF03 Funcional Invalidar explicitamente a chave no Redis quando o produto sofrer atualização. “se o preço mudar”
RNF01 Não-Funcional Latência de resposta em Cache Hit inferior a 2 milissegundos. Alta Vazão / SLA
RNF02 Não-Funcional Persistência Append-Only File (AOF) para recuperação após reinício do Redis. Confiabilidade

📋 Fase 2 — Backlog & User Stories

ID User Story Prioridade
US01 Como cliente, quero carregar a página do produto em menos de 10ms via cache em memória. Alta
US02 Como lojista, quero atualizar o preço do produto e ver o cache ser invalidado no mesmo instante. Alta
US03 Como SRE, quero que as chaves expirem automaticamente após 60 segundos para evitar acúmulo de memória. Média

🌿 Fase 3 — Engenharia em Equipe (Git Flow & Setup)

# Branch da funcionalidade
git checkout -b feature/US01-cache-aside-redis

# Subir o Redis isolado
docker-compose up -d

# Monitorar os comandos em tempo real
docker exec -it db_cache_redis redis-cli -a redissecret MONITOR

🛠️ Fase 4 — Implementação Passo a Passo (app/cache_manager.py)

def buscar_produto_com_cache_aside(redis_client, produto_id, ttl=60):
    cache_key = f"produto:{produto_id}"
    dados = redis_client.get(cache_key)
    
    # 1. Cache HIT
    if dados:
        return json.loads(dados)

    # 2. Cache MISS: Busca no banco relacional
    produto_db = buscar_no_postgresql(produto_id)

    # 3. Salva no Redis com TTL configurável
    if produto_db:
        redis_client.setex(cache_key, ttl, json.dumps(produto_db))
    return produto_db

🧭 Decisões Técnicas (ADRs)


🚀 Como Executar no Laboratório

1. Abra o terminal na pasta deste projeto

No seu editor/IDE, abra a pasta deste projeto (File > Open Folder) ou navegue via terminal:

cd db_cache_03_redis_sharding_tuning

2. Execute a aplicação ou testes

docker-compose up -d
# Executar a suíte de testes automatizados com asserções de HIT/MISS/TTL:
python -m unittest tests/test_cache_manager.py

[!TIP] Dica para execução a partir da raiz do repositório: Se você abriu o repositório completo no VS Code, basta navegar até a pasta antes de executar: cd catalogo_projetos/db_cache_03_redis_sharding_tuning


🧪 Testes de Validação & Asserções

# Executar a demonstração guiada de Cache Hit, Miss e Invalidação:
python app/cache_manager.py


🏛️ Arquitetura Visual & Engenharia de Dados

A arquitetura abaixo demonstra o fluxo de persistência, otimização e isolamento dos componentes na subpasta app/:

Arquitetura do Banco de Dados

flowchart TD
    subgraph DDL["Modelagem & Schema (DDL)"]
        S1["Tabelas / Coleções"] --> S2["Constraints & Índices"]
    end
    subgraph DML["Regras & Automação (DML / PL)"]
        R1["Triggers / Aggregations"] --> R2["Procedimentos Transacionais"]
    end
    subgraph Perf["Otimização & Armazenamento"]
        P1["Planos EXPLAIN / Partições"] --> P2["Garantia de ACID / TTL"]
    end
    subgraph Homolog["Homologação & Qualidade"]
        Q1["Docker Compose & Scripts"] --> Q2["Checkpoints CP-01..05 PASS"]
    end

    DDL --> DML
    DML --> Perf
    Perf --> Homolog

    style DDL fill:#e3f2fd,stroke:#1976d2,stroke-width:1.5px
    style DML fill:#fffde7,stroke:#fbc02d,stroke-width:1.5px
    style Perf fill:#e8f5e9,stroke:#388e3c,stroke-width:1.5px
    style Homolog fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1.5px

🎯 Engenharia de Requisitos & Modelagem Formal

👤 User Stories (Histórias de Usuário)

ID Persona História de Usuário Critério de Aceite Prioridade
US-01 Engenheiro de Alta Concorrência Desejo implementar o padrão Cache-Aside com Redis Consultar cache primeiro e repovoar sob cache miss a partir do banco Alta
US-02 Arquiteto de Sistemas Desejo estratégia de expiração com TTL e jitter para mitigar cache stampede TTLs probabilísticos evitando que múltiplas chaves expirem simultaneamente Alta
US-03 Desenvolvedor Backend Desejo invalidação seletiva de cache orientada a eventos via Pub/Sub Mensagens de broadcast limpando chaves específicas em atualizações de dados Alta
US-04 DBA de Infraestrutura Desejo política de eviction LRU configurada para gerenciar memória Configuração maxmemory com allkeys-lru prevenindo esgotamento de RAM Média
US-05 Auditor de Performance Desejo testes de estresse comprovando redução de 90% na carga do banco Benchmarks com locust/k6 demonstrando latência sub-milissegundo Média

⚙️ Requisitos Funcionais (RF)

ID Descrição do Requisito Criticidade
RF-01 Mecanismo Cache-Aside integrado com banco relacional e Redis 7.2 Alta
RF-02 Controle inteligente de TTL com técnicas de jitter anti-avalanche Alta
RF-03 Sistema de invalidação atômica via canais Redis Pub/Sub Alta
RF-04 Políticas de particionamento (sharding) e controle de eviction LRU Média
RF-05 Suíte de testes de estresse e verificação de taxas de cache hit Média

🛡️ Requisitos Não-Funcionais (RNF)

ID Especificação Arquitetural Criticidade
RNF-01 Latência de leitura em cache inferior a 2 milissegundos Alta
RNF-02 Consistência eventual garantida em menos de 100ms após mutações Alta
RNF-03 Tolerância a indisponibilidade do Redis com fallback suave para o banco Alta
RNF-04 Ambiente totalmente dockerizado com cluster Redis e backend Média
RNF-05 Código da aplicação isolado na pasta app/ Alta

🔗 Matriz de Rastreabilidade (RTM)

User Story Requisito Funcional Requisito Não-Funcional Módulo / Artefato de Código Status de Homologação
US-01 RF-01 RNF-01, RNF-03 app/cache_service.py Testado
US-02 RF-02 RNF-01, RNF-02 app/cache_service.py Testado
US-03 RF-03 RNF-02, RNF-05 app/pubsub_invalidator.py Testado
US-04 RF-04 RNF-03, RNF-04 app/tuning.sql Testado
US-05 RF-05 RNF-01, RNF-05 tests/test_cache.py Testado

🏁 Checkpoints de Qualidade & Homologação

Checkpoint Escopo da Validação Artefato Verificado Status
CP-01 Subida Conteinerizada do Ambiente docker-compose.yml PASS ✅
CP-02 Criação de Estrutura & Schemas app/ PASS ✅
CP-03 Automação Transacional & Regras Triggers / Queries PASS ✅
CP-04 Otimização de Performance & Índices Indexes / Tuning PASS ✅
CP-05 Homologação com Suíte de Testes tests/ PASS ✅