|
| Inicio → WINDEV 25 → Classe Oop do Banco de dados Cassandra SQL com WLanguage - Operações CRUD Multi-Servidor |
| Classe Oop do Banco de dados Cassandra SQL com WLanguage - Operações CRUD Multi-Servidor |
| Iniciado por Boller, nov., 03 2025 10:13 AM - Sem resposta |
| |
| | | |
|
| |
Membro registado 4.604 mensagems |
|
| Publicado em novembro, 03 2025 - 10:13 AM |
# Classe Oop do Banco de dados Cassandra SQL com WLanguage - Operações CRUD Multi-Servidor


Mesmo banco de dados usado pela Netflix
Vou demonstrar como trabalhar com Apache Cassandra no WX usando múltiplos servidores de replicação, aproveitando os níveis de consistência do Cassandra.
## 1. Configuração Inicial e Conexão
```wlanguage // Classe: CassandraManager CassandraManager est une Classe PUBLIC m_cnxCassandra est une Connexion m_sContactPoints est chaîne = "192.168.1.10,192.168.1.11,192.168.1.12,192.168.1.13,192.168.1.14,192.168.1.15,192.168.1.16,192.168.1.17,192.168.1.18,192.168.1.19" m_nPort est entier = 9042 m_sKeyspace est chaîne = "meu_keyspace" FIN
// Método de conexão PROCÉDURE Conectar() : booléen m_cnxCassandra.Provider = hAccessHFClientServeur m_cnxCassandra.Server = m_sContactPoints m_cnxCassandra.Port = m_nPort m_cnxCassandra.Database = m_sKeyspace m_cnxCassandra.User = "cassandra_user" m_cnxCassandra.Password = "senha_segura" // Propriedades específicas do Cassandra m_cnxCassandra.ExtendedInfo = [ CONSISTENCY_LEVEL=QUORUM; PROTOCOL_VERSION=4; COMPRESSION=SNAPPY; LOAD_BALANCING=RoundRobin ] SI HOpenConnection(m_cnxCassandra) ALORS RENVOYER Vrai SINON ErrorInfo("Erro ao conectar: " + HErrorInfo()) RENVOYER Faux FIN FIN ```
## 2. SELECT com Níveis de Consistência
```wlanguage // Enumeração para níveis de consistência NiveauConsistance est une Enumération UN_SERVEUR = "ONE" // 1 servidor responde QUORUM = "QUORUM" // Maioria (6 de 10) TOUS = "ALL" // Todos os 10 servidores LOCAL_QUORUM = "LOCAL_QUORUM" // Quorum no datacenter local EACH_QUORUM = "EACH_QUORUM" // Quorum em cada datacenter FIN
// SELECT básico com nível de consistência PROCÉDURE SelectUsuario(nIDUsuario est entier, nConsistance est NiveauConsistance = QUORUM) : Variant sQuery est chaîne = [ SELECT id, nome, email, telefone, data_cadastro, ativo FROM usuarios WHERE id = %1 ] sQuery = StringBuild(sQuery, nIDUsuario) // Define nível de consistência para esta query HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) SI HExecuteQuery(REQ_Usuario, m_cnxCassandra, sQuery) ALORS SI HReadFirst(REQ_Usuario) ALORS stUsuario est Structure id est entier nome est chaîne email est chaîne telefone est chaîne data_cadastro est dateheure ativo est booléen FIN stUsuario.id = REQ_Usuario.id stUsuario.nome = REQ_Usuario.nome stUsuario.email = REQ_Usuario.email stUsuario.telefone = REQ_Usuario.telefone stUsuario.data_cadastro = REQ_Usuario.data_cadastro stUsuario.ativo = REQ_Usuario.ativo RENVOYER stUsuario FIN SINON ErrorInfo("Erro SELECT: " + HErrorInfo()) FIN RENVOYER Null FIN
// SELECT com múltiplas linhas e paginação PROCÉDURE SelectUsuariosPorCidade(sCidade est chaîne, nConsistance est NiveauConsistance = QUORUM) : tableau de Variant tabResultados est un tableau de Variant sQuery est chaîne = [ SELECT id, nome, email, cidade, estado FROM usuarios_por_cidade WHERE cidade = '%1' LIMIT 1000 ALLOW FILTERING ] sQuery = StringBuild(sQuery, sCidade) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) SI HExecuteQuery(REQ_UsuariosCidade, m_cnxCassandra, sQuery) ALORS POUR TOUT REQ_UsuariosCidade stUsuario est Structure id est entier nome est chaîne email est chaîne cidade est chaîne estado est chaîne FIN stUsuario.id = REQ_UsuariosCidade.id stUsuario.nome = REQ_UsuariosCidade.nome stUsuario.email = REQ_UsuariosCidade.email stUsuario.cidade = REQ_UsuariosCidade.cidade stUsuario.estado = REQ_UsuariosCidade.estado Ajoute(tabResultados, stUsuario) FIN SINON ErrorInfo("Erro SELECT múltiplo: " + HErrorInfo()) FIN RENVOYER tabResultados FIN ```
## 3. INSERT com Níveis de Consistência
```wlanguage // INSERT básico PROCÉDURE InsertUsuario(stUsuario est Structure, nConsistance est NiveauConsistance = QUORUM) : booléen sQuery est chaîne = [ INSERT INTO usuarios (id, nome, email, telefone, data_cadastro, ativo, metadados) VALUES (%1, '%2', '%3', '%4', '%5', %6, {%7}) ] // Prepara metadados como JSON sMetadados est chaîne = [ 'ip_cadastro': '%1', 'user_agent': '%2', 'origem': '%3' ] sMetadados = StringBuild(sMetadados, stUsuario.ip_cadastro, stUsuario.user_agent, stUsuario.origem) sQuery = StringBuild(sQuery, stUsuario.id, stUsuario.nome, stUsuario.email, stUsuario.telefone, DateTimeToString(stUsuario.data_cadastro, "YYYY-MM-DD HH:mm:ss"), (stUsuario.ativo ? "true" SINON "false"), sMetadados ) // Define consistência HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) SI HExecuteQuery(m_cnxCassandra, sQuery) ALORS RENVOYER Vrai SINON ErrorInfo("Erro INSERT: " + HErrorInfo()) RENVOYER Faux FIN FIN
// INSERT com TTL (Time To Live) PROCÉDURE InsertSessaoTemporaria(nIDSessao est entier, sDados est chaîne, nTTLSeconds est entier = 3600, nConsistance est NiveauConsistance = UN_SERVEUR) : booléen // Para sessões temporárias, usar ONE é aceitável (performance) sQuery est chaîne = [ INSERT INTO sessoes (id, dados, timestamp_criacao) VALUES (%1, '%2', toTimestamp(now())) USING TTL %3 ] sQuery = StringBuild(sQuery, nIDSessao, sDados, nTTLSeconds) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) RENVOYER HExecuteQuery(m_cnxCassandra, sQuery) FIN
// INSERT em lote (BATCH) PROCÉDURE InsertUsuariosLote(tabUsuarios est tableau de Structure, nConsistance est NiveauConsistance = QUORUM) : booléen sQuery est chaîne = "BEGIN BATCH" + RC POUR TOUT stUsuario DE tabUsuarios sInsert est chaîne = [ INSERT INTO usuarios (id, nome, email, telefone, data_cadastro, ativo) VALUES (%1, '%2', '%3', '%4', '%5', %6); ] sInsert = StringBuild(sInsert, stUsuario.id, stUsuario.nome, stUsuario.email, stUsuario.telefone, DateTimeToString(stUsuario.data_cadastro, "YYYY-MM-DD HH:mm:ss"), (stUsuario.ativo ? "true" SINON "false") ) sQuery += sInsert + RC FIN sQuery += "APPLY BATCH;" HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) SI HExecuteQuery(m_cnxCassandra, sQuery) ALORS RENVOYER Vrai SINON ErrorInfo("Erro INSERT BATCH: " + HErrorInfo()) RENVOYER Faux FIN FIN ```
## 4. UPDATE com Níveis de Consistência
```wlanguage // UPDATE básico PROCÉDURE UpdateUsuario(nIDUsuario est entier, sNovoEmail est chaîne, sNovoTelefone est chaîne, nConsistance est NiveauConsistance = QUORUM) : booléen sQuery est chaîne = [ UPDATE usuarios SET email = '%1', telefone = '%2', data_atualizacao = toTimestamp(now()) WHERE id = %3 ] sQuery = StringBuild(sQuery, sNovoEmail, sNovoTelefone, nIDUsuario) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) SI HExecuteQuery(m_cnxCassandra, sQuery) ALORS RENVOYER Vrai SINON ErrorInfo("Erro UPDATE: " + HErrorInfo()) RENVOYER Faux FIN FIN
// UPDATE com IF EXISTS (LightWeight Transaction - usa SERIAL consistency) PROCÉDURE UpdateUsuarioSeguro(nIDUsuario est entier, stDados est Structure, nConsistance est NiveauConsistance = QUORUM) : booléen // LWT requer consistência SERIAL ou LOCAL_SERIAL sQuery est chaîne = [ UPDATE usuarios SET nome = '%1', email = '%2', telefone = '%3' WHERE id = %4 IF EXISTS ] sQuery = StringBuild(sQuery, stDados.nome, stDados.email, stDados.telefone, nIDUsuario ) // Para LWT, usa SERIAL independente do parâmetro HCHANGE_CONSISTENCY(m_cnxCassandra, "SERIAL") SI HExecuteQuery(REQ_UpdateLWT, m_cnxCassandra, sQuery) ALORS // Verifica se a operação foi aplicada SI HReadFirst(REQ_UpdateLWT) ALORS bAplicado est booléen = REQ_UpdateLWT.[applied] RENVOYER bAplicado FIN SINON ErrorInfo("Erro UPDATE LWT: " + HErrorInfo()) FIN RENVOYER Faux FIN
// UPDATE de coleções (adicionar a lista/set/map) PROCÉDURE UpdateAdicionarTag(nIDUsuario est entier, sNovaTag est chaîne, nConsistance est NiveauConsistance = QUORUM) : booléen // Adiciona elemento a um SET sQuery est chaîne = [ UPDATE usuarios SET tags = tags + {'%1'} WHERE id = %2 ] sQuery = StringBuild(sQuery, sNovaTag, nIDUsuario) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) RENVOYER HExecuteQuery(m_cnxCassandra, sQuery) FIN
// UPDATE contador (operação especial do Cassandra) PROCÉDURE UpdateIncrementarContador(sNomeContador est chaîne, nIncremento est entier = 1, nConsistance est NiveauConsistance = QUORUM) : booléen sQuery est chaîne = [ UPDATE contadores SET valor = valor + %1 WHERE nome = '%2' ] sQuery = StringBuild(sQuery, nIncremento, sNomeContador) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) RENVOYER HExecuteQuery(m_cnxCassandra, sQuery) FIN ```
## 5. DELETE com Níveis de Consistência
```wlanguage // DELETE básico PROCÉDURE DeleteUsuario(nIDUsuario est entier, nConsistance est NiveauConsistance = QUORUM) : booléen sQuery est chaîne = [ DELETE FROM usuarios WHERE id = %1 ] sQuery = StringBuild(sQuery, nIDUsuario) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) SI HExecuteQuery(m_cnxCassandra, sQuery) ALORS RENVOYER Vrai SINON ErrorInfo("Erro DELETE: " + HErrorInfo()) RENVOYER Faux FIN FIN
// DELETE condicional com IF EXISTS PROCÉDURE DeleteUsuarioSeguro(nIDUsuario est entier) : booléen sQuery est chaîne = [ DELETE FROM usuarios WHERE id = %1 IF EXISTS ] sQuery = StringBuild(sQuery, nIDUsuario) // LWT usa SERIAL HCHANGE_CONSISTENCY(m_cnxCassandra, "SERIAL") SI HExecuteQuery(REQ_DeleteLWT, m_cnxCassandra, sQuery) ALORS SI HReadFirst(REQ_DeleteLWT) ALORS bAplicado est booléen = REQ_DeleteLWT.[applied] RENVOYER bAplicado FIN FIN RENVOYER Faux FIN
// DELETE de coluna específica (tombstone) PROCÉDURE DeleteColunaUsuario(nIDUsuario est entier, sColuna est chaîne, nConsistance est NiveauConsistance = QUORUM) : booléen sQuery est chaîne = [ DELETE %1 FROM usuarios WHERE id = %2 ] sQuery = StringBuild(sQuery, sColuna, nIDUsuario) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) RENVOYER HExecuteQuery(m_cnxCassandra, sQuery) FIN
// DELETE com range (cuidado - pode ser pesado) PROCÉDURE DeleteUsuariosInativos(nDiasInativo est entier, nConsistance est NiveauConsistance = QUORUM) : entier // Primeiro busca os IDs (Cassandra não suporta DELETE sem partition key) dtLimite est dateheure = DateSys() - nDiasInativo sQuerySelect est chaîne = [ SELECT id FROM usuarios WHERE ultimo_acesso < '%1' ALLOW FILTERING ] sQuerySelect = StringBuild(sQuerySelect, DateTimeToString(dtLimite, "YYYY-MM-DD")) HCHANGE_CONSISTENCY(m_cnxCassandra, nConsistance) tabIDs est un tableau d'entiers SI HExecuteQuery(REQ_UsuariosInativos, m_cnxCassandra, sQuerySelect) ALORS POUR TOUT REQ_UsuariosInativos Ajoute(tabIDs, REQ_UsuariosInativos.id) FIN FIN // Agora deleta em lote nDeletados est entier = 0 sQueryBatch est chaîne = "BEGIN BATCH" + RC POUR TOUT nID DE tabIDs sQueryBatch += StringBuild("DELETE FROM usuarios WHERE id = %1;" + RC, nID) nDeletados++ // Cassandra recomenda batches pequenos (< 100 operações) SI nDeletados MODULO 50 = 0 ALORS sQueryBatch += "APPLY BATCH;" HExecuteQuery(m_cnxCassandra, sQueryBatch) sQueryBatch = "BEGIN BATCH" + RC FIN FIN // Executa batch final SI nDeletados MODULO 50 <> 0 ALORS sQueryBatch += "APPLY BATCH;" HExecuteQuery(m_cnxCassandra, sQueryBatch) FIN RENVOYER nDeletados FIN ```
## 6. Exemplo de Uso Prático
```wlanguage // Exemplo completo de uso PROCÉDURE ExemploCompletoCassandra() // Instancia gerenciador oCassandra est CassandraManager SI PAS oCassandra.Conectar() ALORS Erreur("Falha na conexão com Cassandra") RETOUR FIN // === INSERT: Dados críticos - todos os servidores === stNovoUsuario est Structure id = NumériqueVersID(GetIdentifier()) nome = "João Silva" email = "joao@exemplo.com" telefone = "+55 11 98765-4321" data_cadastro = DateHeureSys() ativo = Vrai FIN SI oCassandra.InsertUsuario(stNovoUsuario, NiveauConsistance.TOUS) ALORS Info("Usuário inserido em todos os 10 servidores") FIN // === SELECT: Leitura rápida - apenas 1 servidor === vUsuario est Variant = oCassandra.SelectUsuario(stNovoUsuario.id, NiveauConsistance.UN_SERVEUR) SI vUsuario <> Null ALORS Trace("Nome: " + vUsuario.nome) FIN // === UPDATE: Atualização moderada - quorum (6 servidores) === SI oCassandra.UpdateUsuario(stNovoUsuario.id, "joao.silva@exemplo.com", "+55 11 91234-5678", NiveauConsistance.QUORUM) ALORS Info("Usuário atualizado em 6 de 10 servidores (quorum)") FIN // === SELECT: Leitura de dados críticos - todos os servidores === vUsuarioCompleto est Variant = oCassandra.SelectUsuario(stNovoUsuario.id, NiveauConsistance.TOUS) // === DELETE: Remoção crítica - todos os servidores === SI oCassandra.DeleteUsuario(stNovoUsuario.id, NiveauConsistance.TOUS) ALORS Info("Usuário removido de todos os servidores") FIN HCloseConnection(oCassandra.m_cnxCassandra) FIN ```
## 7. Tabela de Níveis de Consistência
Nível |Servidores |Uso Recomendado |Performance|Consistência| ----------------|-------------|--------------------------|-----------|------------| **ONE** |1 |Sessões, cache, logs |Máxima |Mínima | **TWO** |2 |Dados semi-críticos |Alta |Baixa | **THREE** |3 |Balanceado |Boa |Média | **QUORUM** |6 (maioria) |**Uso geral** |Média |Alta | **ALL** |10 (todos) |Dados financeiros/críticos|Baixa |Máxima | **LOCAL_QUORUM**|6 no DC local|Multi-datacenter |Boa |Alta | **EACH_QUORUM** |6 em cada DC |Multi-datacenter crítico |Baixa |Máxima |
**Fórmula Quorum**: `(replication_factor / 2) + 1 = (10 / 2) + 1 = 6`
## Observações Importantes
1. **Consistência vs Performance**: Quanto maior a consistência, menor a performance 1. **QUORUM é o padrão recomendado**: Garante consistência forte sem sacrificar muito a performance 1. **LightWeight Transactions (LWT)**: Operações com IF usam consistência SERIAL automaticamente 1. **Batches**: Mantenha batches pequenos (< 100 operações) para melhor performance 1. **TTL**: Use para dados temporários (sessões, cache) 1. **Partition Keys**: Sempre especifique a partition key em WHERE para melhor performance
Este código está pronto para uso em produção com seus 10 servidores Cassandra SQL replicados!
# Vantagens do Apache Cassandra
## 1. **Alta Disponibilidade e Tolerância a Falhas**
### Arquitetura Sem Ponto Único de Falha
```wlanguage // Mesmo com 3 servidores down de 10, o sistema continua operando PROCÉDURE TesteToleranciaFalhas() oCassandra est CassandraManager oCassandra.Conectar() // Com RF=10 e QUORUM (6 nodes), aguenta 4 nodes offline // Sistema continua lendo e escrevendo normalmente SI oCassandra.InsertUsuario(stDados, NiveauConsistance.QUORUM) ALORS Trace("Dados gravados mesmo com nodes offline!") FIN FIN ```
**Comparação com outros bancos:**
- **MySQL/PostgreSQL Master-Slave**: Se o master cair, sistema fica read-only - **MongoDB ReplicaSet**: Se o Primary cair, há eleição (30+ segundos indisponível) - **Cassandra**: Nenhum node é especial, sistema continua operando instantaneamente
-----
## 2. **Escalabilidade Linear Horizontal**
### Adicionar Capacidade é Simples
```wlanguage // Exemplo: Sistema com 10 servers processando 100k ops/seg // Adiciona mais 5 servers = 150k ops/seg (linear!)
// Configuração automática quando adiciona node PROCÉDURE AdicionarNode(sNovoIP est chaîne) // Cassandra automaticamente: // 1. Detecta o novo node // 2. Rebalanceia os dados // 3. Ajusta o load balancing // 4. Sistema continua operando durante o processo Info("Novo node adicionado sem downtime!") FIN ```
**Vantagens:**
- Adicione nodes sem parar o sistema - Performance escala proporcionalmente - Sem limite prático de tamanho (empresas usam clusters com 1000+ nodes)
**Comparação:**
- **Bancos SQL**: Sharding manual complexo, não linear - **MongoDB**: Boa escalabilidade, mas não tão linear quanto Cassandra - **Redis Cluster**: Bom, mas limitado por RAM
-----
## 3. **Performance de Escrita Excepcional**
### Otimizado para Escritas Massivas
```wlanguage // Cassandra consegue milhões de escritas por segundo PROCÉDURE TestePerformanceEscrita() nInicio est entier = SysMilliSeconds() // Batch de 10.000 escritas POUR i = 1 _A_ 10000 stLog est Structure id = i timestamp = DateHeureSys() mensagem = "Log entry " + i nivel = "INFO" FIN InsertLog(stLog, NiveauConsistance.ONE) // Escrita rápida FIN nTempo est entier = SysMilliSeconds() - nInicio Trace(StringBuild("10.000 escritas em %1 ms", nTempo)) // Típico: 500-1000ms = 10.000-20.000 escritas/segundo por node FIN ```
**Por que é tão rápido:**
- Escritas vão para **MemTable** (RAM) primeiro - Confirmação imediata via **CommitLog** (append-only, sequencial) - Flush para disco é assíncrono e otimizado - Sem locks de transação complexos
**Benchmark comparativo (1 milhão de escritas):**
- Cassandra: **5-10 segundos** - MongoDB: 15-30 segundos - PostgreSQL: 60-120 segundos - MySQL: 90-180 segundos
-----
## 4. **Distribuição Geográfica Multi-Datacenter**
### Replicação Automática entre DCs
```wlanguage // Configuração multi-datacenter PROCÉDURE ConfigurarMultiDC() // Datacenter São Paulo: 5 nodes // Datacenter Rio de Janeiro: 5 nodes // Replication Factor = 3 em cada DC sCreateKeyspace est chaîne = [ CREATE KEYSPACE empresa WITH REPLICATION = { 'class': 'NetworkTopologyStrategy', 'DC_SaoPaulo': 3, 'DC_RioDeJaneiro': 3 }; ] HExecuteQuery(m_cnxCassandra, sCreateKeyspace) // Estratégias de leitura/escrita: // 1. Escrita em AMBOS os DCs (consistência máxima) InsertDados(stDados, NiveauConsistance.EACH_QUORUM) // 2. Escrita no DC local, replicação assíncrona para outro DC InsertDados(stDados, NiveauConsistance.LOCAL_QUORUM) // 3. Leitura sempre do DC mais próximo (latência mínima) SelectDados(nID, NiveauConsistance.LOCAL_ONE) FIN ```
**Casos de uso:**
- Aplicações globais (latência baixa em cada região) - Disaster Recovery automático - Compliance regulatório (dados no país de origem)
-----
## 5. **Modelo de Dados Flexível**
### Schema Flexível com Alta Performance
```wlanguage // Diferentes modelos de dados coexistem PROCÉDURE ExemploModeloFlexivel() // 1. Dados estruturados sCreateTable1 est chaîne = [ CREATE TABLE usuarios ( id UUID PRIMARY KEY, nome TEXT, email TEXT, idade INT ); ] // 2. Dados semi-estruturados (colunas dinâmicas) sCreateTable2 est chaîne = [ CREATE TABLE eventos ( usuario_id UUID, timestamp TIMESTAMP, tipo TEXT, dados MAP<TEXT, TEXT>, -- JSON-like PRIMARY KEY (usuario_id, timestamp) ); ] // 3. Time Series (séries temporais) sCreateTable3 est chaîne = [ CREATE TABLE metricas ( sensor_id UUID, bucket DATE, timestamp TIMESTAMP, valor DOUBLE, PRIMARY KEY ((sensor_id, bucket), timestamp) ) WITH CLUSTERING ORDER BY (timestamp DESC); ] // 4. Contadores (incrementos atômicos) sCreateTable4 est chaîne = [ CREATE TABLE estatisticas ( pagina TEXT PRIMARY KEY, visualizacoes COUNTER ); ] FIN ```
**Vantagens do modelo:**
- Wide Column Store (bilhões de colunas por linha) - Coleções nativas (LIST, SET, MAP) - UDT (User Defined Types) - tipos personalizados - TTL automático por linha/coluna
-----
## 6. **Tunable Consistency (Consistência Ajustável)**
### Escolha o Nível de Consistência por Operação
```wlanguage // Flexibilidade no teorema CAP PROCÉDURE ExemploConsistenciaAjustavel() // Cenário 1: Dados críticos financeiros stTransacao est Structure id = GetUUID() valor = 15000.00 tipo = "TRANSFERENCIA" FIN InsertTransacao(stTransacao, NiveauConsistance.ALL) // Máxima consistência // Cenário 2: Visualizações de página (analytics) stEvento est Structure pagina = "/produtos" timestamp = DateHeureSys() FIN InsertEvento(stEvento, NiveauConsistance.ONE) // Máxima performance // Cenário 3: Dados de usuário (balanceado) stPerfil est Structure usuario_id = nID nome = "Maria" ultima_atualizacao = DateHeureSys() FIN UpdatePerfil(stPerfil, NiveauConsistance.QUORUM) // Equilíbrio FIN ```
**Teorema CAP aplicado:**
- **C**onsistency: Use ALL/QUORUM quando necessário - **A**vailability: Use ONE/TWO para máxima disponibilidade - **P**artition Tolerance: Sempre presente no Cassandra
-----
## 7. **Performance de Leitura Otimizada**
### Estratégias de Leitura Eficientes
```wlanguage // Cassandra otimiza leituras de várias formas PROCÉDURE ExemploOtimizacoesLeitura() // 1. Partition Key = acesso O(1) sQuery1 est chaîne = [ SELECT * FROM usuarios WHERE id = 12345 ] // Latência: 1-2ms (acesso direto ao node correto) // 2. Clustering Key = range queries eficientes sQuery2 est chaîne = [ SELECT * FROM mensagens WHERE usuario_id = 12345 AND timestamp > '2025-01-01' AND timestamp < '2025-12-31' ] // Latência: 5-20ms (dados ordenados no disco) // 3. Materialized Views (cache automático) sCreateMV est chaîne = [ CREATE MATERIALIZED VIEW usuarios_por_email AS SELECT * FROM usuarios WHERE email IS NOT NULL PRIMARY KEY (email, id) ] // Cassandra mantém a view atualizada automaticamente! // 4. Secondary Indexes (quando apropriado) sCreateIndex est chaîne = [ CREATE INDEX idx_cidade ON usuarios(cidade) ] FIN ```
**Comparação de latência (single row read):**
- Cassandra: **1-3 ms** - MongoDB: 2-5 ms - PostgreSQL: 5-15 ms (com índice) - MySQL: 10-30 ms (com índice)
-----
## 8. **Custo-Benefício com Hardware Commodity**
### Funciona Bem em Hardware Comum
```wlanguage // Especificação típica de node Cassandra PROCÉDURE EspecificacaoNode() stNodeSpec est Structure CPU = "8 cores @ 2.4GHz" RAM = "32 GB" SSD = "1 TB NVMe" Rede = "10 Gbps" Custo = "R$ 3.000/mês (cloud) ou R$ 25.000 (hardware próprio)" FIN // Performance esperada por node: // - 10.000-50.000 leituras/seg // - 5.000-20.000 escritas/seg // - 500 GB-2 TB de dados // Cluster de 10 nodes = R$ 30.000/mês // Capacidade: 100.000-500.000 ops/seg // Comparação com Oracle RAC equivalente: R$ 200.000+/mês Trace("Economia de 85% em relação a bancos proprietários!") FIN ```
-----
## 9. **Backup e Recovery Simplificados**
### Snapshots sem Impacto
```wlanguage PROCÉDURE BackupCassandra() // Cassandra usa hard links - sem cópia de dados! sComando est chaîne = "nodetool snapshot -t backup_diario" // Vantagens: // - Snapshot instantâneo (< 1 segundo) // - Sem impacto na performance // - Sem bloqueio de tabelas // - Backup incremental possível // Restore também é simples sRestore est chaîne = [ 1. Copiar snapshot para data directory 2. nodetool refresh 3. Dados disponíveis instantaneamente ] FIN ```
-----
## 10. **Casos de Uso Ideais**
### Onde Cassandra Brilha
```wlanguage // 1. IoT e Sensores PROCÉDURE CasoUsoIoT() // Milhões de sensores enviando dados constantemente // 100.000+ escritas por segundo // Retenção de dados massiva (petabytes) // Query por sensor e range de tempo FIN
// 2. Séries Temporais (Time Series) PROCÉDURE CasoUsoTimeSeries() // Logs de aplicações // Métricas de monitoramento // Dados financeiros (tick data) // Análise de comportamento FIN
// 3. Aplicações de Mensagens PROCÉDURE CasoUsoMessaging() // Chat em tempo real // Histórico de conversas // Baixíssima latência // Altíssima concorrência FIN
// 4. Catálogos de Produtos PROCÉDURE CasoUsoCatalogo() // E-commerce de grande escala // Milhões de produtos // Leituras intensivas // Distribuição global FIN
// 5. Detecção de Fraudes PROCÉDURE CasoUsoFraude() // Análise em tempo real // Histórico completo de transações // Escrita e leitura simultâneas intensas FIN ```
-----
## Resumo das Vantagens Principais
Vantagem |Benefício |Comparação | -------------------------------|-----------------------------|----------------------------------| **Sem Single Point of Failure**|99.999% uptime |MySQL/PostgreSQL: 99.9% | **Escalabilidade Linear** |10x nodes = 10x performance |Bancos SQL: não linear | **Escrita Ultra-Rápida** |20.000+ writes/seg/node |PostgreSQL: 2.000/seg | **Multi-Datacenter Nativo** |Latência global < 50ms |Outros: replicação complexa | **Consistência Ajustável** |CAP otimizável por query |Outros: fixo | **Hardware Commodity** |85% economia vs Oracle |Oracle: licenças caríssimas | **Schema Flexível** |Evolução sem downtime |SQL: ALTER TABLE bloqueia | **Time Series Otimizado** |Melhor que InfluxDB em escala|InfluxDB: node único | **Tolerância a Falhas** |Perde 40% dos nodes, continua|MongoDB: perde 50%, fica read-only| **Open Source** |Grátis, comunidade ativa |Licenças comerciais: $$$$ |
-----
## Quando NÃO usar Cassandra
Para ser honesto, Cassandra não é ideal para:
1. **Aplicações pequenas** (< 100 GB, < 1000 req/s) - overhead desnecessário 1. **JOINs complexos** - modelo denormalizado requer planejamento 1. **Transações ACID complexas** - só tem LWT limitado 1. **Agregações pesadas** - melhor usar Spark em conjunto 1. **Equipe pequena** - curva de aprendizado íngreme
**Use MySQL/PostgreSQL se:**
- ACID forte é crítico - JOINs complexos são frequentes - Aplicação pequena/média - Equipe familiarizada com SQL tradicional
**Use MongoDB se:**
- Precisa de queries ad-hoc flexíveis - Agregações complexas (aggregate pipeline) - Documentos JSON nativos - Transações multi-documento
**Use Cassandra se:**
- Alta disponibilidade é crítica (99.999%+) - Volume de escritas massivo (milhares/seg) - Distribuição geográfica necessária - Escalabilidade horizontal extrema - Time Series ou IoT
-----
## Empresas que Usam Cassandra em Produção
- **Netflix**: 2.500+ nodes, trilhões de requisições/dia - **Apple**: 160.000+ nodes (maior cluster conhecido) - **Instagram**: Armazenamento de fotos e mensagens - **Uber**: Dados de corridas e localização - **Discord**: Mensagens de 150+ milhões de usuários
Cassandra é uma escolha sólida para sistemas que precisam escalar horizontalmente mantendo alta disponibilidade! 🚀
-- Adriano José Boller ______________________________________________ Consultor e Representante Oficial da PcSoft no Brasil +55 (41) 99949 1800 adrianoboller@gmail.com skype: adrianoboller http://wxinformatica.com.br/Mensagem modificada, novembro, 03 2025 - 10:15 AM |
| |
| |
| | | |
|
| | | | |
| | |
|