8 min

SQL distribuído: quando usar Spanner, CockroachDB e YugabyteDB

Veja quando o SQL distribuído justifica seu custo, como Spanner, CockroachDB e YugabyteDB se comparam e como planejar cargas multirregionais com segurança.

SQL distribuído: quando usar Spanner, CockroachDB e YugabyteDB

O que significa SQL distribuído

SQL distribuído é uma arquitetura de banco de dados relacional que distribui dados e processamento de transações entre várias máquinas, mas apresenta às aplicações um único banco de dados SQL lógico. Ele mantém tabelas, joins, índices, restrições e transações ACID, e acrescenta particionamento automático, replicação e recuperação de falhas.

Em geral, um sistema entra nessa categoria quando combina estas características:

  • Um esquema relacional e uma interface de consultas SQL
  • Escalabilidade horizontal entre nós do banco de dados
  • Consistência transacional entre partições
  • Replicação e failover automáticos
  • Operação coordenada como um único banco de dados lógico

A definição importa porque um banco de dados não vira SQL distribuído apenas por adicionar réplicas de leitura ao PostgreSQL ou MySQL. Um primário com réplicas ainda envia as gravações por um servidor principal. O sharding gerenciado pela aplicação distribui gravações, mas obriga a aplicação a decidir onde cada registro fica e como operações entre shards se comportam. O SQL distribuído transfere grande parte dessa responsabilidade para o banco de dados.

A posição entre um RDBMS convencional e NoSQL

SQL distribuído combina o modelo de programação relacional de um RDBMS convencional com o desenho escalável associado a armazenamentos de dados distribuídos. Implantações tradicionais de PostgreSQL e MySQL funcionam bem quando uma instância primária consegue lidar com a carga de gravação e uma falha regional não exige gravações contínuas em outro local. Réplicas de leitura, cache, pool de conexões e índices melhores podem ampliar esse modelo por anos.

Muitos bancos NoSQL facilitaram a distribuição limitando joins, transações ou garantias de consistência. Essas escolhas continuam fazendo sentido para cargas como grandes fluxos de eventos, caches descartáveis e registros que raramente participam de transações com várias linhas. Um cluster relacional assume mais coordenação porque as aplicações esperam que restrições e transações continuem válidas depois que os dados são divididos entre nós.

A diferença prática está em quem assume a complexidade. Com sharding manual, as equipes de aplicação implementam roteamento, reequilibram dados, coordenam alterações de esquema e lidam com operações que tocam vários shards. Com SQL distribuído, o banco fornece esses mecanismos, embora os engenheiros ainda precisem projetar esquemas e consultas para um sistema em rede.

Os problemas que ele foi projetado para resolver

SQL distribuído foi projetado para aplicações cuja disponibilidade, distribuição geográfica ou crescimento de gravações ultrapassou uma arquitetura com primário único. Exemplos comuns incluem um serviço SaaS global, um sistema de reservas que não pode vender além da capacidade e um livro-razão financeiro cujas regras precisam sobreviver a falhas de nós.

Ele pode eliminar a necessidade de sharding no nível da aplicação e reduzir a dependência de um único local de gravação. Também pode manter dados perto dos usuários ou dentro de jurisdições aprovadas. Esses benefícios têm um preço: mais réplicas, mais tráfego de rede, mais coordenação e modos de falha que não existem em um único servidor.

Um banco de dados relacional gerenciado e convencional continua sendo a melhor opção inicial quando a carga cabe confortavelmente em uma região. O SQL distribuído justifica seu custo quando sharding personalizado, failover regional ou controles geográficos de dados se transformariam em um grande sistema de engenharia por conta própria.

Como o SQL distribuído funciona internamente

SQL distribuído funciona ao dividir dados em partições replicadas e coordenar alterações por consenso e protocolos de transações distribuídas. O banco esconde boa parte dessa mecânica atrás do SQL, mas seu comportamento ainda molda latência, capacidade, desenho do esquema e resposta a incidentes.

As partições determinam onde os registros ficam

Um cluster divide suas tabelas lógicas em unidades menores que podem se mover de forma independente entre nós. O Spanner normalmente chama essas unidades de splits, o CockroachDB usa ranges e o YugabyteDB usa tablets. Cada unidade cobre parte do espaço de chaves de uma tabela ou índice.

Os limites das partições podem seguir intervalos, hashes ou regras geográficas explícitas. Um intervalo ordenado pelo identificador do cliente torna simples examinar registros relacionados, mas um identificador que cresce continuamente pode direcionar novas gravações para uma só partição. A distribuição por hash espalha melhor as gravações, mas pode dificultar varreduras ordenadas ou o posicionamento por locatário. Muitos esquemas de produção combinam um identificador de locatário com outro valor para manter os dados relacionados acessíveis sem concentrar todas as gravações em um lugar.

Índices secundários precisam de seu próprio armazenamento distribuído. Por isso, uma gravação em uma linha pode atualizar a tabela base e várias entradas de índice em partições diferentes. Um índice barato em um único servidor pode gerar trabalho extra de consenso e tráfego de rede em um cluster.

Replicação e consenso protegem cada partição

Cada partição normalmente tem várias réplicas, e um grupo de consenso decide a sequência aceita de alterações. CockroachDB e YugabyteDB usam replicação baseada em Raft. O Spanner usa replicação baseada em Paxos junto com sua infraestrutura de tempo.

Um líder ou leaseholder coordena as gravações de um grupo de réplicas. O sistema registra uma alteração em réplicas suficientes para formar quórum antes de tratá-la como confirmada. Se um nó desaparece, os membros restantes podem eleger ou designar outro coordenador, desde que o quórum continue disponível.

Quórum é uma exigência matemática, não uma promessa de que toda falha será inofensiva. Um grupo com três réplicas geralmente tolera uma réplica indisponível. Ao perder dois membros, a cópia restante não pode aceitar gravações com segurança, pois não consegue provar que outra maioria não avançou em outro lugar. A distribuição entre domínios de falha importa tanto quanto a quantidade de réplicas.

Transações distribuídas coordenam várias partições

Uma transação que toca uma partição muitas vezes termina com pouca coordenação. Uma transação que envolve várias partições precisa de uma decisão de commit comum, para que todos os participantes apliquem suas gravações ou as interrompam.

O protocolo exato varia conforme o produto, mas o trabalho costuma incluir ler ou bloquear versões relevantes, validar alterações concorrentes, replicar intenções ou registros provisórios e finalizar o commit. Transações longas aumentam a janela de conflitos. Lotes grandes podem envolver muitos grupos de consenso e causar picos de latência, mesmo quando cada instrução isolada parece simples.

Por isso, projetar transações com consciência da rede importa. Agrupe linhas relacionadas sob prefixos de partição compatíveis quando o banco permitir essa estratégia. Mantenha transações curtas, evite esperar serviços externos enquanto uma transação está aberta e não carregue milhares de registros sem relação em uma única unidade atômica sem medir o efeito.

