PostgreSQL en verbindingsspecifieke instellingen voor schrijfconsistentie

De vertaling van het artikel is speciaal gemaakt voor de studenten van de cursus "Databank". Interesse om je in deze richting te ontwikkelen? Wij nodigen u uit om Open dag, waar we in detail praten over het programma, kenmerken van het online format, competenties en carrièremogelijkheden die afgestudeerden na de training te wachten staan.

PostgreSQL en verbindingsspecifieke instellingen voor schrijfconsistentie

PostgreSQL en verbindingsspecifieke instellingen voor schrijfconsistentie
Bij Compose hebben we te maken met veel databases, wat ons de mogelijkheid geeft om meer vertrouwd te raken met hun functionaliteit en tekortkomingen. Terwijl we de kenmerken van nieuwe databases leren waarderen, beginnen we soms te bedenken hoe mooi het zou zijn als soortgelijke kenmerken aanwezig zouden zijn in de meer volwassen tools waarmee we al heel lang werken. Een van de nieuwe features die ik in PostgreSQL wilde zien, was de configureerbare schrijfconsistentie per verbinding over het hele cluster. En het blijkt dat we het al hebben, en vandaag willen we informatie met u delen over hoe u het kunt gebruiken.

Waarom heb ik het nodig?

Hoe het cluster zich moet gedragen, is afhankelijk van uw toepassing. Neem bijvoorbeeld een app voor het betalen van rekeningen. U hebt XNUMX% consistentie in het hele cluster nodig, dus u moet synchrone commits inschakelen, zodat uw database wacht totdat alle wijzigingen zijn aangebracht. Als uw applicatie echter een snelgroeiend sociaal netwerk is, geeft u waarschijnlijk de voorkeur aan een snelle respons boven XNUMX% consistentie. Om dit te bereiken, kunt u asynchrone commits in uw cluster gebruiken.

Ontmoet compromissen

U moet een afweging maken tussen gegevensconsistentie en prestaties. PostgreSQL wijkt af van consistentie omdat de standaardconfiguratie dan voorspelbaar is en zonder onverwachte verrassingen. Laten we nu eens kijken naar de compromissen.

Afweging 1: Prestaties

Als het PostgreSQL-cluster geen consistentie vereist, kan het asynchroon worden uitgevoerd. Er wordt naar de clusterleider geschreven en updates worden een paar milliseconden later naar de replica's verzonden. Wanneer een PostgreSQL-cluster consistentie vereist, moet het synchroon draaien. Het schrijven wordt gedaan naar de clusterleider, die een update naar de replica's verzendt en wacht op de bevestiging dat ze allemaal hebben geschreven voordat een bevestiging wordt verzonden naar de client die het schrijven heeft gestart dat het schrijven is gelukt. Het praktische verschil tussen deze benaderingen is dat de asynchrone methode twee netwerkhops vereist, terwijl de synchrone methode er vier vereist.

Afweging 2: consistentie

Het resultaat in het geval dat een leider in deze twee benaderingen faalt, zal ook verschillend zijn. Als het werk asynchroon wordt uitgevoerd en een dergelijke fout optreedt, worden niet alle records vastgelegd door de replica's. Hoeveel zal er verloren gaan? Hangt af van de applicatie zelf en de efficiëntie van replicatie. Compose-replicatie voorkomt dat een replica een leider wordt als de hoeveelheid informatie daarin 1 MB minder is dan in de leider, dat wil zeggen dat maximaal 1 MB aan records verloren kan gaan tijdens asynchrone werking.

Dit gebeurt niet in de synchrone modus. Als de leider faalt, worden alle replica's bijgewerkt, aangezien elk bevestigd schrijven op de leider ook op de replica's moet worden bevestigd. Dit is consistentie.

Synchronisch gedrag is zinvol in een factureringstoepassing waar consistentie een duidelijk voordeel heeft in de afweging tussen consistentie en prestaties. Het allerbelangrijkste voor een dergelijke toepassing zijn geldige gegevens. Denk nu eens aan een sociaal netwerk waarin het de hoofdtaak is om de aandacht van de gebruiker vast te houden door zo snel mogelijk op verzoeken te reageren. In dit geval zullen prestaties met minder netwerk-hops en minder wachten op commits een prioriteit zijn. De afweging tussen prestaties en consistentie is echter niet de enige waar u aan moet denken.

Afweging 3: Crashes

Het is erg belangrijk om te begrijpen hoe een cluster zich gedraagt ​​tijdens een storing. Overweeg een situatie waarin een of meer replica's mislukken. Wanneer commits asynchroon worden verwerkt, blijft de leider functioneren, dat wil zeggen, schrijfbewerkingen accepteren en verwerken, zonder te wachten op ontbrekende replica's. Wanneer de replica's terugkeren naar het cluster, halen ze de leider in. Als de replica's bij synchrone replicatie niet reageren, heeft de leider geen keus en blijft hij wachten op bevestiging van de commit totdat de replica terugkeert naar het cluster en het schrijven kan accepteren en doorvoeren.

Eén verbinding per transactie?

Elke applicatie heeft een ander type combinatie van consistentie en prestaties nodig. Tenzij het natuurlijk onze app is om rekeningen te betalen, waarvan we denken dat deze volledig consistent is, of onze bijna kortstondige app voor sociale netwerken. In alle andere gevallen zullen er momenten zijn waarop sommige bewerkingen synchroon moeten zijn en andere asynchroon. Mogelijk wilt u niet dat het systeem wacht totdat een bericht dat naar de chat is verzonden, is vastgelegd, maar als een betaling in dezelfde applicatie wordt verwerkt, moet u wachten.

