Eventual Consistency na prática
O Eventual consistency (EC) é um modelo em que cópias de dados podem variar temporariamente, mas com o passar do tempo, sem uma coordenação global. Esta é a chave para a alta disponibilidade (AP por CAP) e baixa latência (PACELC), se você definir corretamente invariantes, regras de merja e garantias de clientes.
1) Quando escolher EC (e quando não)
Adequado:- Fidas, perfis, likes/contadores, diretórios/busca, visualizações em dinheiro.
- Sistemas globais com registros locais e invariantes suaves.
- Projeções (CQRS) onde a origem da verdade é um núcleo rigoroso e a leitura é asincrona.
- Invariantes duros, dinheiro, único, limites, inventário «não sair de menos». Lá está o SR/mais forte EC, saga/TSS.
2) Design de dados sob EC: conflitos e sua resolução
Princípio: Cada gravação possui metadados de versão e função de fusão definida.
Marcas de tempo/versionização: «versão», «ts», «ator».
Relógios vetoriais: detectam a causalidade, permitem perceber «paralelos conflitantes».
- LWW (Last-Write-Wins): Simples e rápido, mas pode perder o sentido.
- CRDT: estruturas comutativas/idumpotentes, garantem a fusão.
- Merge de domínio: função de negócio (por exemplo, combinar listas sem duplicação, somar contadores, «email mais novo + formatação de marcas de formatação»).
- Contadores → G-Counter/PN-Counter.
- Várias → OR-Set (remover sem «colar»).
- Registros → LWW-Register (cuidado com «perdas»).
- Mapas/documentos → Map of CRDTs.
- Edição compartilhada → CRDT/OT de texto.
3) Replicação e anti-entropia
Gossip/anti-entropy: troca periódica de estados/haches entre nós.
Hinted handoff: «depósito» temporário da gravação para um nó inacessível.
Read repair: durante a leitura, descobriram a concordância e puxaram versões recentes.
Pacotes de alterações (deltas): correndo delta em vez de fotos completas.
Quorum R/W: Ajustamos 'R', 'W', 'N' sob comprometimento de velocidade e frescura (por exemplo, 'R + W> N' mais próximo do strong no «último registro»).
4) Garantias de cliente acima de EC
Read-Your-Writes (RYW): o autor vê-a após a sua gravação (sticky-sessions/rotulagem de versão).
Monotonic Reads: não «retrocedemos» o cliente para um valor mais antigo (armazenando watermark última versão).
Causal Consistency: mantenha a causalidade dentro da sessão/fluxo de ação (marcas vetoriais em cabeçalhos/tokens).
Bounded Staleness: Garantia de «no máximo, nas versões n' N» para ecrãs críticas UX.
5) Pattern UX para EC
Updates otimistas refletindo instantaneamente a ação marcando «sincronização».
Sinalização de frescura: sinalização atualizada X segundos para trás, botão Atualizar.
Conflito-UI: Para raros conflitos - «mostrar as duas versões e escolher/combinar».
Skeleton/placeholder + soft refresh: não bloquear UI com a expectativa de quórum global.
6) Modelos arquitetônicos
6. 1 CQRS + projeções
Núcleo Write (COP): invariantes rigorosos.
Plano read (EC): projeções asinhrônicas, índices, cachês; A liga é supostamente.
6. 2 Região Multi AP
Gravações localmente rápido, replicação asincrona.
Geo-partitioning: os dados «vivem» mais perto do usuário; A Região Cruzada é uma unidade.
Funções CRDT/merge removem a dor dos conflitos.
6. 3 Quórum Configuração
yaml consistency:
replicas: 3 # N write_quorum: 2 # W read_quorum: 2 # R => R + W> N, closer to freshness on "last record"
read_repair: true hinted_handoff: true
7) Políticas de versionagem e merge (exemplo)
yaml entity: "profile"
versioning:
clock: "vector" # или "hybrid_time"
fields:
name: { merge: "lww" }
emails: { merge: "set_union" } # OR-Set tags: { merge: "or_set" }
likes: { merge: "pn_counter" }
conflict_ui:
enabled: true show_diff_for: ["name"]
auto_merge_for: ["emails","tags","likes"]
8) Observabilidade EC: o que medir
Staleness Age (p50/p95/p99): 'now - data _ versão _ ts' ou 'número de versões atrasadas'.
Reprodução Lag: atraso na entrega entre regiões/nós.
Confidt Rate: proporção de updates paralelos, distribuição por tipo.
Read-Repair Rate/Latency: Com que frequência e rapidez «tratamos» na leitura.
Convertence Time: Tempo anterior à eclosão após a eclosão ou falha do nó.
SLO semântico: «95% dos perfis não têm mais de 2s», «99% do fido é compatível <10s».
9) Runbook 'e incidentes
Cenários:1. Crescimento de lag inter-regional: reduzir 'write fan-out', incluir um read-repair agressivo, trotar escritores pesados.
2. Aumento de conflitos: incluir temporariamente uma regra mais «rigorosa» (por exemplo, causal/RYW) e limitar os updates competitivos em chaves quentes.
3. Projeções atrasadas - Priorizar filas de replicação, reduzir temporariamente a frequência de updates não críticos.
4. Os dados foram «afundados» em uma parte dos nós: força-anti-entropia, rebalance das partições, auditoria hinted handoff.
5. Análise manual: descarga de chaves de conflito, ferramenta «merge-preview», fixe de bateria.
10) Testes EC
Jepsen-testes semelhantes, separação de rede, clock-skew, reescrição.
Property-based: invariantes de função merge (comutação, idempotidade, associatividade).
Conflitos Fuzz: updates paralelos por chave com ordem de entrega variável.
«Serras» de carga: Alternando bursts/bloqueios para avaliar conversence time.
Simulações UX: visibilidade RYW/monotonic em cenários típicos.
11) Multi-tenente e planos
Tags 'tenant _ id/place/region' em eventos/registros.
Fairness: limites de replicação/repair per tenant para que o cliente «barulhento» não aumente a estaleness geral.
Residency: dados e suas réplicas dentro da jurisdição; As representações regionais cruzadas são apenas as unidades.
12) Erros típicos
LWW para tudo. Perde as alterações paralelas significativas; use o CRDT/domínio merge.
Não há garantia de clientes. O usuário não vê sua própria gravação → perda de credibilidade.
Falta de observabilidade da obsolescência. Não há métricas estaleness/lag «degradação oculta».
Dual-write em sistemas diferentes sem merge. Fantasmas e divergências são infinitas.
Ordem global a qualquer custo. Os quóruns extras matam p95 e os negócios têm ordem local suficiente.
13) Receitas rápidas
Fid/fita: EC + causal/RYW para o autor, CRDT para reações, staleness p95 ≤ 2-5s.
Perfis/configurações: bounded staleness (≤1 -2s), RYW, domínio merge (união de multiplicidade).
Catálogo global: geo-partition, replicação asíncrona, read-repair sob demanda, conflitos via OR-Set.
Métricas/contadores: PN-Counter, consolidação no fundo; exibe valores «aproximados» marcados.
14) Mini referência (padrão verbal)
Write-edge: gravação local com versão ('vector/hybrid'), registro de eventos.
Replication: очереди + gossip/anti-entropy, hinted handoff.
Armazenamento: particionamento por chave, funções CRDT/merj em nível de gravação.
Read-plane: cachês com read-repair, RYW/monotonic tokens, bounded staleness para telas críticas.
Observabilidade: laje/obsolescência/conflitos, alertas para excesso de stylness SLO.
15) Folha de cheque antes de vender
- Invariantes são claramente descritos e onde o EC é permitido.
- A versionagem (vector/hybrid) e as funções determinadas de merge/CRDT foram selecionadas.
- Garantia cliente (RYW/monotonic/causal) implementada para UX crítico.
- Replicação configurada, read-repair, hinted handoff; quórum R/W está documentado.
- Métricas estaleness/lag/convergence e alertas nas liminares p95/p99.
- Runbook 'e para o crescimento dos conflitos/lajes; ferramentas de merge manual seguras.
- Testes de separação de rede, updates paralelos e propriedade de convergência.
- Os limites multi-tenentes e as políticas residency são considerados.
- Indicadores UX de frescura e comportamento fallback estão alinhados com o produto.
Conclusão
Eventual consistency não é um «compromisso de compromisso», mas uma ferramenta de escalabilidade e acessibilidade. Se você formalizar invariantes, escolher funções de merge corretas (preferencialmente CRDT onde for apropriado), fornecer garantias ao cliente e medir o tempo de estelionato e tempo de duração, o sistema será rápido, sustentável e honesto - tanto para os usuários como para os negócios.