Tempo e ordenação exigem mecanismos explícitos

Nós distribuídos não compartilham um relógio perfeitamente sincronizado, então cada produto precisa de uma forma de ordenar transações. O Spanner usa limites de incerteza do TrueTime e espera de commit para oferecer consistência externa. Outros sistemas podem combinar relógios físicos com componentes lógicos, rastreamento de dependências e protocolos de transação.

A coordenação de relógios afeta operações como execução serializável, leituras de seguidores e snapshots. As aplicações devem usar timestamps de transação do banco em vez de presumir que timestamps gerados por servidores de aplicação separados estabelecem uma ordem global confiável.

A localidade controla o caminho pela rede

A configuração de localidade define onde as réplicas ficam e qual região coordena as gravações de um registro. As leituras podem ser rápidas quando há uma réplica adequada perto de quem chama. Uma gravação fortemente ordenada ainda precisa alcançar as réplicas necessárias para o quórum, portanto sua latência reflete a topologia escolhida.

Um bom posicionamento segue a carga de trabalho, não um diagrama da empresa. Se a maioria das gravações de um locatário da UE se origina na Europa, coordená-las lá evita uma viagem intercontinental no início de cada transação. Um registro compartilhado globalmente, como um contador atualizado por todas as regiões, não pode ficar perto de todos os gravadores e pode se tornar um ponto de contenção.

Quando SQL distribuído é a escolha certa

SQL distribuído é a escolha certa quando resiliência geográfica, capacidade horizontal de gravação ou correção entre partições importam o suficiente para justificar custos contínuos de coordenação. Uma empresa grande não precisa dele automaticamente, e um produto pequeno pode precisar se sua promessa de negócio inclui disponibilidade regional rigorosa.

Condições que justificam uma avaliação

Uma avaliação séria é adequada quando várias destas condições se aplicam:

  • O serviço precisa continuar funcionando durante uma falha de zona ou região
  • A demanda de gravações está perto do limite prático de um banco primário
  • O sharding manual consumiria muito tempo de engenharia da aplicação
  • Transações precisam continuar corretas entre nós ou locais
  • Registros exigem posicionamento geográfico que possa ser aplicado de fato

Essas condições devem ser sustentadas por números. Defina o objetivo de tempo de recuperação, o objetivo de ponto de recuperação, a latência das transações, a taxa máxima de gravações e os domínios de falha. Um pedido vago de escala global não basta para escolher uma arquitetura.

Ter usuários em diferentes regiões, por si só, não é motivo decisivo. Uma aplicação rica em conteúdo pode manter servidores web e caches perto dos usuários e ainda reter uma região de banco de dados. Réplicas de leitura podem atender a navegação regional se resultados um pouco antigos forem aceitáveis. O caso se fortalece quando usuários de vários locais precisam fazer gravações de baixa latência em dados relacionados.

Condições que favorecem um banco mais simples

Um serviço relacional convencional costuma ser preferível quando o tráfego é moderado, as gravações vêm de uma região e a recuperação pode envolver uma promoção planejada do banco. Ele oferece ferramentas maduras, ampla compatibilidade com extensões, depuração conhecida e uma conta de infraestrutura menor.

Exigências rígidas de latência também podem favorecer um primário regional. Uma gravação local e durável pode terminar muito mais rápido do que uma gravação por quórum que atravessa regiões distantes. Sistemas voltados a análises devem separar transações operacionais de varreduras longas, em vez de esperar que o mesmo cluster seja excelente nas duas tarefas.

A capacidade da equipe importa. Serviços gerenciados reduzem o trabalho com hardware, atualizações e operação do plano de controle, mas não eliminam contenção no esquema, novas tentativas de transação, planejamento de consultas, gestão de capacidade ou tratamento de incidentes no lado da aplicação. Se a equipe não tem tempo para testar o comportamento em falhas, adotar um banco distribuído pode aumentar o risco.

Um limite de decisão baseado nas alternativas

A justificativa mais forte surge quando a alternativa já é complicada. Se os engenheiros estão prestes a criar roteamento de locatários, mapas de shards, regras de transação entre shards, procedimentos de promoção regional e ferramentas de migração separadas, um banco que fornece essas funções merece uma avaliação cuidadosa.

Se a alternativa é uma instância gerenciada de PostgreSQL com uma réplica de leitura e backups testados, a migração exige evidências claras. Primeiro, faça benchmark do sistema atual. A saturação de CPU pode ser uma consulta ineficiente, gestão ruim de conexões, excesso de índices ou falta de cache, e não uma necessidade de gravações horizontais.

Consistência, disponibilidade e latência

SQL distribuído geralmente preserva a consistência transacional durante falhas ao recusar operações que não conseguem alcançar o quórum necessário. Esse comportamento protege o estado confirmado, mas significa que algumas solicitações podem falhar ou esperar durante uma partição de rede.

CAP descreve o comportamento em falhas

O teorema CAP se aplica quando a comunicação entre partes do cluster é interrompida. Para os dados afetados, um sistema não consegue garantir ao mesmo tempo consistência linearizável e respostas bem-sucedidas de todos os lados isolados. Um banco orientado à consistência permite que o lado com quórum continue e rejeita gravações inseguras em outros lugares.

CAP não explica a latência na operação normal. Mesmo quando todos os links funcionam, as réplicas precisam se comunicar. A decisão de engenharia mais ampla inclui o que acontece durante uma partição e quanta coordenação a aplicação aceita enquanto tudo está saudável.

Uma aplicação precisa lidar explicitamente com resultados indisponíveis. Timeouts, erros de transação que permitem nova tentativa e perda temporária de uma região de gravação são possibilidades normais. Retornar sucesso de ambas as regiões isoladas seria pior para um saldo ou uma reserva, pois a reconciliação talvez não tivesse uma resposta automática válida.

Leituras fortes e leituras intencionalmente antigas são diferentes

Uma leitura forte observa um estado do banco coerente com a garantia de ordenação solicitada. Alguns produtos também oferecem leituras de seguidores ou leituras com atraso limitado, que trocam atualização imediata por menor latência e menos trabalho no coordenador de gravação.

Essa escolha deve seguir o campo lido. Uma descrição de produto costuma tolerar uma réplica levemente desatualizada. Uma senha recém-alterada, o saldo atual da conta ou o estoque restante devem usar um caminho forte ou consistente com a sessão. As aplicações não devem marcar toda leitura como antiga para ganhar velocidade e depois reconstruir a correção no código de serviço.

O comportamento de ler suas próprias gravações precisa ser testado com o driver e a camada de roteamento reais. Depois de uma atualização, a próxima solicitação pode chegar a outro servidor de aplicação ou endpoint do banco. Tokens de sessão, limites de transação ou uma configuração de leitura forte podem ser necessários para garantir que o usuário veja a alteração aceita.

