Skriving på tvers av regioner: hvor blir endringen egentlig bekreftet?
Ruting bringer en forespørsel til en region; bare en transaksjonsgrense gjør skrivingen atomisk. Navngi invarianten, velg eieren, og design deretter nytt forsøket rundt den.
To applikasjonsservere i to regioner, én klient som skriver gjennom en VPN, og et spørsmål ingen skrev ned: hvilken komponent avgjør at skrivingen skjedde? Ruting bringer forespørselen til en prosess. En transaksjonsgrense avgjør når endringen blir varig og synlig. Dette er forskjellige jobber utført av forskjellige systemer, og gapet mellom dem er der de fleste feilene i skriving på tvers av regioner bor.
Start med forretningsregelen, ikke med kartet
Start med en setning om forretningsregelen i stedet for om geografien: hvilke lesinger og skrivinger må lykkes sammen, og hvilke samtidige endringer må være umulige mens de gjør det. For en lagerreservasjon betyr det at lagerkontrollen og reservasjonen enten begge trer i kraft eller ingen av dem, og ingen andre ordrer kan forbruke den samme enheten imellom.
| 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 |
Det er nettopp den midterste raden team hopper over. Atomisitet uten tilstrekkelig isolasjon lar to transaksjoner hver bli bekreftet korrekt og likevel produsere en tilstand som forretningen anser som umulig, og ingen mengde nytt-forsøk-logikk reparerer det i ettertid.
Én autoritativ grense slår to regionale servere
Regionale applikasjonsservere kan bli der de er, så lenge de sender operasjonen til en tjeneste som utfører den innenfor én støttet transaksjonsgrense. Applikasjonslaget blir en ruter for intensjon; datalaget eier sannheten.
Hold den grensen kort og nær dataene den berører. En transaksjon som holdes åpen mens et menneske svarer på en forespørsel, eller mens et kall krysser to regioner, bruker tiden sin på å holde låser og øker sjansen for at noe annet går ut på tid bak den. Den feilen ser ut som et databaseproblem og er egentlig et designproblem som har kledd seg ut som ett. Å flytte beslutningen ned i datalaget fjerner det vanligvis 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;
Les den skissen som en grense, ikke som en ytelsesanbefaling. Poenget er at kontrollen og innsettingen deler én bekreftelse, så en samtidig ordre ser enten lageret forbrukt eller ser det ikke i det hele tatt.
Hva en replikert database gir og ikke gir
En replikert database kan gi en bredere grense når dens egen transaksjonsmodell støtter det. Spanner dokumenterer atomiske lese-skrive-transaksjoner innenfor én database på tvers av tabeller, med definert isolasjon og nytt-forsøk-atferd. Det er en garanti man leser, tester og bevisst hviler på.
Det er også en garanti som kommer fra produktet, ikke fra ruten. En VPN mellom regioner endrer hvordan pakker reiser og hvordan feil viser seg. Den forlenger ikke en transaksjonsgrense med en eneste rad, uansett hvor sunn tunnelen ser ut. Å forveksle de to skaper arkitekturer der hver komponent består sin egen kontroll og dataene fortsatt er uenige.
To databaser blir ikke ett system
To uavhengig administrerte databaser får ikke en felles transaksjonsbehandler fordi klienter kan nå begge. Hvis forretningen virkelig trenger en atomisk forpliktelse over paret, må koordineringsmekanismen, deltakerne og gjenopprettingsprosessen alle velges og kvalifiseres i stedet for å antas.
Tenk på øyeblikket der en deltaker eller en lenke forsvinner etter at arbeidet er forberedt. En støttet distribuert bekreftelse kan etterlate en uavklart tilstand som trenger en gjenopprettingsprosedyre og en menneskelig beslutning, og den kommer uten et løfte om at hver region forblir skrivbar gjennom hver partisjon.
Hvis asynkron koordinering i stedet er akseptabelt, si det eksplisitt og skriv ned de mellomliggende forretningstilstandene og avstemmingsreglene. En kjede av lokalt bekreftede trinn med kompensasjon er et legitimt design; det er bare ikke én atomisk transaksjon under et annet navn.
Design nytt forsøket før det første avbruddet
En klient kan miste svaret etter at operasjonen er bekreftet, så den som kaller kan ikke behandle tidsavbrudd som feil. Bevar en varig forespørselsidentitet og bruk tjenestens resultat eller en idempotensmekanisme før en endring prøves på nytt, ellers blir nytt forsøk en andre skriving.
Automatiske transaksjons-callbacks kan også kjøre mer enn én gang etter en abort som kan prøves på nytt, noe som gjør dem til et dårlig hjem for irreversible eksterne effekter. Hold dem utenfor callbacken med mindre arbeidsflyten definerer en eksplisitt sikker protokoll for dem. Samme forsiktighet gjelder for alt som koster penger eller sender en melding. En dobbel belastning er en mye vanskeligere samtale enn en dobbel logglinje.
Aksept bør spille av fire scenarioer: to klienter som kjemper om samme rad, en abort tjenesten sier kan prøves på nytt, en bekreftelse der svaret aldri kommer, og tapet av en region eller lenken mellom dem. Registrer det bekreftede forretningsresultatet og de uavklarte tilstandene ved siden av rutingsdesignet, så ingen forveksler nettverket med komponenten som gir garantien.