Två applikationsservrar i två regioner, en klient som skriver via en VPN och en fråga som ingen skrev ned: vilken komponent avgör att skrivningen har skett? Routing för begäran till en process. En transaktionsgräns avgör när ändringen blir beständig och synlig. Det är olika jobb som utförs av olika system, och gapet mellan dem är där de flesta fel vid skrivning över regioner bor.

Börja med affärsregeln, inte med kartan

Börja med en mening om affärsregeln i stället för om geografin: vilka läsningar och skrivningar måste lyckas tillsammans, och vilka samtidiga ändringar måste vara omöjliga medan det sker. För en lagerreservation innebär det att lagerkontrollen och reservationen antingen båda träder i kraft eller ingen av dem, och ingen andra order får förbruka samma enhet däremellan.

RequirementWhat satisfies itWhat does not
All-or-nothing applicationA transaction inside one owning systemA VPN path between regions
No double spendIsolation strong enough to exclude the conflictAtomicity alone
Survive a region lossReplication the database itself documentsTwo independent databases behind one client

Det är just den mittersta raden som team hoppar över. Atomicitet utan tillräcklig isolering låter två transaktioner båda bekräftas korrekt och ändå producera ett tillstånd som verksamheten anser omöjligt, och ingen mängd omförsökslogik reparerar det i efterhand.

En auktoritativ gräns slår två regionala servrar

Regionala applikationsservrar kan stanna där de är, så länge de lämnar operationen till en tjänst som utför den inom en enda stödd transaktionsgräns. Applikationslagret blir en router för avsikt; datalagret äger sanningen.

Håll den gränsen kort och nära de data den rör. En transaktion som hålls öppen medan en människa svarar på en uppmaning, eller medan ett anrop korsar två regioner, lägger sin tid på att hålla lås och ökar chansen att något annat får tidsutfall bakom den. Det felet ser ut som ett databasproblem och är egentligen ett designproblem som klätt ut sig till ett. Att flytta beslutet till datalagret tar oftast bort det helt.

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;

Läs den skissen som en gräns, inte som en prestandarekommendation. Poängen är att kontrollen och infogningen delar en enda bekräftelse, så en samtidig order ser antingen lagret förbrukat eller ser det inte alls.

Vad en replikerad databas ger och inte ger

En replikerad databas kan ge en bredare gräns när dess egen transaktionsmodell stöder det. Spanner dokumenterar atomiska läs- och skrivtransaktioner inom en enda databas över tabeller, med definierad isolering och omförsöksbeteende. Det är en garanti som man läser, testar och medvetet förlitar sig på.

Det är också en garanti som kommer från produkten, inte från vägen. En VPN mellan regioner ändrar hur paket reser och hur fel visar sig. Den förlänger inte en transaktionsgräns med en enda rad, hur frisk tunneln än ser ut. Att blanda ihop de två ger arkitekturer där varje komponent klarar sin egen kontroll och data ändå inte stämmer.

Två databaser blir inte ett system

Två oberoende administrerade databaser får inte en delad transaktionshanterare för att klienter kan nå båda. Om verksamheten verkligen behöver en atomisk förpliktelse över paret måste koordineringsmekanismen, deltagarna och återställningsprocessen alla väljas och kvalificeras i stället för att antas.

Tänk på ögonblicket då en deltagare eller en länk försvinner efter att arbetet förberetts. En stödd distribuerad bekräftelse kan lämna ett oklart tillstånd som kräver en återställningsprocedur och ett mänskligt beslut, och den kommer utan ett löfte om att varje region förblir skrivbar genom varje partition.

Om asynkron koordinering i stället är acceptabel, säg det uttryckligen och skriv ned de mellanliggande affärstillstånden plus avstämningsreglerna. En kedja av lokalt bekräftade steg med kompensation är en legitim design; det är bara inte en enda atomär transaktion under ett annat namn.

Designa omförsöket före det första avbrottet

En klient kan förlora svaret efter att operationen har bekräftats, så anroparen kan inte behandla en timeout som ett fel. Bevara en varaktig begärandeidentitet och använd tjänstens resultat eller en idempotensmekanism innan en ändring görs om, annars blir omförsöket en andra skrivning.

Automatiska transaktions-callbacks kan också köras mer än en gång efter ett omförsökbart avbrott, vilket gör dem till ett dåligt hem för oåterkalleliga externa effekter. Håll dem utanför callbacken om inte arbetsflödet definierar ett uttryckligt säkert protokoll för dem. Samma försiktighet gäller för allt som kostar pengar eller skickar ett meddelande. En dubbel debitering är ett mycket svårare samtal än en dubbel logg rad.

Acceptansen bör spela upp fyra scenarier: två klienter som tävlar om samma rad, ett avbrott som tjänsten säger kan göras om, en bekräftelse vars svar aldrig kommer, och förlusten av en region eller länken mellan dem. Registrera det bekräftade affärsresultatet och de olösta tillstånden bredvid routingdesignen, så att ingen förväxlar nätverket med komponenten som ger garantin.

Relaterade artiklar