PostgreSQL och anslutningsspecifika skrivkonsistensinställningar

Översättningen av artikeln förbereddes speciellt för kursens studenter "Databas". Intresserad av att utvecklas i denna riktning? Vi inbjuder dig till Öppen dag, där vi pratar i detalj om programmet, funktioner i onlineformatet, kompetenser och karriärmöjligheter som väntar akademiker efter utbildningen.

PostgreSQL och anslutningsspecifika skrivkonsistensinställningar

PostgreSQL och anslutningsspecifika skrivkonsistensinställningar
På Compose arbetar vi med många databaser, vilket ger oss möjlighet att bli mer bekanta med deras funktionalitet och brister. När vi lär oss att älska funktionerna i nya databaser börjar vi ibland tänka på hur trevligt det skulle vara om liknande funktioner fanns i de mer mogna verktygen vi har arbetat med länge. En av de nya funktionerna som jag ville se i PostgreSQL var konfigurerbar skrivkonsistens per anslutning över hela klustret. Och som det visar sig har vi det redan, och idag vill vi dela med dig av information om hur du kan använda det.

Varför behöver jag det?

Hur klustret ska bete sig beror på din applikation. Ta till exempel en app för betalning av räkningar. Du kommer att behöva XNUMX % konsistens över hela klustret, så du måste aktivera synkrona commits så att din databas väntar på att alla ändringar ska göras. Men om din ansökan är ett snabbt växande socialt nätverk, kommer du förmodligen att föredra snabb respons över XNUMX % konsistens. För att uppnå detta kan du använda asynkrona commits i ditt kluster.

Möt kompromisser

Du måste göra avvägningar mellan datakonsistens och prestanda. PostgreSQL går bort från konsekvens eftersom standardkonfigurationen då är förutsägbar och utan oväntade överraskningar. Låt oss nu titta på kompromisserna.

Avvägning 1: Prestanda

Om PostgreSQL-klustret inte kräver konsistens kan det köras asynkront. Skrivningen görs till klusterledaren och uppdateringar kommer att skickas till dess repliker några millisekunder senare. När ett PostgreSQL-kluster kräver konsistens måste det köras synkront. Skrivningen kommer att göras till klusterledaren, som skickar en uppdatering till replikerna och väntar på bekräftelse på att var och en har skrivit innan bekräftelse skickas till klienten som initierade skrivningen om att den lyckades. Den praktiska skillnaden mellan dessa tillvägagångssätt är att den asynkrona metoden kräver två nätverkshopp, medan den synkrona metoden kräver fyra.

Avvägning 2: Konsistens

Resultatet i händelse av ett ledarmisslyckande i dessa två tillvägagångssätt blir också olika. Om arbetet utförs asynkront, om ett sådant fel inträffar, kommer inte alla poster att begås av replikerna. Hur mycket kommer att gå förlorat? Beror på själva applikationen och effektiviteten av replikeringen. Compose-replikering förhindrar en replik från att bli en ledare om mängden information i den är 1 MB mindre än i ledaren, det vill säga upp till 1 MB poster kan potentiellt gå förlorade under asynkron drift.

Detta händer inte i synkront läge. Om ledaren misslyckas uppdateras alla repliker, eftersom alla skrivningar som bekräftas på ledaren måste bekräftas på replikerna. Detta är konsekvens.

Synkront beteende är vettigt i en faktureringsapplikation där konsekvens har en klar fördel i avvägningen mellan konsekvens och prestanda. Det viktigaste för en sådan applikation är giltig data. Tänk nu på ett socialt nätverk där huvuduppgiften är att hålla användarens uppmärksamhet genom att svara på förfrågningar så snabbt som möjligt. I det här fallet kommer prestanda med färre nätverkshopp och mindre väntan på commits att vara en prioritet. Avvägningen mellan prestanda och konsekvens är dock inte den enda du måste tänka på.

Avvägning 3: Kraschar

Det är mycket viktigt att förstå hur ett kluster beter sig under ett misslyckande. Tänk på en situation där en eller flera repliker misslyckas. När commits behandlas asynkront kommer ledaren att fortsätta att fungera, det vill säga acceptera och bearbeta skrivningar, utan att vänta på saknade repliker. När replikerna återvänder till klustret kommer de ikapp ledaren. Med synkron replikering, om replikerna inte svarar, kommer ledaren inte att ha något val och kommer att fortsätta att vänta på commit-bekräftelse tills repliken återvänder till klustret och kan acceptera och commit skrivningen.

En anslutning per transaktion?

Varje applikation behöver en annan typ av kombination av konsistens och prestanda. Såvida det inte är vår app för betalning av räkningar, som vi föreställer oss vara helt konsekvent, eller vår nästan tillfälliga app för sociala nätverk. I alla andra fall kommer det att finnas tillfällen då vissa operationer måste vara synkrona och vissa måste vara asynkrona. Du kanske inte vill att systemet ska vänta tills ett meddelande som skickas till chatten har begåtts, men om en betalning behandlas i samma applikation måste du vänta.

