📚 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.

🌾 Séries Temporais IoT em Alta Escala no Apache Cassandra

v1.0 — Modelagem Query-Driven, Chaves Compostas e Expiração Nativa com TTL

Trilha de Engenharia de Dados & Bancos de Dados — Projeto 6 de 10

🎓 Nível Profissional Simulado: Data Engineer / Distributed Systems Specialist. Em sistemas de telemetria agroindustrial com dezenas de milhares de sensores emitindo dados a cada 5 segundos, a arquitetura distribuída do Cassandra (LSM Trees sem master) garante vazão massiva de escrita e consultas rápidas por partição.


🎯 Objetivo

Desenvolver um modelo de dados colunar orientado a consultas (Query-Driven Modeling) no Apache Cassandra 5.0 para monitoramento de sensores ambientais em silos de grãos, utilizando Chave de Partição Composta ((silo_id, data_leitura), horario), ordenação física em disco (Clustering Order) e expiração de dados com TTL de 60 dias.


🏗️ Diagrama de Particionamento Colunar no Cassandra

graph TD
    classDef ring fill:#1A365D,stroke:#63B3ED,stroke-width:2px,color:#fff;
    classDef part fill:#2A4365,stroke:#90CDF4,stroke-width:1px,color:#fff;
    classDef row fill:#2C5282,stroke:#BEE3F8,stroke-width:1px,color:#fff;

    Ring["🪐 Cassandra Ring (Cluster Distribuído)"]:::ring

    Ring --> P1["📦 Partição: (silo_1, '2026-08-27')"]:::part
    Ring --> P2["📦 Partição: (silo_1, '2026-08-28')"]:::part
    Ring --> P3["📦 Partição: (silo_2, '2026-08-27')"]:::part

    P1 --> R1["🕒 23:59:00 | 24.5°C | 13.2% | CO2: 410 (TTL: 60d)"]:::row
    P1 --> R2["🕒 23:58:00 | 24.6°C | 13.1% | CO2: 412 (TTL: 60d)"]:::row

🧑‍💼 Fase 1 — Levantamento de Requisitos

O Briefing do Cliente (Diretor de Operações de Cooperativa Agrícola)

“Nossos 200 silos armazenam milhões de toneladas de soja e milho. Se a umidade subir ou a temperatura passar de 28°C, os grãos fermentam e o prejuízo é milionário. Temos sensores de temperatura, umidade e CO2 enviando dados sem parar. O banco antigo travava na hora de gravar tantos registros. Precisamos de um banco que suporte milhares de gravações por segundo e que delete automaticamente os dados antigos após 60 dias sem precisar de rotinas pesadas de limpeza.”

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

ID Tipo Descrição Origem no Briefing
RF01 Funcional Gravar leituras de sensores com precisão de timestamp e status de alerta. “sensores enviando dados sem parar”
RF02 Funcional Permitir busca instantânea das medições de um silo em um determinado dia ordenadas da mais recente para a mais antiga. “monitorar temperatura e umidade”
RF03 Funcional Auto-expiração das medições após 60 dias utilizando a diretiva nativa USING TTL. “delete automaticamente após 60 dias”
RNF01 Não-Funcional Modelagem Query-Driven: 1 consulta = 1 partição física (zero scans de cluster). Performance Distribuída
RNF02 Não-Funcional Arquitetura colunar Masterless com tolerância a falhas e alta disponibilidade. Confiabilidade de Safra

📋 Fase 2 — Backlog & User Stories

ID User Story Prioridade
US01 Como sensor IoT, quero persistir medições em milissegundos sem sofrer bloqueio de tabela. Alta
US02 Como agrônomo, quero consultar a curva térmica de um silo em 24h para antecipar focos de calor. Alta
US03 Como arquiteto de infraestrutura, quero que os dados expirem via TTL economizando espaço em disco. Média

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

# Branch da funcionalidade
git checkout -b feature/US01-cassandra-timeseries

# Subir o Cassandra isolado via Docker
docker-compose up -d

# Conectar no console cqlsh
docker exec -it db_cassandra_agro cqlsh -u cassandra -p cassandra

🛠️ Fase 4 — Implementação Passo a Passo (cql/01_schema_keyspace.cql)

CREATE KEYSPACE IF NOT EXISTS agrosense 
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};

CREATE TABLE IF NOT EXISTS agrosense.telemetria_silo (
    silo_id uuid,
    data_leitura date,
    horario timestamp,
    temperatura_graos double,
    umidade_relativa double,
    nivel_co2 double,
    status_alerta text,
    PRIMARY KEY ((silo_id, data_leitura), horario)
) WITH CLUSTERING ORDER BY (horario DESC);

🧭 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_nosql_06_cassandra_timeseries

2. Execute a aplicação ou testes

docker-compose up -d
# Executar a suíte de testes automatizados:
python -m unittest tests/test_cassandra_timeseries.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 proj_aplicacoes_full_stack/projetos/db_nosql_06_cassandra_timeseries


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

-- Inserir telemetria com TTL
INSERT INTO agrosense.telemetria_silo (
    silo_id, data_leitura, horario, temperatura_graos, umidade_relativa, nivel_co2
) VALUES (
    550e8400-e29b-41d4-a716-446655440000,
    '2026-08-27',
    toTimestamp(now()),
    24.5, 13.2, 410.0
) USING TTL 5184000;

-- Consultar exatamente a partição do dia
SELECT horario, temperatura_graos, umidade_relativa 
FROM agrosense.telemetria_silo 
WHERE silo_id = 550e8400-e29b-41d4-a716-446655440000 
  AND data_leitura = '2026-08-27';

✅ Checkpoint Final

  1. Chave de partição composta distribui dados uniformemente no cluster.
  2. Ordenação por Clustering Key permite leitura sequencial direta de disco.
  3. Expiração nativa por TTL evita saturação de armazenamento.
  4. Suíte de testes automatizados com 100% de aprovação.
  5. Docker Compose pronto para deploy de nós distribuídos.

⬅️ Ver Todos os Projetos no Super-Hub 🏠 Página Inicial do Portal