Al deze beslissingen worden uiteraard genomen door de applicatie-ontwikkelaar. Door de juiste beslissingen te nemen over wanneer u elke aanpak moet gebruiken, kunt u het meeste uit uw cluster halen. Het is belangrijk dat de ontwikkelaar op SQL-niveau hiertussen kan schakelen voor verbindingen en voor transacties.

Zorgen voor controle in de praktijk

Standaard biedt PostgreSQL consistentie. Dit wordt bepaald door de serverparameter synchronous_commit. Standaard staat deze op zijn plaats on, maar er zijn nog drie andere opties: local, remote_write of off.

Wanneer u de parameter instelt op off alle synchrone commits worden gestopt, zelfs op het lokale systeem. De lokale parameter specificeert de synchrone modus voor het lokale systeem, maar schrijfbewerkingen naar replica's worden asynchroon uitgevoerd. Remote_write gaat zelfs nog verder: schrijfbewerkingen naar replica's worden asynchroon uitgevoerd, maar worden geretourneerd wanneer de replica de schrijfbewerking heeft geaccepteerd, maar deze niet naar schijf heeft geschreven.

Door het beschikbare scala aan opties te overwegen, kiezen we een gedrag en houden we dat in gedachten on – dit zijn synchrone opnames, we zullen kiezen local voor asynchrone commits via het netwerk, terwijl lokale commits synchroon blijven.

Nu zullen we je zo meteen vertellen hoe je dit instelt, maar stel je voor dat we het opzetten synchronous_commit в local voor de server. We vroegen ons af of het mogelijk was om de parameter te wijzigen synchronous_commit on the fly, en het bleek dat het niet alleen mogelijk is, er zijn zelfs twee manieren om dit te doen. De eerste is om de sessie van uw verbinding als volgt in te stellen:

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

Alle volgende schrijfbewerkingen in de sessie bevestigen schrijfbewerkingen naar de replica's voordat een positief resultaat wordt geretourneerd naar de verbonden client. Tenzij je de instelling natuurlijk verandert synchronous_commit opnieuw. Je kunt een deel weglaten SESSION in de opdracht omdat deze de standaardwaarde heeft.

De tweede methode is goed als u er zeker van wilt zijn dat u synchrone replicatie krijgt voor een enkele transactie. In veel NoSQL-generatiedatabases bestaat het concept van transacties niet, maar in PostgreSQL wel. In dit geval start u een transactie en stelt u vervolgens in synchronous_commit в on voordat u de boeking voor de transactie uitvoert. COMMIT zal de transactie uitvoeren met behulp van een willekeurige parameterwaarde synchronous_commit, die destijds werd ingesteld, hoewel het het beste is om de variabele vooraf in te stellen om er zeker van te zijn dat andere ontwikkelaars begrijpen dat schrijfbewerkingen niet asynchroon zijn.

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

Alle transactietoezeggingen worden nu bevestigd als geschreven naar replica's voordat de database een positief antwoord retourneert aan de verbonden client.

PostgreSQL configureren

Voordien stelden we ons een PostgreSQL-systeem voor met synchronous_commit, geïnstalleerd local. Om dit aan de serverzijde realistisch te maken, moet u twee serverconfiguratie-opties instellen. Nog een parameter synchronous_standby_names zal tot zijn recht komen wanneer synchronous_commit zal erin zijn on. Het bepaalt welke replica's in aanmerking komen voor synchrone commits, en wij zullen dit instellen *, wat betekent dat alle replica's erbij betrokken zijn. Deze waarden worden meestal geconfigureerd in configuratiebestand door toe te voegen:

synchronous_commit = local  
synchronous_standby_names='*'

Door de parameter in te stellen synchronous_commit in betekenis local, creëren we een systeem waarbij lokale schijven synchroon blijven, maar netwerkreplica-commits zijn standaard asynchroon. Tenzij we natuurlijk besluiten om deze commits synchroon te maken, zoals hierboven weergegeven.

Als je de ontwikkeling hebt gevolgd Gouverneursproject, heb je misschien enkele recente wijzigingen opgemerkt (1, 2), waardoor Governor-gebruikers deze parameters konden testen en hun consistentie konden controleren.

Nog een paar woorden...

Nog maar een week geleden had ik je verteld dat het onmogelijk is om PostgreSQL zo fijn af te stemmen. Toen benadrukte Kurt, lid van het Compose-platformteam, dat een dergelijke mogelijkheid bestond. Hij kalmeerde mijn bezwaren en vond in de PostgreSQL-documentatie het volgende:

PostgreSQL en verbindingsspecifieke instellingen voor schrijfconsistentie

Deze instelling kan op elk moment worden gewijzigd. Het gedrag van elke transactie wordt bepaald door de instelling die van kracht is op het moment van de commit. Daarom is het voor sommige transacties mogelijk en nuttig om synchroon vast te leggen en voor andere asynchroon. Om er bijvoorbeeld eentje te forceren multistatement transactie om asynchroon commits te maken wanneer de standaardwaarde van de parameter het tegenovergestelde is, ingesteld SET LOCAL synchronous_commit TO OFF bij een transactie.

Met deze kleine wijziging aan het configuratiebestand gaven we gebruikers controle over hun consistentie en prestaties.

Bron: www.habr.com

Voeg een reactie