PostgreSQL og tilkoblingsspesifikke skrivekonsistensinnstillinger

Oversettelsen av artikkelen ble utarbeidet spesielt for studentene på kurset "Database". Interessert i å utvikle seg i denne retningen? Vi inviterer deg til Åpen dag, hvor vi snakker i detalj om programmet, funksjoner i nettformatet, kompetanse og karrieremuligheter som venter nyutdannede etter trening.

PostgreSQL og tilkoblingsspesifikke skrivekonsistensinnstillinger

PostgreSQL og tilkoblingsspesifikke skrivekonsistensinnstillinger
Hos Compose har vi å gjøre med mange databaser, noe som gir oss muligheten til å bli mer kjent med deres funksjonalitet og mangler. Når vi lærer å elske funksjonene til nye databaser, begynner vi noen ganger å tenke på hvor fint det ville vært om lignende funksjoner var til stede i de mer modne verktøyene vi har jobbet med lenge. En av de nye funksjonene som jeg ønsket å se i PostgreSQL var konfigurerbar skrivekonsistens for en tilkobling på tvers av hele klyngen. Og som det viser seg, har vi det allerede, og i dag ønsker vi å dele informasjon med deg om hvordan du kan bruke det.

Hvorfor trenger jeg det?

Hvordan klyngen skal oppføre seg avhenger av applikasjonen din. Ta for eksempel en app for betaling av regninger. Du trenger XNUMX % konsistens på tvers av klyngen, så du må aktivere synkrone forpliktelser slik at databasen venter på at alle endringer skal gjøres. Men hvis søknaden din er et raskt voksende sosialt nettverk, vil du sannsynligvis foretrekke rask respons fremfor XNUMX % konsistens. For å oppnå dette kan du bruke asynkrone forpliktelser i klyngen din.

Møt kompromisser

Du må gjøre avveininger mellom datakonsistens og ytelse. PostgreSQL beveger seg bort fra konsistens fordi standardkonfigurasjonen da er forutsigbar og uten uventede overraskelser. La oss nå se på kompromissene.

Avveining 1: Ytelse

Hvis PostgreSQL-klyngen ikke krever konsistens, kan den kjøres asynkront. Skrivingen gjøres til klyngelederen, og oppdateringer vil bli sendt til replikaene noen få millisekunder senere. Når en PostgreSQL-klynge krever konsistens, må den kjøres synkront. Skrivingen vil bli gjort til klyngelederen, som vil sende en oppdatering til replikaene og vente på bekreftelse på at hver enkelt har skrevet før du sender bekreftelse til klienten som startet skrivingen om at den var vellykket. Den praktiske forskjellen mellom disse tilnærmingene er at den asynkrone metoden krever to nettverkshopp, mens den synkrone metoden krever fire.

Avveining 2: Konsistens

Resultatet ved ledersvikt i disse to tilnærmingene vil også være forskjellig. Hvis arbeidet utføres asynkront, så hvis en slik feil oppstår, vil ikke alle poster bli begått av replikaene. Hvor mye vil gå tapt? Avhenger av selve applikasjonen og effektiviteten av replikering. Compose-replikering vil forhindre at en replika blir en leder hvis mengden informasjon i den er 1 MB mindre enn i lederen, det vil si at opptil 1 MB med poster potensielt kan gå tapt under asynkron drift.

Dette skjer ikke i synkron modus. Hvis lederen mislykkes, oppdateres alle replikaene, siden enhver skriving bekreftet på lederen må bekreftes på replikaene. Dette er konsistens.

Synkron oppførsel gir mening i en faktureringsapplikasjon der konsistens har en klar fordel i avveiningen mellom konsistens og ytelse. Det viktigste for en slik applikasjon er gyldige data. Tenk nå på et sosialt nettverk der hovedoppgaven er å holde brukerens oppmerksomhet ved å svare på forespørsler så raskt som mulig. I dette tilfellet vil ytelse med færre nettverkshopp og mindre ventetid på forpliktelser være en prioritet. Avveiningen mellom ytelse og konsistens er imidlertid ikke den eneste du må tenke på.

Avveining 3: Krasj

Det er veldig viktig å forstå hvordan en klynge oppfører seg under en feil. Tenk på en situasjon der en eller flere kopier mislykkes. Når commits behandles asynkront, vil lederen fortsette å fungere, det vil si akseptere og behandle skrivinger, uten å vente på manglende replikaer. Når kopiene kommer tilbake til klyngen, tar de igjen lederen. Med synkron replikering, hvis replikaene ikke reagerer, vil lederen ikke ha noe valg og vil fortsette å vente på bekreftelse av forpliktelsen til replikaen kommer tilbake til klyngen og kan godta og foreta skrivingen.

Én tilkobling per transaksjon?

Hver applikasjon trenger en annen type kombinasjon av konsistens og ytelse. Med mindre det selvfølgelig er vår regning-betalende app, som vi ser for oss å være helt konsistent, eller vår nesten flyktige sosiale nettverksapp. I alle andre tilfeller vil det være tider når noen operasjoner må være synkrone og noen må være asynkrone. Du vil kanskje ikke at systemet skal vente til en melding som sendes til chatten er forpliktet, men hvis en betaling behandles i samme applikasjon, må du vente.