Alla dessa beslut fattas naturligtvis av applikationsutvecklaren. Att fatta rätt beslut om när du ska använda varje tillvägagångssätt hjälper dig att få ut det mesta av ditt kluster. Det är viktigt att utvecklaren kan växla mellan dem på SQL-nivå för anslutningar och för transaktioner.

Säkerställa kontroll i praktiken

Som standard ger PostgreSQL konsistens. Detta styrs av serverparametern synchronous_commit. Som standard är den i position on, men den har tre andra alternativ: local, remote_write eller off.

När du ställer in parametern till off alla synkrona commits stoppas, även på det lokala systemet. Den lokala parametern anger synkront läge för det lokala systemet, men skrivningar till repliker utförs asynkront. Remote_write går ännu längre: skrivningar till repliker görs asynkront, men returneras när repliken har accepterat skrivningen men inte skrivit den till disk.

Genom att överväga det tillgängliga utbudet av alternativ väljer vi ett beteende och med tanke på det on – det här är synkrona inspelningar, vi väljer local för asynkrona commits över nätverket, medan lokala commits lämnas synkrona.

Nu ska vi berätta hur du ställer in det här på ett ögonblick, men föreställ dig att vi ställer in det synchronous_commit в local för servern. Vi undrade om det var möjligt att ändra parametern synchronous_commit i farten, och det visade sig att det inte bara är möjligt, det finns till och med två sätt att göra detta. Det första är att ställa in sessionen för din anslutning enligt följande:

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

Alla efterföljande skrivningar i sessionen kommer att bekräfta skrivningar till replikerna innan ett positivt resultat returneras till den anslutna klienten. Såvida du inte ändrar inställningen synchronous_commit igen. Du kan utelämna en del SESSION i kommandot eftersom det kommer att vara i standardvärdet.

Den andra metoden är bra när du bara vill se till att du får synkron replikering för en enda transaktion. I många NoSQL-genereringsdatabaser existerar inte konceptet med transaktioner, men det gör det i PostgreSQL. I det här fallet startar du en transaktion och ställer sedan in synchronous_commit в on innan transaktionen genomförs. COMMIT kommer att utföra transaktionen med valfritt parametervärde synchronous_commit, som sattes vid den tiden, även om det är bäst att ställa in variabeln i förväg för att se till att andra utvecklare förstår att skrivningar inte är asynkrona.

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

Alla transaktionsbekräftelser kommer nu att bekräftas som skrivna till repliker innan databasen returnerar ett positivt svar till den anslutna klienten.

Konfigurera PostgreSQL

Innan detta föreställde vi oss ett PostgreSQL-system med synchronous_commit, installerad i local. För att göra detta realistiskt på serversidan måste du ställa in två serverkonfigurationsalternativ. Ytterligare en parameter synchronous_standby_names kommer till sin rätt när synchronous_commit kommer att vara med on. Det avgör vilka repliker som är kvalificerade för synkrona commits, och vi kommer att ställa in det på *, vilket kommer att innebära att alla repliker är inblandade. Dessa värden är vanligtvis konfigurerade i konfigurationsfil genom att lägga till:

synchronous_commit = local  
synchronous_standby_names='*'

Genom att ställa in parametern synchronous_commit till mening local, skapar vi ett system där lokala diskar förblir synkrona, men nätverksreplika commits är asynkrona som standard. Såvida vi inte bestämmer oss för att göra dessa commits synkrona, som visas ovan.

Om du har följt utvecklingen Guvernörsprojekt, du kanske har märkt några senaste ändringar (1, 2), vilket gjorde det möjligt för Governor-användare att testa dessa parametrar och övervaka deras konsistens.

Några fler ord...

För bara en vecka sedan skulle jag ha sagt att det är omöjligt att finjustera PostgreSQL så fint. Det var då Kurt, en medlem av Compose-plattformsteamet, insisterade på att en sådan möjlighet fanns. Han lugnade mina invändningar och hittade i PostgreSQL-dokumentationen följande:

PostgreSQL och anslutningsspecifika skrivkonsistensinställningar

Denna inställning kan ändras när som helst. Beteendet för alla transaktioner bestäms av den inställning som gäller vid tidpunkten för bekräftelsen. Därför är det möjligt och användbart för vissa transaktioner att utföra synkront och för andra asynkront. Till exempel att tvinga en multistatement transaktion att göra commits asynkront när standardvärdet för parametern är motsatt, set SET LOCAL synchronous_commit TO OFF i en transaktion.

Med denna lilla modifiering av konfigurationsfilen gav vi användarna kontroll över deras konsistens och prestanda.

Källa: will.com

Lägg en kommentar