O isolamento controla os resultados concorrentes

O isolamento de transação determina quais anomalias transações concorrentes podem produzir. O isolamento serializável busca fazer as transações concluídas parecerem executadas uma de cada vez, mesmo quando o banco as executa concorrentemente.

A execução serializável pode interromper um participante quando operações concorrentes não podem ser ordenadas com segurança. Essa interrupção protege contra um resultado incorreto, não indica corrupção do banco. As aplicações precisam de novas tentativas limitadas em torno de toda a transação, incluindo todas as leituras que influenciaram suas gravações.

As tentativas precisam ser idempotentes fora do banco. Se o código envia um e-mail ou chama um provedor de pagamentos antes de a transação ter sido confirmada com certeza, uma nova tentativa pode repetir o efeito colateral. Registre um evento de caixa de saída na transação do banco, confirme-a e deixe um worker separado entregar a ação externa.

A distância impõe um limite mínimo à latência de gravação

Uma transação entre regiões não pode terminar mais rápido que as mensagens exigidas por seu protocolo. Uma ida e volta de 80 milissegundos entre membros do quórum acrescenta tempo real antes de considerar execução de consultas, manutenção de índices, trabalho da aplicação e filas.

O padrão caro costuma ser várias transações sequenciais em uma única ação do usuário. Se o checkout faz uma inserção de pedido, uma reserva de estoque, uma atualização de status de pagamento e uma gravação de auditoria como quatro commits bloqueantes, o custo de rede se acumula. Combinar alterações de banco que compartilham um resultado atômico pode eliminar idas e voltas desnecessárias, enquanto chamadas externas de pagamento devem ficar fora de uma transação aberta.

Meça a latência por percentis, não por médias. Mudança de liderança, contenção, pausas de armazenamento e novas tentativas aparecem na cauda. Um desenho que atinge a meta da mediana, mas falha no percentil 99 durante reequilíbrio normal, ainda pode causar falhas visíveis aos usuários.

Spanner, CockroachDB e YugabyteDB comparados

Spanner, CockroachDB e YugabyteDB resolvem problemas parecidos de distribuição, mas diferem no modelo de implantação, compatibilidade, implementação de transações e premissas operacionais. Escolher entre eles exige testar o comportamento da aplicação, em vez de decidir pelo rótulo SQL em comum.

ÁreaGoogle SpannerCockroachDBYugabyteDB
Interface SQL principalGoogleSQL ou dialeto PostgreSQLSQL compatível com PostgreSQL pelo protocolo de conexão PostgreSQLYSQL para SQL compatível com PostgreSQL, além de YCQL para acesso no estilo Cassandra
Base de replicaçãoGrupos Paxos com ordenação baseada em TrueTimeReplicação Raft sobre rangesReplicação Raft sobre tablets
Forma típica de entregaBanco de dados gerenciado no Google CloudServiço em nuvem gerenciado ou implantação autogerenciadaServiço em nuvem gerenciado ou implantação autogerenciada
Questão de portabilidadeDialeto e comportamento específicos da plataformaLacunas em recursos, extensões e semântica do PostgreSQLDiferenças de versão e recursos entre YSQL e PostgreSQL
Caso natural de avaliaçãoSistemas no Google Cloud que precisam de posicionamento transacional globalEquipes que buscam desenvolvimento orientado a PostgreSQL com operação distribuídaEquipes que querem acesso orientado a PostgreSQL ou uma escolha entre APIs SQL e no estilo Cassandra

Spanner se encaixa em uma estratégia gerenciada no Google Cloud

O Spanner se encaixa em organizações dispostas a usar um banco gerenciado no Google Cloud e projetar em torno de seu dialeto, topologia e modelo operacional. O TrueTime sustenta transações externamente consistentes, o que significa que transações confirmadas respeitam a ordenação em tempo real dentro da semântica documentada.

Seu dialeto PostgreSQL pode reduzir diferenças de sintaxe SQL, mas um dialeto não equivale completamente ao PostgreSQL. Extensões, funções administrativas, catálogos do sistema, tipos de dados, drivers e premissas de ORM ainda exigem verificação. As equipes devem inventariar cada dependência de banco antes de considerar uma aplicação existente portável.

O Spanner merece atenção especial quando o sistema desejado já depende de identidade, rede, observabilidade e controles regionais do Google Cloud. O modelo gerenciado elimina a administração de nós de banco, embora desenho de esquema, ajuste de consultas, cotas, gestão de custos e recuperação da aplicação continuem sendo responsabilidades do cliente.

CockroachDB se encaixa em aplicações distribuídas orientadas a PostgreSQL

O CockroachDB se encaixa em equipes que querem acesso à aplicação no estilo PostgreSQL enquanto distribuem dados transacionais entre ranges. Ele usa isolamento serializável por padrão, então as aplicações precisam repetir corretamente transações rejeitadas por contenção ou conflitos de ordenação.

A compatibilidade deve ser testada nas camadas de migração, driver e ORM. Extensões do PostgreSQL e comportamentos especializados podem não existir ou ser diferentes. Consultas que dependem de planos de execução em um único nó também podem se comportar de forma diferente depois que tabelas e índices são divididos entre ranges.

O movimento de ranges e o reequilíbrio automático simplificam mudanças de capacidade, mas uma escolha ruim de chave primária ainda pode gerar ranges quentes. As abstrações multirregionais ajudam a expressar a localidade das tabelas, mas os desenvolvedores precisam decidir quais registros são regionais, quais são globais e onde as gravações devem ser coordenadas.

YugabyteDB se encaixa em requisitos de YSQL e APIs mistas

O YugabyteDB se encaixa em aplicações que valorizam uma interface relacional compatível com PostgreSQL e podem se beneficiar de sua API separada compatível com Cassandra. O YSQL fornece tabelas relacionais e transações distribuídas, enquanto o YCQL segue outro modelo de dados e não deve ser tratado como outro caminho para toda operação YSQL.

Sua camada de armazenamento distribui dados por tablets. O desenho da tabela, a divisão de tablets, o posicionamento de índices e o escopo da transação influenciam como o trabalho se espalha pelo cluster. Aplicações PostgreSQL ainda precisam de testes de compatibilidade para extensões, funções, ferramentas e comportamento do planejador.

A disponibilidade de abordagens diferentes de implantação pode atender políticas de infraestrutura que exigem controle sobre o posicionamento. Esse controle transfere a responsabilidade operacional ao cliente quando a operação é própria: atualizações, procedimentos de reparo, capacidade, observabilidade, certificados, backups e testes de falha precisam ter responsáveis.

Um teste útil de produto usa evidências da aplicação