Alle disse avgjørelsene tas selvfølgelig av applikasjonsutvikleren. Å ta de riktige avgjørelsene om når du skal bruke hver tilnærming vil hjelpe deg å få mest mulig ut av klyngen din. Det er viktig at utvikleren kan bytte mellom dem på SQL-nivå for tilkoblinger og for transaksjoner.

Sikre kontroll i praksis

Som standard gir PostgreSQL konsistens. Dette styres av serverparameteren synchronous_commit. Som standard er den i posisjon on, men den har tre andre alternativer: local, remote_write eller off.

Når du setter parameteren til off alle synkrone commits stoppes, selv på det lokale systemet. Den lokale parameteren spesifiserer synkron modus for det lokale systemet, men skriving til replikaer utføres asynkront. Remote_write går enda lenger: skriving til replikaer gjøres asynkront, men returneres når replikaen har akseptert skrivingen, men ikke har skrevet den til disk.

Ved å vurdere det tilgjengelige utvalget av alternativer, velger vi en atferd og huske på det on – dette er synkrone opptak, vil vi velge local for asynkrone commits over nettverket, mens lokale commits skal være synkrone.

Nå skal vi fortelle deg hvordan du setter opp dette om et øyeblikk, men forestill deg at vi setter opp synchronous_commit в local for serveren. Vi lurte på om det var mulig å endre parameteren synchronous_commit på farten, og det viste seg at det ikke bare er mulig, det er til og med to måter å gjøre dette på. Den første er å angi økten for tilkoblingen din som følger:

SET SESSION synchronous_commit TO ON;  
// Your writes go here

Alle påfølgende skrivinger i økten vil bekrefte skrivinger til replikaene før de returnerer et positivt resultat til den tilkoblede klienten. Med mindre du endrer innstillingen synchronous_commit en gang til. Du kan utelate en del SESSION i kommandoen fordi den vil være i standardverdien.

Den andre metoden er god når du bare vil sørge for at du får synkron replikering for en enkelt transaksjon. I mange NoSQL-generasjonsdatabaser eksisterer ikke konseptet med transaksjoner, men det gjør det i PostgreSQL. I dette tilfellet starter du en transaksjon og setter deretter synchronous_commit в on før du utfører oppføringen for transaksjonen. COMMIT vil forplikte transaksjonen ved å bruke en hvilken som helst parameterverdi synchronous_commit, som ble satt på den tiden, selv om det er best å sette variabelen på forhånd for å sikre at andre utviklere forstår at skriving ikke er asynkron.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Your writes go here
COMMIT;  

Alle transaksjonsbekreftelser vil nå bli bekreftet som skrevet til replikaer før databasen returnerer et positivt svar til den tilkoblede klienten.

Sette opp PostgreSQL

Før dette så vi for oss et PostgreSQL-system med synchronous_commit, installert i local. For å gjøre dette realistisk på serversiden, må du angi to serverkonfigurasjonsalternativer. En parameter til synchronous_standby_names vil komme til sin rett når synchronous_commit vil være i on. Den avgjør hvilke replikaer som er kvalifisert for synkrone forpliktelser, og vi vil sette den til *, som vil bety at alle kopier er involvert. Disse verdiene er vanligvis konfigurert i konfigurasjonsfil ved å legge til:

synchronous_commit = local  
synchronous_standby_names='*'

Ved å stille inn parameteren synchronous_commit til mening local, lager vi et system der lokale disker forblir synkrone, men nettverksreplika-commits er asynkrone som standard. Med mindre vi bestemmer oss for å gjøre disse forpliktelsene synkrone, som vist ovenfor.

Hvis du har fulgt utviklingen Sysselmannsprosjekt, du har kanskje lagt merke til noen nylige endringer (1, 2), som tillot Governor-brukere å teste disse parameterne og overvåke konsistensen deres.

Noen flere ord...

For bare en uke siden ville jeg ha fortalt deg at det er umulig å finjustere PostgreSQL så fint. Det var da Kurt, et medlem av Compose-plattformteamet, insisterte på at en slik mulighet eksisterte. Han roet mine innvendinger og fant i PostgreSQL-dokumentasjonen følgende:

PostgreSQL og tilkoblingsspesifikke skrivekonsistensinnstillinger

Denne innstillingen kan endres når som helst. Atferden for enhver transaksjon bestemmes av innstillingen som er gjeldende på tidspunktet for forpliktelsen. Derfor er det mulig og nyttig for noen transaksjoner å foreta synkront og for andre asynkront. For eksempel å tvinge en multistatement transaksjon for å foreta commits asynkront når standardverdien til parameteren er motsatt, satt SET LOCAL synchronous_commit TO OFF i en transaksjon.

Med denne lille modifikasjonen av konfigurasjonsfilen ga vi brukerne kontroll over konsistensen og ytelsen deres.

Kilde: www.habr.com

Legg til en kommentar