GH GambleHub

CQRS e divisão de leitura/escrita

O que é CQRS

O CQRS (Command Query Responability Segregation) é uma abordagem arquitetônica que separa o modelo de dados e os componentes de gravação (commands) e leitura (queries).
A ideia é que o processo de alteração de estado seja otimizado para invariantes e transações validadas, e a leitura para projeções rápidas, com destino e escala.

💡 Os comandos alteram o status e devolvem o resultado da operação. Os pedidos são apenas lidos e não têm efeitos colaterais.

Para quê é preciso

Desempenho de leitura: projeções materializadas sob cenários específicos (fitas, relatórios, diretórios).
Estabilidade da via crítica, a gravação está isolada dos joins e equipamentos pesados.
Escolha de armazenamento: OLTP para gravação, OLAP/kesh/motores de busca para leitura.
Evolução acelerada: Adicione novas visões sem o risco de «quebrar» transações.
Observabilidade e auditoria (especialmente na ligação com o Event Surcing): é mais fácil restaurar e reinventar o estado.


Quando aplicar (e quando não aplicar)

Adequado se:
  • As leituras com diferentes cortes de dados e agregação complexa prevalecem.
  • O caminho crítico de gravação deve ser fino e previsível.
  • Você precisa de SLO/SLA diferentes para leitura e gravação.
  • É necessário isolar a lógica de registro do domínio das necessidades analíticas/de busca.
Não é adequado se:
  • O domínio é simples, a carga é baixa; A CRUD está a lidar.
  • Uma forte coerência entre leitura e gravação é obrigatória para todos os cenários.
  • A equipa é inexperiente e a complexidade operacional é inaceitável.

Conceitos básicos

Comando (Command): a intenção é alterar o status ('CreateOrder', 'CapturePayment'). A verificar os invariantes.
Consulta (Query): obtenção de dados ('GetOrderById', 'ListUserTransactions'). Sem efeitos colaterais.
Modelo de gravação: unidades/invariantes/transações; armazenamento - relacional/chave-valor/logs de evento.
Modelo de leitura (projeções): tabelas/índices/kesh materializadas, sincronizadas de forma asincrona.
Coerência: muitas vezes, o eventual entre a gravação e a leitura; caminhos críticos - através da leitura direta do modelo write.


Arquitetura (esqueleto)

1. Serviço Write: aceita comandos, valida invariantes, registra alterações (BB ou eventos).
2. Outbox/CDC: publicação garantida de alterações.
3. Processadores de projeção: escutam eventos/CDC e atualizam modelos read.
4. Serviço de read: serve querias a partir de visualizações materializadas/cajas/buscas.
5. Sagas/Orquestra: Coordenam processos cruzados.
6. Observabilidade: lâmina de projeções, porcentagem de aplicações bem sucedidas, DLQ.


Projetar modelo de gravação

Unidades: limites de transação nítidos (por exemplo, «Order», «Payment», «UserBalance»).
Invariantes: formalize (somas em dinheiro ≥ 0, exclusividade, limites).
Os comandos são idimpotentes à chave (por exemplo, 'idempotency _ key').
Transações são mínimas em abrangência; Efeitos secundários externos - via outbox.

Exemplo de comando (pseudo-JSON)

json
{
"command": "CapturePayment",
"payment_id": "pay_123",
"amount": 1000,
"currency": "EUR",
"idempotency_key": "k-789",
"trace_id": "t-abc"
}

Projetar modelo de leitura

Afaste as solicitações: quais telas/relatórios são necessários?
A denormização é válida, o modelo read é «dinheiro otimizado».
Várias projeções para diferentes tarefas: pesquisa (OpenSearch), relatórios (armazenamento de coluna), cartões (KV/Redis).
TTL e intersecção: as projeções devem ser capazes de recuperar da origem (replicações de eventos/eventos).


Coerência e UX

Eventual consistency: a interface pode exibir dados antigos brevemente.
Pattern UX: «dados são atualizados»..., UI optimístico, indicadores de sincronização, bloqueio de ações perigosas antes da confirmação.
Para as operações que exigem coerência forte (por exemplo, mostrar o balanço exato antes de cancelar), leia diretamente no modelo write.


CQRS e Event Surcing (opcional)

O Event Surcing (ES) armazena eventos e o estado do aparelho é resultado do seu encolhimento.
A ligação CQRS + ES fornece uma auditoria perfeita e um cruzamento fácil de projeções, mas aumenta a complexidade.
Alternativa: normal OLTP-BD + outbox/CDC → projeção.


Replicação: Outbox e CDC

Outbox (em uma transação): gravação de alterações de domínio + gravação de evento em outbox; O pablicher é entregue no pneu.
CDC: leitura a partir de logs de BD (Debezium etc.) → transformação em eventos de domínio.
Garantia: por padrão at-least-once, os consumidores e projeções devem ser idimpotentes.


Selecionar armazenamento

