PostgreSQL en de instellingen voor de consistentie van schrijfacties voor elke specifieke verbinding

De vertaling van het artikel is speciaal voorbereid voor studenten van de cursus Databases. Wil je je in deze richting ontwikkelen? We nodigen je uit voor de Open Dag, waar we uitgebreid uitleggen over het programma, de kenmerken van het online formaat, de vaardigheden en carrièremogelijkheden die afgestudeerden na de opleiding te wachten staan.

PostgreSQL en de instellingen voor de consistentie van schrijfacties voor elke specifieke verbinding

PostgreSQL en de instellingen voor de consistentie van schrijfacties voor elke specifieke verbinding
Bij Compose hebben we te maken met veel databases, wat ons de kans geeft om beter kennis te maken met hun functionaliteit en tekortkomingen. Terwijl we leren de functionele kenmerken van nieuwe databases te waarderen, denken we soms na over hoe prettig het zou zijn als dergelijke functies ook aanwezig waren in de meer volwassen tools waarmee we al lange tijd werken. Een van de nieuwe functies die we in PostgreSQL wilden zien, was instelbare consistentie van schrijfoperaties per verbinding in het hele cluster. En het blijkt dat we die al hebben, en vandaag willen we je vertellen hoe je deze kunt gebruiken.

Waarom heb ik dit nodig?

De manier waarop het cluster zich gedraagt, hangt af van je applicatie. Neem bijvoorbeeld een applicatie voor het betalen van rekeningen. Je hebt honderd procent consistentie in het cluster nodig, dus moet je synchronisatiecommits inschakelen, zodat je database wacht totdat alle wijzigingen zijn doorgevoerd. Maar als je applicatie een snelgroeiend sociaal netwerk is, geef je waarschijnlijk de voorkeur aan een snelle respons boven honderd procent consistentie. Om dit te bereiken, kun je asynchrone commits in je cluster gebruiken.

Maak kennis met de compromis

Je moet een compromis sluiten tussen dataconsistentie en prestatie. PostgreSQL verschuift van consistentie, aangezien de standaardconfiguratie in dit geval voorspelbaar en zonder onverwachte verrassingen is. Laten we nu de compromissen verkennen.

Compromis 1: Prestatie

Als een PostgreSQL-cluster geen consistentie vereist, kan het vrij goed asynchroon werken. Schrijven gebeurt op de leider van het cluster, en zijn replica's ontvangen na enkele milliseconden de updates. Wanneer een PostgreSQL-cluster consistentie vereist, moet het synchroon werken. Het schrijven gebeurt op de clusterleider, die de updates naar de replica's verstuurt en wacht op bevestiging dat elke replica de opname heeft gedaan voordat de leider een bevestiging naar de cliënt stuurt die de opname heeft geïnitieerd, dat deze succesvol was. Het praktische verschil tussen deze benaderingen is dat de asynchrone methode twee netwerkhops vereist, terwijl de synchrone vier vereist.

Compromis 2: Consistentie

Het resultaat in het geval van een falen van de leider in deze twee benaderingen zal ook verschillend zijn. Als de verwerking asynchroon is, zullen niet alle opnames door de replica's zijn bevestigd bij het optreden van een dergelijke fout. Hoeveel gaat er verloren? Dit hangt af van de applicatie zelf en de efficiëntie van de replicatie. De Compose-replicatie voorkomt dat een replica leider wordt als de hoeveelheid informatie daarin 1 MB minder is dan die van de leider, wat betekent dat er potentieel tot 1 MB aan opnames verloren kan gaan bij asynchroon werken.

In de synchrone modus gebeurt dit niet. Als de leider faalt, worden alle replica's bijgewerkt, omdat elke opname die op de leider is bevestigd, ook in de replica's moet worden bevestigd. Dat is consistentie.

Synchrone werking is zinvol in een applicatie voor factuurbetalingen, waar consistentie een duidelijk voordeel heeft bij het zoeken naar een compromis tussen consistentie en prestaties. Het belangrijkste voor zo'n applicatie zijn geldige gegevens. En denk nu aan een sociaal netwerk waar de belangrijkste taak is om de aandacht van de gebruiker vast te houden door aanvragen zo snel mogelijk te beantwoorden. In dat geval hebben prestaties met minder netwerk-hops en minder wachttijd voor bevestigingen prioriteit. Maar het compromis tussen prestaties en consistentie is niet de enige waarover moet worden nagedacht.

Compromis 3: Falen

Het is belangrijk om te begrijpen hoe een cluster zich gedraagt tijdens een storing. Laten we de situatie bekijken waarin één of meer replicas falen. Wanneer commits asynchroon worden verwerkt, blijft de leader functioneren, dat wil zeggen, hij blijft records accepteren en verwerken zonder te wachten op ontbrekende replicas. Wanneer de replicas terugkeren naar het cluster, halen ze de leader in. Bij synchronisatie van replicas, als de replicas niet reageren, heeft de leader geen keuze en blijft hij wachten op bevestiging van de commit totdat de replica terugkeert naar het cluster en de record kan accepteren en bevestigen.

Eén verbinding per transactie?

Elk applicatie heeft een specifieke combinatie van consistentie en prestaties nodig. Tenzij het natuurlijk onze factureringsapplicatie is, die we volledig consistent voorstellen, of onze bijna ongrijpbare sociale media-app. In alle andere gevallen zullen er momenten zijn waarop sommige operaties synchroon moeten zijn en sommige asynchroon. Je wilt misschien niet dat het systeem wacht totdat een bericht dat in de chat is verzonden is gecommit, maar als er in dezelfde applicatie een betaling plaatsvindt, moet je wel wachten.