Uma comparação útil executa a mesma carga representativa em cada produto viável. Teste criação de esquema, migrações, SQL gerado pelo ORM, novas tentativas de transação, restauração de backup, failover, eventos de escalonamento e as consultas de maior volume.

Não compare apenas o pico de transações por segundo. Registre latência p50, p95 e p99, taxas de conflito e nova tentativa, bytes transferidos entre regiões, amplificação de armazenamento, tempo de restauração e esforço do operador durante um incidente simulado. A melhor escolha é a que atende metas de correção e recuperação com custo e esforço operacional aceitáveis.

SaaS global com usuários regionais

Experimente sem receio
Experimente mudanças arriscadas no esquema com snapshots e volte atrás quando os testes falharem.

Uma aplicação SaaS global se beneficia de SQL distribuído quando os locatários precisam de posicionamento regional de dados e acesso transacional sem pilhas de banco separadas para cada geografia. O desenho funciona melhor quando a locação é explícita no esquema e a maioria das transações permanece dentro de um locatário.

A localidade do locatário deve seguir contratos e tráfego

Um identificador de locatário pode orientar o posicionamento, para que registros europeus permaneçam em locais europeus aprovados, enquanto os registros de outro cliente ficam no país ou região contratados. Isso mantém um esquema lógico único, permitindo políticas físicas diferentes.

As regras de posicionamento precisam cobrir mais do que a tabela base. Entradas de índice, fluxos de alteração, dados temporários, backups e registros exportados podem conter informações reguladas. Uma política que fixa linhas, mas envia um índice secundário global para outro lugar, pode violar o limite pretendido.

O isolamento de locatários também afeta o desempenho. Um locatário grande pode sobrecarregar uma partição compartilhada ou dominar um nó. Pode ser necessário usar hash ou subparticionamento dentro desse locatário, preservando o acesso eficiente a transações no escopo dele.

Leituras regionais exigem uma política explícita de atualização

Painéis com muitas leituras podem usar réplicas próximas quando dados levemente atrasados são aceitáveis. Alterações de conta, decisões de autorização e telas de confirmação após a transação exigem um comportamento mais forte. Classifique caminhos de consulta pelo requisito de atualização, em vez de adotar uma configuração global única.

O posicionamento das gravações deve seguir o gravador habitual de cada locatário. Se a equipe de um cliente trabalha principalmente em Singapura, coordenar suas gravações em outro continente cria latência evitável. Um procedimento de migração de locatário deve atualizar o posicionamento sem perder gravações, violar residência de dados ou deixar caches da aplicação apontando para locais antigos.

O código de uma aplicação global precisa tolerar movimentação

Líderes mudam, nós reiniciam e o roteamento muda durante a manutenção. Drivers precisam de timeouts sensatos, políticas de nova tentativa, renovação de conexão e lógica de reinício de transação. As tentativas devem usar jitter e limite para que um cluster sobrecarregado não receba uma onda sincronizada e imediata de solicitações repetidas.

O monitoramento deve separar a latência do usuário por região e classe de locatário. Uma média global pode esconder um grupo distante de clientes pagando várias viagens extras pela rede. Identificadores de rastreamento que conectam spans de API a instruções de banco facilitam encontrar erros de localidade.

Fluxos financeiros e livros-razão

Fluxos financeiros se beneficiam quando restrições e transações do banco aplicam as regras do livro-razão diante de falhas e solicitações concorrentes. A distribuição não cria contabilidade correta por si só, então o esquema precisa codificar as regras que não podem ser violadas.

Um livro-razão deve preservar uma sequência auditável de lançamentos

Um livro-razão orientado a anexação registra cada movimentação como lançamentos, em vez de substituir repetidamente um único valor de saldo sem histórico. Cada lançamento deve ter um identificador estável de transação, contas, valores, moeda, timestamp de negócio e metadados de criação. As regras de partida dobrada devem ser verificadas antes do commit, para que débitos e créditos se equilibrem na unidade de lançamento.

Um saldo em cache pode acelerar leituras, mas precisa mudar na mesma transação que os lançamentos ou ser claramente tratado como dado derivado. Trabalhos de reconciliação devem comparar totais derivados com lançamentos de origem e informar diferenças sem reescrever silenciosamente o histórico.

Raramente é necessária ordenação global para todas as contas. Transações que afetam uma conta ou um par de transferência precisam de ordem consistente, enquanto contas sem relação podem prosseguir em paralelo. Projetar em torno desse limite reduz a contenção em comparação com uma única sequência global ou linha de liquidação.

A idempotência torna as novas tentativas seguras

APIs de pagamento, filas e webhooks repetem tentativas depois de timeouts, portanto cada operação de negócio precisa de uma chave de idempotência estável. Aplique unicidade no escopo correto, como um comerciante ou conta, e crie o registro de pagamento e os lançamentos do livro-razão em uma transação do banco.

CREATE TABLE payment_attempts (
    account_id UUID NOT NULL,
    idempotency_key TEXT NOT NULL,
    provider_reference TEXT,
    status TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    PRIMARY KEY (account_id, idempotency_key)
);

Se dois workers enviarem a mesma operação, a restrição de unicidade decide qual inserção terá sucesso. O worker que perder deve ler o registro existente e retornar seu resultado já definido. Ele não deve criar uma segunda cobrança do provedor apenas porque uma transação do banco foi repetida.

Chamadas externas exigem um limite de transação

Um banco de dados não consegue confirmar uma transação de forma atômica com um provedor de pagamentos sem relação, a menos que ambos participem de um protocolo especializado de coordenação, o que a maioria das APIs públicas não faz. Mantenha a chamada de rede fora da transação do banco e modele o fluxo como estados explícitos, como pendente, autorizado, capturado, falhou e revertido.

Uma caixa de saída transacional pode publicar alterações confirmadas para workers posteriores. Os consumidores devem eliminar duplicatas pelo identificador do evento, pois a entrega de mensagens pode ocorrer mais de uma vez. Isso oferece processamento recuperável sem alegar uma única transação impossível entre todos os serviços.

Contas muito acessadas exigem um desenho específico da carga

Processamentos de folha de pagamento, liquidações de marketplace e grandes comerciantes podem concentrar gravações em uma conta. Adicionar nós ao banco não divide uma única linha conflitante entre eles. As opções incluem partições de lançamentos imutáveis, acumuladores por período, lançamento em fila para uma conta ou uma hierarquia cuidadosamente definida de subcontas.

Teste a distribuição real de concentração. Tráfego sintético uniforme pode fazer o cluster parecer pronto, enquanto um comerciante de produção gera conflitos serializáveis repetidos. A correção vem primeiro, mas o modelo de dados deve expor concorrência segura onde as regras contábeis permitirem.

Estoque, reservas e agendamentos

Sistemas de estoque e reservas precisam de uma transação autoritativa de alocação quando vários usuários podem disputar o mesmo item escasso. Leituras rápidas de disponibilidade melhoram a navegação, mas apenas o caminho de commit pode decidir quem recebe a unidade final.

Gravações condicionais evitam vendas acima do estoque

Uma atualização condicional pode reservar estoque somente quando ainda há quantidade suficiente. A quantidade de linhas afetadas informa à aplicação se a alocação teve sucesso.

UPDATE inventory
SET available = available - 1
WHERE sku = $1
  AND available > 0;

Essa instrução deve compartilhar uma transação com o registro de reserva. Ler a disponibilidade primeiro e decrementar depois cria uma condição de corrida, a menos que o nível de isolamento e o tratamento do predicado protejam a decisão. Restrições do banco devem rejeitar quantidades negativas como outra camada de segurança.

Para assentos marcados, uma restrição de unicidade sobre o identificador da apresentação e do assento dá uma reserva vencedora. O estoque de hotel costuma ser modelado por quarto-noite ou data do pool de inventário, para que estadias sobrepostas não possam reivindicar a mesma capacidade. A unidade correta de contenção vem da regra de negócio.

Reservas temporárias separam alocação de pagamento

Uma reserva temporária separa estoque enquanto o pagamento ou a confirmação do usuário avança. Armazene seu prazo de expiração e status, depois converta-a em reserva confirmada por uma transação condicional. Um worker de expiração deve liberar apenas reservas que ainda estão ativas, pois confirmação e expiração podem competir.

O atraso do relógio de parede não basta para garantir a liberação. Workers podem parar, filas podem atrasar e regiões podem falhar. Consultas que calculam o estoque vendável devem considerar de forma consistente o status expirado, enquanto tarefas de reparo recuperam reservas perdidas.

A duração da reserva é uma decisão de produto e capacidade. Uma reserva de dez minutos pode ser razoável para o checkout, mas pode bloquear uma parte relevante de um estoque escasso durante um pico. Meça abandono e tempo de conclusão do pagamento antes de defini-la.

Contenção extrema não escala de forma linear

Milhares de compradores disputando uma linha não podem ser paralelizados com a adição de réplicas. Todo decréscimo bem-sucedido precisa ser ordenado em relação aos demais. Controles de admissão, uma fila, baldes de estoque ou cotas regionais pré-alocadas podem proteger o banco durante um lançamento.

Cotas regionais reduzem a coordenação, mas mudam a semântica. Se a Europa tem unidades não usadas enquanto outra região esgota, o sistema precisa de uma forma segura de transferir cota ou aceitar desequilíbrio temporário. Use esse padrão apenas quando o negócio puder definir como reconciliar a capacidade regional.

Alta disponibilidade e recuperação de desastres

Teste cargas reais
Prototipe fluxos de checkout, reservas ou razão contábil e teste seus padrões de transação de ponta a ponta.

SQL distribuído pode manter o serviço durante falhas de infraestrutura selecionadas quando o posicionamento de réplicas, a capacidade de reserva e o comportamento da aplicação correspondem a um objetivo de serviço definido. Só a replicação não estabelece esse resultado.

SLOs devem especificar domínios de falha

Uma meta de disponibilidade precisa de uma carga e um cenário de falha. Defina se o serviço deve sobreviver à perda de um nó, de uma zona de disponibilidade ou de uma região inteira. Declare a taxa de erro e a latência aceitáveis durante o evento, não apenas depois da recuperação.

Um cluster de três réplicas em um único prédio tem um perfil de risco diferente de três réplicas em zonas independentes. Uma topologia multirregional protege contra um evento maior, mas introduz caminhos de quórum mais longos e exige capacidade restante suficiente para absorver o tráfego depois que um local desaparece.

O objetivo de tempo de recuperação define com que rapidez o serviço deve retornar. O objetivo de ponto de recuperação define quanto dado confirmado pode ser perdido. A replicação síncrona por quórum pode apoiar a meta de nenhuma perda de dados confirmados em falhas cobertas, mas apenas enquanto as réplicas exigidas e o caminho da aplicação se comportarem como planejado.

O failover cria eventos visíveis para a aplicação

Mudanças de liderança podem interromper transações em andamento, fechar conexões e aumentar a latência. As aplicações devem distinguir resultados de banco que permitem nova tentativa de erros permanentes de negócio. Uma transação que falha deve reiniciar por inteiro, em vez de repetir apenas sua instrução final.

Pools de conexão podem reter endpoints inativos após uma falha. Verificações de saúde, comportamento de DNS, balanceadores de carga, validação de certificados e descoberta de topologia pelo driver pertencem ao plano de teste. O banco pode estar saudável enquanto a aplicação ainda não consegue encontrá-lo.

A capacidade depois de uma falha merece cálculo explícito. Se três regiões normalmente operam perto de 70% de utilização, perder uma delas não deixa espaço suficiente para sua parcela de trabalho. Reservar margem custa dinheiro, mas uma topologia sem capacidade de failover não atende à meta declarada.

Simulações de falha validam o desenho

Exercícios de falha devem desativar um nó, isolar uma zona, interromper a conectividade regional e remover um endpoint da aplicação. Meça duração dos erros, taxa de novas tentativas de transação, percentis de latência, crescimento de filas e resposta dos operadores.

Execute esses exercícios após mudanças relevantes de topologia, driver ou esquema. Um procedimento comprovado com o tráfego do ano passado pode falhar depois que o volume de dados dobra ou um locatário se torna dominante. Automatize partes seguras do exercício para que as evidências não dependam de um evento manual anual.

Replicação não é backup

Réplicas copiam fielmente exclusões acidentais, migrações defeituosas e gravações nocivas da aplicação. Backups e recuperação para um ponto no tempo protegem contra dano lógico que a replicação não consegue detectar.

Testes de restauração devem criar um ambiente limpo e separado, verificar checksums ou regras da aplicação e medir o tempo total de recuperação. Inclua chaves de criptografia, políticas de acesso, versões de esquema e configurações dependentes. Um backup que existe, mas não pode ser restaurado dentro do objetivo, não é um sistema de recuperação adequado.

Residência de dados e arquitetura guiada por conformidade

SQL distribuído pode posicionar locatários ou grupos de registros em regiões aprovadas, mas a conformidade depende de cada cópia, caminho de acesso e processo operacional. A localidade do banco é um controle dentro de um programa mais amplo.

Regras de residência precisam de definições precisas

Uma exigência de que os dados permaneçam em um país pode se referir a armazenamento, processamento, acesso de suporte, backups, chaves de criptografia ou a todos eles. Essas interpretações produzem topologias diferentes. Assessoria jurídica e auditores devem traduzir regulamentações e contratos em controles técnicos testáveis.