Write: relacional (PostgreSQL/MySQL) para transações; KV/Photo - onde os invariantes são simples.

Read:
  • KV/Redis - cartões e leituras-chave rápidas;
  • Pesquisa (OpenSearch/Elasticsearch) - pesquisa/filtros/facetas;
  • Colunas (ClickHouse/BigQuery) - relatórios;
  • Kesh em CDN - diretórios públicos/conteúdo.

Pattern de integração

Camada API: endpoints/serviços individuais para 'commands' e 'quéries'.
Idempotidade: chave da operação no cabeçalho/corpo; armazenamento de recent-keys com TTL.
Sagas/Orquestra: tempo, compensações, repetição de passos.
Backpressure: limitação do paralelismo dos processadores de projeção.


Observabilidade

Métricas write: p95/99 latência de comandos, proporção de transações bem sucedidas, erros de validação.
Métricas de read: p95/99 consultas, hit-rate kesha, carga do cluster de busca.
Projeções (tempo e mensagens), taxa DLQ, porcentagem de deduções.
Tracing: 'trace _ id' passa pelo comando → outbox → projeção de → query.


Segurança e Complacência

Separação de direitos: diferentes scopes/papéis de escrita e leitura; o princípio dos menores privilégios.
PII/PCI: minimize nas projeções; criptografia at-rest/in-flight; camuflagem.
Auditoria: verifique o comando, o ator, o resultado, 'trace _ id'; arquivos WORM para domínios críticos (pagamentos, KYC).


Testes

Contracto testes: para comandos (erros, invariantes) e queries (formatos/filtros).
Project tests: Apresente uma série de eventos/CDC e verifique o modelo read final.
Chaos/latency: injeção de atrasos nos processadores de projeção; verificação de UX na laje.
Replayability: cruzamento de projeções no estande de snapshots/logs.


Migração e evolução

Novos campos - adutor no evento/CDC; modelos read são reencontrados.
Gravação dupla (dual-write) em redesenhos de padrão; Temos projeções antigas até mudar.
Versioning: 'v1 '/' v2' eventos e endpoints, plano sunset.
Função flags: digite novas quéries/projeções de canário.


Antipattern

CQRS «para a moda» em serviços CRUD simples.
Severa dependência sincronizada de leitura da escrita (mata isolamento e resistência).
Um índice para tudo é misturar consultas heterogéneas em uma read-store.
Não há idempotidade nas projeções de duplicação e discrepância.
Projeções não remodeladas (sem replay/snapshot).


Exemplos de domínios

Pagamentos (serviço online)

Write: 'Athorize', 'Capture', 'Refund' no banco de dados de transação; outbox publica 'payment'.

Read:
  • Redis «cartão de pagamento» para UI;
  • ClickHouse para relatórios;
  • Para encontrar transações.
  • Caminho crítico: autorização ≤ 800 ms p95; coerência de leitura para UI - eventual (até 2-3 c).

KYC

Write: comandos de início/update de status; armazenamento de PII em um BD protegido.
Read: projeção facilitada de estatais sem PII; O PII é puxado por pontos quando necessário.
Segurança: scopes diferentes para leitura de status e acesso a documentos.

Balanços (iGaming/Finanças)

Write: unidade 'UserBalance', com encrencas atômicas/decrementos; chaves idoneais para a cirurgia.
Read: kesh para «equilíbrio rápido»; para cancelar - leitura direta de write (coerência rigorosa).
Os depósitos/conclusões são coordenados por eventos, e as indemnizações por falhas.


Folha de cheque de implementação

  • As unidades e invariantes do modelo write são selecionados.
  • Quéries-chave foram definidas e projectadas sob elas.
  • Os processadores de projeção outbox/CDC e idumpotentes estão configurados.
  • Há um plano para cruzar projeções (snapshot/replay).
  • SLO: Latidão dos comandos, claridade das projeções, disponibilidade de read/write individualmente.
  • As permissões de acesso e a criptografia de dados foram compartilhadas.
  • Alertas em DLQ/liga/falhas de dedução.
  • Testes: contratos, projeções, caos, réplicas.

FAQ

O Event Surcing é necessário para o CQRS?
Não. Você pode construir em um BD + outbox/CDC convencional.

Como lutar contra a secessão?
Claramente projetar UX, medir projeções de liga, deixar operações críticas ler a partir de write.

É possível manter write e read em um único serviço?
Sim, separação física - opcional; a divisão lógica da responsabilidade é obrigatória.

E as transações entre as unidades?
Através de sagas e eventos; evite transações distribuídas, se possível.


Resultado

O CQRS desenrola as mãos, um caminho de gravação fino e confiável, com invariantes claros e leituras rápidas e de destino a partir de projeções materializadas. Isso aumenta a produtividade, simplifica a evolução e torna o sistema mais resistente às cargas de trabalho - se for disciplinado gerindo coerência, observabilidade e migração.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.