Escritas multirregião: onde a confirmação realmente acontece?
O encaminhamento leva um pedido a uma região; só uma fronteira de transação torna as escritas atómicas. Nomeie o invariante, escolha o proprietário e depois desenhe a nova tentativa em torno dele.
Dois servidores de aplicação em duas regiões, um cliente que escreve através de uma VPN e uma pergunta que ninguém escreveu: que componente decide que a escrita aconteceu? O encaminhamento leva o pedido até um processo. Uma fronteira de transação decide quando a alteração se torna duradoura e visível. São tarefas diferentes realizadas por sistemas diferentes, e a lacuna entre elas é onde vive a maioria dos erros de escrita multirregião.
Comece pela regra de negócio, não pelo mapa
Comece por uma frase sobre a regra de negócio e não sobre a geografia: que leituras e escritas têm de ter sucesso em conjunto e que alterações concorrentes têm de ser impossíveis enquanto isso acontece. Para uma reserva de inventário isso significa que a verificação de stock e a reserva ou ambas produzem efeito ou nenhuma, e nenhum segundo pedido pode consumir a mesma unidade entretanto.
| Requirement | What satisfies it | What does not |
|---|---|---|
| All-or-nothing application | A transaction inside one owning system | A VPN path between regions |
| No double spend | Isolation strong enough to exclude the conflict | Atomicity alone |
| Survive a region loss | Replication the database itself documents | Two independent databases behind one client |
É precisamente essa linha do meio que as equipas saltam. A atomicidade sem isolamento suficiente permite que duas transações se confirmem corretamente cada uma e ainda assim produzam um estado que o negócio considera impossível, e nenhuma quantidade de lógica de nova tentativa o repara depois.
Uma fronteira autoritativa vence dois servidores regionais
Os servidores de aplicação regionais podem ficar onde estão, desde que submetam a operação a um serviço que a execute dentro de uma única fronteira de transação suportada. A camada de aplicação torna-se um encaminhador de intenção; a camada de dados possui a verdade.
Mantenha essa fronteira curta e próxima dos dados que toca. Uma transação mantida aberta enquanto uma pessoa responde a um pedido, ou enquanto uma chamada atravessa duas regiões, passa o tempo a segurar bloqueios e a aumentar a probabilidade de algo mais expirar atrás dela. Essa falha parece um problema de base de dados e é na realidade um problema de desenho disfarçado de um. Mover a decisão para a camada de dados geralmente elimina-o por completo.
BEGIN;
UPDATE inventory SET reserved = reserved + 1
WHERE sku = 'A-100' AND available >= 1;
INSERT INTO reservation (sku, order_id) VALUES ('A-100', 'ord-9f');
COMMIT;
Leia esse esboço como uma fronteira, não como uma recomendação de desempenho. O ponto é que a verificação e a inserção partilham uma confirmação, pelo que um pedido concorrente ou vê o stock consumido ou não o vê de todo.
O que uma base de dados replicada dá e não dá
Uma base de dados replicada pode fornecer uma fronteira mais ampla quando o seu próprio modelo de transação o permite. O Spanner documenta transações atómicas de leitura e escrita dentro de uma única base de dados entre tabelas, com isolamento e comportamento de nova tentativa definidos. É uma garantia que se lê, testa e na qual se confia deliberadamente.
É também uma garantia que vem do produto, não da rota. Uma VPN entre regiões altera a forma como os pacotes viajam e como as falhas se apresentam. Não estende uma fronteira de transação nem uma linha, por muito saudável que o túnel pareça. Confundir as duas coisas produz arquiteturas em que cada componente passa a sua própria verificação e os dados continuam a divergir.
Duas bases de dados não se tornam um só sistema
Duas bases de dados geridas de forma independente não adquirem um gestor de transações partilhado pelo facto de os clientes conseguirem alcançar ambas. Se o negócio precisa realmente de um compromisso atómico sobre o par, o mecanismo de coordenação, os participantes e o processo de recuperação têm de ser escolhidos e qualificados em vez de assumidos.
Pense no momento em que um participante ou uma ligação desaparece depois de o trabalho ter sido preparado. Uma confirmação distribuída suportada pode deixar um estado em dúvida que exige um procedimento de recuperação e uma decisão humana, e não vem com a promessa de que cada região permaneça escrevível através de cada partição.
Se em vez disso for aceitável uma coordenação assíncrona, diga-o explicitamente e registe os estados de negócio intermédios e as regras de reconciliação. Uma cadeia de passos confirmados localmente com compensação é um desenho legítimo; simplesmente não é uma transação atómica com outro nome.
Desenhe a nova tentativa antes da primeira falha
Um cliente pode perder a resposta depois de a operação ter sido confirmada, pelo que quem chama não pode tratar um tempo limite como falha. Preserve uma identidade de pedido duradoura e use o resultado do serviço ou um mecanismo de idempotência antes de repetir uma mutação, caso contrário a nova tentativa torna-se uma segunda escrita.
As chamadas de retorno automáticas de transações também podem executar-se mais de uma vez após um aborto repetível, o que as torna um mau local para efeitos externos irreversíveis. Mantenha essas fora da chamada de retorno, a menos que o fluxo de trabalho defina um protocolo seguro explícito para elas. A mesma cautela aplica-se a tudo o que custe dinheiro ou envie uma mensagem. Uma cobrança duplicada é uma conversa muito mais difícil do que uma linha de registo duplicada.
A aceitação deve repetir quatro cenários: dois clientes em corrida pela mesma linha, um aborto que o serviço diz ser repetível, uma confirmação cuja resposta nunca chega e a perda de uma região ou da ligação entre elas. Registe o resultado de negócio confirmado e os estados não resolvidos ao lado do desenho do encaminhamento, para que ninguém confunda a rede com o componente que fornece a garantia.