As equipes precisam de um inventário de campos regulados e dados derivados. Logs, rastreamentos, índices de busca, exportações analíticas, anexos de suporte e filas de mensagens podem conter as mesmas informações pessoais da tabela principal. Restringir o banco enquanto exporta cargas brutas globalmente não atende à política pretendida.

A minimização de dados pode simplificar o desenho. Se um serviço global precisa apenas de um identificador de conta e um status agregado, mantenha detalhes sensíveis na região aprovada e exponha em outros lugares a menor representação permitida.

Políticas de posicionamento devem incluir operações de ciclo de vida

As políticas devem informar onde réplicas ativas, réplicas temporárias, backups, snapshots, registros de alteração e ambientes de restauração podem existir. Reequilíbrio e manutenção devem obedecer ao mesmo limite. Um procedimento de emergência não deve copiar dados regulados para uma região não aprovada apenas por conveniência.

O controle de acesso precisa de limites geográficos e organizacionais. Identidades de serviço devem receber apenas as tabelas e operações de que precisam. O acesso humano à produção deve ser registrado, limitado no tempo quando viável e revisado. Chaves de criptografia vinculadas à região podem acrescentar controle, embora a disponibilidade das chaves e a recuperação de desastres precisem então de seu próprio desenho.

A realocação de locatários merece um fluxo documentado. Mudanças contratuais, migração de clientes ou reestruturação corporativa podem exigir mover registros entre jurisdições. O processo deve identificar quando as cópias antigas desaparecem, como os backups expiram e quais evidências comprovam a conclusão.

Relatórios globais podem exigir conjuntos de dados derivados

Um painel global pode entrar em conflito com posicionamento rigoroso se examina dados brutos de clientes entre regiões. O processamento regional pode calcular agregados aprovados localmente e publicar resultados não sensíveis em um armazenamento central de relatórios.

As regras de agregação devem impedir a reconstrução de registros restritos. Grupos pequenos, campos de texto livre e dimensões detalhadas podem expor informações pessoais mesmo quando identificadores diretos são removidos. Por isso, a governança de análises pertence à revisão de arquitetura, e não a um projeto de relatórios posterior.

Cargas operacionais e analíticas muitas vezes merecem sistemas separados. O banco transacional protege o estado atual do produto, enquanto pipelines com escopo regional produzem conjuntos de dados governados para relatórios. Essa separação mantém varreduras analíticas longas longe de transações sensíveis à latência.

Planejamento de custo e desempenho

Prototipe um SaaS global
Crie a estrutura de um SaaS multilocatário e valide cedo as premissas de posicionamento por locatário.

SQL distribuído custa mais que um banco básico em uma única região porque mantém capacidade redundante e coordena trabalho pela rede. O investimento ainda pode se justificar quando substitui trabalho caro de sharding ou evita perdas que superam o custo operacional adicional.

Computação e armazenamento incluem o custo da replicação

Um conjunto de dados lógico de 2 TB com três réplicas completas começa perto de 6 TB de dados replicados, antes de índices secundários, espaço temporário de compactação, backups e metadados. A cobrança e a compressão reais variam por produto, então estimativas devem usar armazenamento físico medido, e não apenas o tamanho lógico das tabelas.

A computação deve cobrir trabalho normal, processamento de consenso, reequilíbrio, atividade de backup e margem para falhas. Nós não são unidades intercambiáveis de capacidade quando uma partição está quente. Adicionar capacidade ajuda apenas se a carga puder se espalhar por ela.

Índices multiplicam o trabalho de gravação e o armazenamento. Revise cada índice secundário pelo valor para consultas, frequência de atualização e posicionamento geográfico. Um índice sem uso em um cluster distribuído desperdiça disco e torna cada gravação afetada mais cara.

Custos de rede podem se tornar relevantes

A replicação envia gravações entre locais de réplicas. Consultas entre regiões, feeds de alteração, backups e tráfego da aplicação acrescentam mais transferência. Tráfego ativo em várias regiões pode gerar uma conta que um benchmark em uma só região nunca revelaria.

Estime bytes por transação, fator de replicação, taxa de gravação, amplificação por índices e direção das transferências. Depois, teste com dados de cobrança do provedor durante uma execução de carga representativa. Só a contagem de solicitações deixa de fora cargas grandes e movimentação em segundo plano.

Erros de localidade aumentam custo e latência. Um serviço implantado em uma região pode consultar repetidamente um coordenador em outra por causa da seleção de endpoint ou do posicionamento do locatário. Rastreamento distribuído e detalhamento regional de custos podem expor esse padrão.

Jornadas do usuário revelam a latência acumulada

Modele ações completas do usuário, não instruções isoladas. Para checkout, conte cada commit sequencial de banco, leitura forte, chamada a API externa e entrega para fila. Aplique tempos de ida e volta regionais medidos e percentis de execução de consulta ao caminho crítico.

Suponha que uma jornada tenha duas gravações sequenciais por quórum, cada uma acrescentando 90 milissegundos de coordenação de rede. Isso adiciona cerca de 180 milissegundos antes do processamento da aplicação. Combinar mudanças que compartilham uma decisão atômica pode eliminar um commit, enquanto executar leituras independentes em paralelo pode encurtar o caminho.

Testes de carga devem incluir contenção e tamanhos de carga reais. Um benchmark com identificadores aleatórios pode se distribuir perfeitamente, embora as gravações de produção atinjam alguns poucos locatários populares. Inclua mudanças de líder e reequilíbrio para que a latência de cauda reflita a operação normal do cluster.

Compare a propriedade total com alternativas realistas

A comparação relevante não é SQL distribuído contra um banco imaginário sem custo operacional. Compare-o com uma alternativa específica: PostgreSQL gerenciado, réplicas, serviços de sharding, recuperação regional, roteamento da aplicação e os engenheiros necessários para mantê-los.

Inclua trabalho de migração, treinamento, observabilidade, resposta a incidentes, planos de suporte e custos de saída. A operação gerenciada pode reduzir trabalho de infraestrutura, enquanto a autogestão pode atender exigências de controle ao custo de uma equipe mais especializada.

Um modelo financeiro simples pode comparar o custo adicional anual da plataforma com perda esperada por indisponibilidade, trabalho de engenharia adiado, exposição de conformidade e receita afetada pela latência regional. Use intervalos para entradas incertas e identifique qual premissa muda a decisão. Se o resultado depende de uma estimativa de indisponibilidade implausivelmente alta, o sistema mais simples provavelmente continua apropriado.

Padrões de desenho do esquema e da aplicação

Um esquema de SQL distribuído tem bom desempenho quando seus caminhos de acesso distribuem trabalho independente e mantêm transações relacionadas próximas. Portar sem alterações um esquema de nó único pode preservar a correção, mas gerar latência ruim ou contenção severa.

Chaves primárias influenciam a distribuição