Al deze beslissingen worden uiteraard door de applicatieontwikkelaar genomen. De juiste keuzes over wanneer welke aanpak toe te passen helpen om het meeste uit het cluster te halen. Het is belangrijk dat de ontwikkelaar kan schakelen tussen deze op het SQL-niveau voor verbindingen en voor transacties.

Het waarborgen van controle in de praktijk

Standaard zorgt PostgreSQL voor consistentie. Dit wordt gecontroleerd door de serverparameter synchronous_commit. Standaard staat deze op on, maar er zijn drie andere opties: local, remote_write of off.

Wanneer de parameter wordt ingesteld op off worden alle synchrone commits gestopt, zelfs in het lokale systeem. De parameter in local definieert de synchrone modus voor het lokale systeem, maar de records naar de replicas worden asynchroon uitgevoerd. Remote_write gaat nog verder: records naar de replicas worden asynchroon verzonden, maar worden teruggestuurd wanneer de replica de record heeft geaccepteerd, maar deze nog niet op schijf heeft geschreven.

Bij het overwegen van de beschikbare opties, kiezen we het gedrag en, ons herinnerend dat on – dit zijn synchrone records, kiezen we local voor asynchrone commits over het netwerk, terwijl we lokale commits synchroon laten.

Nu zullen we je vertellen hoe je dit in een oogwenk kunt instellen, maar stel je voor dat we synchronous_commit in local voor de server hebben geïnstalleerd. We vroegen ons af of we de parameter synchronous_commit on-the-fly konden wijzigen, en het bleek dat dit niet alleen mogelijk is, er zijn zelfs twee manieren om dit te doen. De eerste is om de sessie van je verbinding als volgt in te stellen:

SET SESSION synchronous_commit TO ON;  
// Je schijft hier

Alle daaropvolgende schrijfbewerkingen in de sessie zullen de schrijfoperaties voor de replicaties bevestigen voordat ze een positieve return aan de aangesloten client geven. Tenzij je natuurlijk de instelling synchronous_commit opnieuw wijzigt. Je kunt het deel SESSION in de opdracht weglaten, aangezien deze op de standaardwaarde zal staan.

De tweede methode is handig wanneer je gewoon wilt zorgen dat je synchrone replicatie voor één transactie krijgt. In veel 'NoSQL'-databases bestaat het concept van transacties niet, maar bij PostgreSQL is het er wel. In dit geval start je een transactie en stel je synchronous_commit in on in voordat je een schrijfoperatie voor de transactie uitvoert. COMMIT zal de transactie vastleggen, met welk waardeparameter synchronous_commit, dat op dat moment is ingesteld, hoewel het beter is om de variabele van tevoren in te stellen, zodat andere ontwikkelaars begrijpen dat de schrijfbewerkingen niet asynchroon zijn.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Je schijft hier
COMMIT;  

Alle commits van transacties zullen nu worden bevestigd als geschreven naar de replicaties nog voordat de database een positieve reactie aan de aangesloten client teruggeeft.

Configuratie van PostgreSQL

Daarvoor hebben we ons een PostgreSQL-systeem voorgesteld met synchronous_commit, ingesteld op local. Om dit realistisch te maken aan de serverzijde, moet je twee serverconfiguratieparameters instellen. Een andere parameter synchronous_standby_names zal van kracht worden wanneer synchronous_commit in on. Het definieert welke replicaties recht hebben op synchroniseerde commits, en we zullen het instellen op *, wat betekent dat alle replicaties betrokken worden. Deze waarden worden meestal ingesteld in het configuratiebestand door toe te voegen:

synchronous_commit = local  
synchronous_standby_names='*'

Door de parameter in te stellen op synchronous_commit op de waarde van local, creëren we een systeem waarin lokale schijven synchron zijn, maar de commits van netwerkreplicaties standaard asynchroon zijn. Tenzij we natuurlijk besluiten om deze commits synchron te maken, zoals hierboven aangegeven.

Als je de ontwikkeling van project Governor hebt gevolgd, u hebt misschien enkele recente wijzigingen opgemerkt (1, 2), die gebruikers in staat stelden om deze parameters te testen en hun consistentie te controleren.

Nog een paar woorden…

Letterlijk een week geleden zou ik u hebben verteld dat het onmogelijk is om PostgreSQL zo fijn te tunen. Precies toen drong Kurt, lid van het Compose-platformteam, erop aan dat deze mogelijkheid er wel is. Hij kalmeerde mijn bezwaren en vond in de PostgreSQL-documentatie het volgende:

PostgreSQL en de instellingen voor de consistentie van schrijfacties voor elke specifieke verbinding

Deze parameter kan op elk moment worden gewijzigd. Het gedrag van een transactie wordt bepaald door de instelling die van kracht is bij het committen. Daarom kan het nuttig zijn dat voor sommige transacties commits synchroon plaatsvinden, terwijl voor andere dit asynchroon gebeurd. Bijvoorbeeld om één multistatement transactie asynchroon commits te laten uitvoeren, wanneer de standaardparameter het tegenovergestelde is, stelt u SET LOCAL synchronous_commit TO OFF in de transactie.

Met zo'n kleine aanpassing in het configuratiebestand hebben we gebruikers de mogelijkheid gegeven om hun consistentie en prestaties te controleren.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster