PostgreSQL og indstillinger for konsistens af skrivninger for hver enkelt forbindelse

Oversættelsen er specielt udarbejdet til studerende på kurset «Databaser». Er du interesseret i at udvikle dig i dette område? Vi inviterer dig til Åbent Hus-dag, hvor vi detaljeret fortæller om programmet, de særlige forhold ved online-formatet, kompetencerne og karrieremulighederne, som venter kandidaterne efter uddannelsen.

PostgreSQL og indstillinger for konsistens af skrivninger for hver enkelt forbindelse

PostgreSQL og indstillinger for konsistens af skrivninger for hver enkelt forbindelse
Hos Compose arbejder vi med mange databaser, hvilket giver os mulighed for at lære deres funktionalitet og begrænsninger at kende. Efterhånden som vi lærer at værdsætte de funktionelle egenskaber ved nye databaser, begynder vi nogle gange at tænke på, hvor godt det ville være, hvis sådanne funktioner også blev tilgængelige i mere etablerede værktøjer, som vi har arbejdet med i lang tid. En af de nye funktioner, som vi ønskede at se i PostgreSQL, var konfigurerbar skrivningskonsistens pr. forbindelse i hele klyngen. Og som det viste sig, har vi det allerede, og i dag vil vi dele information med dig om, hvordan du kan bruge det.

Hvorfor vil jeg have dette?

Hvordan klyngen skal fungere, afhænger af din applikation. Lad os tage et eksempel med en betalingsapplikation. Du vil have 100% konsistens i klyngen, så du bliver nødt til at aktivere synkrone commits, så din database venter på, at alle ændringer er foretaget. Men hvis din applikation er et hurtigt voksende socialt netværk, vil du sandsynligvis foretrække hurtig respons frem for 100% konsistens. For at opnå dette kan du bruge asynkrone commits i din klynge.

Mød kompromiset

Du skal finde et kompromis mellem datakonsistens og ydeevne. PostgreSQL skrider væk fra konsistens, da standardkonfigurationen i dette tilfælde er forudsigelig og uden uventede overraskelser. Lad os nu se på kompromiserne.

Kompromis 1: Ydeevne

Hvis PostgreSQL-clusteret ikke kræver konsistens, kan det fungere asynkront. Skriveoperationer skjer på clusterets leder, og opdateringer vil blive sendt til replikaerne efter et par millisekunder. Når PostgreSQL-clusteret kræver konsistens, skal det fungere synkront. Skriveoperationen vil blive udført på lideren, som sender opdateringen til replikaerne og venter på bekræftelse, så hver replika har udført skriveoperationen, før den sender bekræftelsen til klienten, der initierede skridningen, om at den blev udført med succes. Den praktiske forskel mellem disse tilgange er, at den asynkrone metode kræver to netværksspring, mens den synkrone kræver fire.

Kompromis 2: Konsistens

Resultatet ved en fejl på lederen i disse to tilgange vil også være forskelligt. Hvis opgaven udføres asynkront, vil ikke alle optegnelser være bekræftet af replikaerne i tilfælde af en sådan fejl. Hvor meget vil gå tabt? Det afhænger af applikationen og effektiviteten af replikationen. Compose-replikation forhindrer en replika i at blive leder, hvis mængden af information i den er 1 MB mindre end i lederen, hvilket betyder, at der potentielt kan gå op til 1 MB optegnelser tabt ved asynkron drift.

Dette sker ikke i den synkrone tilstand. Hvis lederen fejler, opdateres alle replikaer, da enhver optegnelse, der er bekræftet på lederen, også skal bekræftes i replikaerne. Her har vi konsistens.

Synkront adfærd giver mening at anvende i en betalingsapplikation, hvor konsistens har en åbenlys fordel i at finde et kompromis mellem konsistens og ydeevne. Det vigtigste for sådan en applikation er gyldige data. Og tænk nu på et socialt netværk, hvor hovedopgaven er at fastholde brugerens opmærksomhed ved at svare på forespørgsler så hurtigt som muligt. I dette tilfælde vil ydeevnen med færre netværksspring og kortere ventetid på bekræftelser være prioriteret. Men kompromiset mellem ydeevne og konsistens er ikke det eneste, man skal overveje.

Kompromis 3: Fejl

Det er meget vigtigt at forstå, hvordan en klynge opfører sig under en fejl. Lad os overveje en situation, hvor en eller flere replikaer fejler. Når commits behandles asynkront, vil lederen fortsætte med at fungere, dvs. tage imod og behandle optegnelser uden at vente på de manglende replikaer. Når replikaerne vender tilbage til klyngen, indhenter de lederen. Ved synkron replikation, hvis replikaerne ikke svarer, har lederen ingen valg og vil fortsætte med at vente på bekræftelse af commit, indtil replikaen vender tilbage til klyngen og kan modtage og bekræfte optegnelsen.

Én forbindelse pr. transaktion?