Uma chave primária que aumenta continuamente pode direcionar novas linhas para o fim de um range. Identificadores aleatórios espalham inserções, mas uma distribuição totalmente aleatória pode tornar caras as varreduras por locatário ou o posicionamento regional. Chaves compostas muitas vezes equilibram esses objetivos ao começar com um identificador de locatário ou balde e manter um valor ordenável dentro do grupo.

Escolha o prefixo de acordo com os limites de transação. Se quase toda operação está no escopo do locatário, agrupá-la pelo locatário pode reduzir trabalho distribuído. Um locatário muito grande pode precisar de baldes dentro de seu namespace para que várias partições aceitem gravações simultaneamente.

Mudar uma chave primária depois que uma tabela cresce pode exigir uma grande regravação dos dados. Teste layouts candidatos com concentração realista antes da migração. Examine atividade das partições, expansão das transações, localidade de índices e comportamento de varredura, em vez de julgar apenas a capacidade total.

A contenção exige redesenho antes de capacidade

Um contador global, uma linha única de configuração ou o saldo de um comerciante podem serializar solicitações que de outra forma seriam independentes. Mais nós não removem a exigência lógica de que toda transação atualize o mesmo valor.

Substitua contadores globais exatos por contadores particionados quando uma agregação temporária for aceitável. Versione a configuração em vez de atualizar uma linha em alta frequência. Para estado monetário, preserve a regra contábil e encontre concorrência em lançamentos somente de anexação ou em subcontas independentes, sem enfraquecer a correção.

Transações longas de ler, modificar e gravar pioram os conflitos. Leia o menor conjunto necessário, evite interação do usuário dentro de uma transação e confirme rapidamente. Se o trabalho de negócio leva minutos, represente-o como uma máquina de estados em várias transações curtas.

O comportamento de nova tentativa faz parte do contrato da aplicação

Drivers podem repetir instruções individuais ou expor um erro que permite nova tentativa ao código da aplicação. Entenda qual camada é responsável por repetir toda a transação. Uma repetição parcial pode usar decisões antigas ou omitir leituras anteriores.

Um loop de tentativas deve ter número máximo de tentativas, espera aleatória e instrumentação. Registre tipo de conflito, operação afetada, quantidade de tentativas e resultado final. Tentativas ilimitadas transformam contenção em latência oculta e podem sobrecarregar o cluster.

Solicitações de negócio precisam de identificadores estáveis para que uma resposta incerta do cliente possa ser verificada com segurança. Se o banco confirma a operação, mas a resposta se perde, o cliente deve consultar a operação já estabelecida em vez de enviar uma operação semanticamente nova.

Alterações de esquema exigem ensaio em escala de produção

Alterações de esquema distribuído podem atualizar metadados rapidamente enquanto preenchimentos retroativos e criação de índices continuam em segundo plano. Essas tarefas consomem armazenamento, rede e CPU, e podem interagir com gravações em produção.

Use migrações de expansão e contração. Primeiro, adicione campos ou tabelas compatíveis, implante código que funcione com as duas formas, faça o preenchimento em lotes controlados, mude as leituras e só então remova a forma antiga após a verificação. O planejamento de reversão deve considerar dados gravados pela nova versão.

Teste migrações grandes com volume e topologia regional semelhantes aos de produção. Uma alteração que termina rapidamente em um pequeno cluster de staging pode levar horas em produção e competir com o tráfego de clientes. Antes de começar, monitore progresso, controles de pausa, margem de disco e comportamento de nova tentativa.

Lista de adoção e prova de conceito

Uma prova de conceito útil testa uma carga representativa contra metas explícitas de correção, latência, resiliência e custo. Benchmarks genéricos não determinam se um esquema e uma aplicação específicos terão bom comportamento.

Selecione uma carga com restrições reais

Escolha um fluxo como reservar um item escasso, lançar uma transferência no livro-razão ou provisionar um locatário em uma região exigida. Reutilize seu esquema, consultas, limites de transação, tamanhos de carga e concentração de tráfego no estilo de produção.

Defina o sucesso antes de executar o teste:

  • Resultados corretos sob concorrência e novas tentativas
  • Latência p50, p95 e p99 por região
  • Capacidade máxima sustentada com margem para falhas
  • Comportamento de recuperação durante falhas de nó e região
  • Custo medido de computação, armazenamento e rede

A margem de segurança deve vir do crescimento esperado e da capacidade para falhas, e não de um multiplicador arbitrário. Se perder uma região está dentro do escopo, os locais restantes precisam lidar com a carga redirecionada durante o teste.

Crie uma superfície de aplicação realista

Uma API e uma pequena interface de usuário revelam sequência de transações, comportamento do driver e latência percebida pelo usuário que uma ferramenta apenas de banco pode não captar. Koder.ai pode criar por chat uma interface React, um backend Go e uma base PostgreSQL. Seu modo de planejamento pode ajudar a definir o fluxo antes da geração, e a exportação do código-fonte permite que engenheiros adaptem a camada de dados para um banco candidato.

Use essa aplicação gerada como estrutura de teste, não como prova de compatibilidade do banco. Execute migrações, inspecione o SQL gerado, configure o driver oficial e implemente novas tentativas de transação de propósito. Snapshots e reversão do Koder.ai podem proteger iterações da aplicação, mas não substituem backups de banco ou testes de restauração.

O Koder.ai também oferece implantação e hospedagem, o que pode posicionar instâncias de teste da aplicação perto das regiões do banco. Assim, é possível medir o caminho completo da solicitação em vez de emitir todos os benchmarks de um único local. Mantenha os dados de teste sintéticos, a menos que o ambiente tenha os controles exigidos para registros de produção.

Teste a operação normal e falhas

O teste deve cobrir tráfego constante, picos, partições quentes, consultas longas, alterações de esquema, trabalho de backup e substituição de nós. Depois, interrompa a conectividade e remova um domínio de falha no ambiente de teste aprovado.

Capture interrupções de transação, tentativas repetidas, respostas indisponíveis, movimentação de liderança, profundidade das filas, uso de disco e transferência regional. Registre o que um operador precisou fazer. Recuperação automática que exige uma etapa manual não documentada ainda não está pronta para produção.

Restaure um backup em um ambiente separado e verifique as regras da aplicação. Para estoque, confirme que alocações não excedem o estoque. Para um livro-razão, recalcule saldos e verifique lançamentos equilibrados. Para locação SaaS, confirme que as políticas de posicionamento e acesso sobreviveram à restauração.

Valide a compatibilidade antes da migração

Faça o inventário de extensões do banco, procedimentos armazenados, gatilhos, tipos de dados, premissas de isolamento, recursos de ORM, consultas de relatórios, ferramentas de backup e scripts administrativos. Classifique cada item como compatível, substituível ou bloqueador.

Execute migrações representativas em uma cópia de tamanho completo ou em um conjunto de dados gerado. Meça duração do preenchimento retroativo, atraso de captura de dados alterados, custo de execução dupla e tempo de transição. Se a migração usar gravações duplas, defina como discrepâncias serão detectadas e qual sistema permanece autoritativo em cada fase.

Leituras espelhadas podem comparar resultados sem alterar o estado de produção. Considere diferenças de tempo e consultas intencionalmente antigas para que a comparação não sinalize variações esperadas como corrupção. Qualquer diferença inexplicada em dados transacionais precisa ser resolvida antes da transição.

Revise a prontidão para produção

Uma revisão de produção deve atribuir responsáveis pela operação do banco, novas tentativas da aplicação, segurança, política de residência, custo e resposta a incidentes. Ela deve incluir painéis, alertas, runbooks, limites de capacidade, evidências de restauração e um ponto de decisão para reversão.

A decisão final ainda pode ser permanecer no PostgreSQL ou MySQL. Uma prova de conceito foi bem-sucedida quando produz evidências confiáveis, mesmo que elas mostrem que a opção distribuída custa mais do que os requisitos atuais justificam. Quando os requisitos apoiam a adoção, migre gradualmente, meça cada etapa e mantenha uma rota de retorno testada até que o novo sistema se prove sob carga real.

Perguntas frequentes

Em termos simples, o que é um banco de dados de «SQL distribuído»?

Um banco de dados SQL distribuído oferece uma interface relacional em SQL, com tabelas, joins, restrições e transações, mas funciona como um cluster em várias máquinas, muitas vezes em várias regiões, enquanto se comporta como um único banco de dados lógico.

Na prática, ele busca combinar:

  • Comportamento conhecido de SQL/ACID
  • Escalabilidade horizontal, com adição de nós
  • Alta disponibilidade e tolerância a falhas sem sharding manual
Como o SQL distribuído difere de uma configuração tradicional de PostgreSQL/MySQL?

Um RDBMS em um só nó ou com primário e réplicas costuma ser mais simples, barato e rápido para OLTP em uma única região.

O SQL distribuído se torna atraente quando a alternativa envolve:

  • Sharding gerenciado pela aplicação
  • Failover complexo entre várias regiões
  • Exigências de consistência forte entre zonas ou regiões
  • Necessidades de residência de dados com um único modelo operacional
Por que sistemas de SQL distribuído usam protocolos de consenso como Raft ou Paxos?

A maioria dos sistemas se apoia em duas ideias centrais:

  • Replicação: cada fragmento ou partição de dados é armazenado em vários nós.
  • Consenso: por exemplo, Raft ou Paxos. As réplicas concordam com a ordem das gravações, e os commits normalmente exigem confirmação da maioria.

É isso que permite consistência forte mesmo quando nós falham, mas também adiciona custo de coordenação pela rede.

Como os dados são particionados e posicionados entre nós e regiões?

Eles dividem as tabelas em partes menores, geralmente chamadas de partições/shards, ou por nomes específicos do fornecedor, como ranges, tablets ou splits. Cada partição:

  • Tem seu próprio grupo de réplicas
  • Pode ficar em nós ou regiões específicos
  • Pode ser movida quando o cluster se reequilibra

Em geral, você influencia o posicionamento com políticas para manter dados muito acessados e os principais gravadores por perto, reduzindo viagens pela rede.

Por que transações podem ser mais lentas no SQL distribuído, sobretudo entre regiões?

Transações distribuídas costumam tocar várias partições, possivelmente em nós ou regiões diferentes. Um commit seguro pode exigir:

  • Bloqueios ou validação entre os participantes
  • Confirmações de replicação, formando quórum
  • Uma decisão de commit coordenada

Essas idas e voltas extras pela rede são o principal motivo de a latência de gravação aumentar, especialmente quando o consenso envolve regiões diferentes.

Quais são os sinais mais claros de que realmente preciso de SQL distribuído?

Considere SQL distribuído quando duas ou mais situações forem verdadeiras:

  • Você tem usuários relevantes em várias regiões e quer dados consistentes
  • Precisa de failover automático entre zonas ou regiões, com RTO/RPO rigorosos
  • Escalar verticalmente já não basta para as gravações
  • Precisa de consistência forte em transações centrais, como dinheiro, estoque ou reservas
  • A conformidade exige posicionamento geográfico dos dados

Se sua carga cabe em uma região com réplicas e cache, um RDBMS convencional costuma ser a melhor escolha inicial.

O que a «consistência forte» me traz e qual é o custo?

Consistência forte significa que, depois que uma transação é confirmada, as leituras não verão dados antigos.

Em termos de produto, ela ajuda a evitar:

  • Gasto duplo ou saldos incorretos
  • Venda da última unidade para mais de uma pessoa
  • Dois usuários reservando o mesmo assento

A contrapartida é que, durante partições de rede, um sistema fortemente consistente pode bloquear ou falhar algumas operações em vez de aceitar versões divergentes da verdade.

Como lidar com novas tentativas de forma segura, usando idempotência, no SQL distribuído?

Baseie-se em restrições e transações do banco de dados:

  • Armazene uma idempotency_key ou similar por solicitação ou tentativa
  • Adicione uma restrição de unicidade, como (account_id, idempotency_key)
  • Em uma única transação, grave o registro de negócio e as linhas de razão ou caixa de saída

Assim, novas tentativas não criam duplicatas, algo essencial para pagamentos, provisionamento e reprocessamento de tarefas em segundo plano.

Como escolher entre Spanner, CockroachDB e YugabyteDB?

Uma separação prática:

  • Spanner: em geral gerenciado no GCP, com forte histórico de arquitetura multirregional. A escolha do dialeto SQL afeta a portabilidade.
  • CockroachDB: experiência e protocolo de conexão semelhantes ao Postgres, gerenciado ou auto-hospedado, mas não é 100% compatível com Postgres.
  • YugabyteDB: API SQL compatível com Postgres, YSQL, além de uma API opcional no estilo Cassandra, YCQL. Gerenciado ou auto-hospedado.

Antes de decidir, teste seu ORM, suas migrações e quaisquer extensões do Postgres de que você depende. Não presuma que será uma substituição direta.

Qual é um bom plano de prova de conceito antes de adotar SQL distribuído?

Comece com uma prova de conceito focada em um fluxo crítico, como checkout, reserva ou lançamento contábil. Valide:

  • Correção, sem reservas duplicadas ou atualizações perdidas
  • Latência p50/p95 das consultas principais, incluindo metas entre regiões
  • Comportamento em falhas, como perda de nó, zona e, quando relevante, região
  • Fundamentos operacionais, como monitoramento, backups e testes de restauração

Se precisar definir custos ou planos, consulte a página de preços. Para notas de implementação relacionadas, consulte o blog.

Related posts