Hver applikation har brug for en særlig type kombination af konsistens og ydeevne. Medmindre det selvfølgelig er vores regningsbetalingsapp, som vi forestiller os er helt konsistent, eller vores næsten flygtige sociale medieapp. I alle andre tilfælde vil der være tidspunkter, hvor nogle operationer skal være synkrone, mens andre skal være asynkrone. Du vil måske ikke have, at systemet skal vente på, at en besked sendt i chatten bliver committed, men hvis der også foretages en betaling i denne app, må man vente.

Alle disse beslutninger træffes naturligvis af applikationsudvikleren. De rigtige beslutninger om, hvornår man skal anvende hvilken tilgang, hjælper med at maksimere udbyttet af klyngen. Det er vigtigt, at udvikleren kan skifte mellem dem på SQL-niveau for forbindelser og for transaktioner.

At sikre kontrol i praksis

Som standard sikrer PostgreSQL konsistens. Dette kontrolleres af serverparameteren synchronous_commit. Som standard er den i position on, men den har tre andre muligheder: local, remote_write eller off.

Når parameteren er indstillet til off sættes alle synkrone commits på pause, selv i det lokale system. Parameteren i local definerer den synkrone tilstand for det lokale system, men optegnelser til replikaer udføres asynkront. Remote_write går endnu længere: optegnelser til replikaer foretages asynkront, men returneres, når replikaen har modtaget optegnelsen, men ikke har skrevet den til disk.

Når vi overvejer det eksisterende udvalg af muligheder, vælger vi adfærden, og vi husker, at on – er synkrone optegnelser, så vi vil vælge local for asynkrone commits over netværket, mens vi holder lokale commits synkrone.

Nu vil vi fortælle dig, hvordan du hurtigt kan konfigurere dette, men forestil dig, at vi installerede synchronous_commit i local til serveren. Vi spekulerede på, om vi kunne ændre parameteren synchronous_commit on-the-fly, og det viste sig, at det ikke bare var muligt, men der er faktisk to måder at gøre det på. Den første måde er at indstille din sessions forbindelse som følger:

SET SESSION synchronous_commit TO ON;  
// Dine skrivninger kommer her

Alle efterfølgende skriver i sessionen vil bekræfte skriveoperationer for replikaer, før en positivt resultat returneres til den tilsluttede klient. Medmindre du selvfølgelig ændrer indstillingen synchronous_commit igen. Du kan udelade delen SESSION i kommandoen, da den vil være i standardværdien.

Den anden måde er god, når du bare vil sikre dig, at du får synkron replikering for en enkelt transaktion. I mange NoSQL-databaser findes begrebet transaktioner ikke, men det findes i PostgreSQL. I dette tilfælde starter du en transaktion og indstiller derefter synchronous_commit i on før udførelsen af skrivningen til transaktionen. COMMIT vil bekræfte transaktionen ved hjælp af den parameterindstilling synchronous_commit, der var indstillet på det tidspunkt, selvom det er bedst at indstille variablen på forhånd for at sikre, at andre udviklere forstår, at skrivningerne ikke er asynkrone.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Dine skrivninger kommer her
COMMIT;  

Alle commit-ter for transaktioner vil nu bekræftes som skrevet til replikaer, før databasen returnerer et positivt svar til den tilsluttede klient.

Konfiguration af PostgreSQL

Indtil nu har vi forestillet os et PostgreSQL-system med synchronous_commit, installeret på local. For at dette kan realiseres på server siden, skal du indstille to serverkonfigurationsparametre. En anden parameter synchronous_standby_names vil træde i kraft, når synchronous_commit er i on. Det definerer, hvilke replikaer der har ret til synkrone commits, og vi vil indstille den til *, hvilket vil betyde, at alle replikaer aktiveres. Disse værdier konfigureres normalt i konfigurationsfilen ved at tilføje:

synchronous_commit = local  
synchronous_standby_names='*'

Ved at indstille parameteren synchronous_commit til værdien local, skaber vi et system, hvor lokale diske forbliver synkrone, men commits til netværksreplikaer som standard er asynkrone. Medmindre vi selvfølgelig beslutter at gøre disse commits synkrone, som vist ovenfor.

Hvis du har fulgt udviklingen af projektet Governor, du måske har bemærket nogle recente ændringer (1, 2), som har gjort det muligt for brugerne af Governor at teste disse parametre og kontrollere deres konsistens.

Et par ord mere…

For blot en uge siden ville jeg have sagt, at det var umuligt at finjustere PostgreSQL så præcist. Det var lige da Kurt, medlem af Compose team's platform, insisterede på, at der var en mulighed for det. Han tavsede mine indvendinger og fandt i PostgreSQL-dokumentationen følgende:

PostgreSQL og indstillinger for konsistens af skrivninger for hver enkelt forbindelse

Denne parameter kan ændres når som helst. Adfærden for enhver transaktion bestemmes af indstillingen, der gælder ved commit. Derfor kan det være nyttigt, at commits for nogle transaktioner foretages synkront, mens de for andre foretages asynkront. For eksempel for at tvinge en multistatement transaktion til at udføre commits asynkront, når standardværdien for parameteren er den modsatte, skal du indstille SET LOCAL synchronous_commit TO OFF i transaktionen.

Med en så lille modification i konfigurationsfilen har vi givet brugerne mulighed for at kontrollere deres konsistens og ydeevne.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster