PostgreSQL e impostazioni di coerenza della scrittura per ogni connessione specifica

La traduzione dell'articolo è stata preparata appositamente per gli studenti del corso «Database». Sei interessato a svilupparti in questo campo? Ti invitiamo a Giornata Port Open, dove parleremo in dettaglio del programma, delle caratteristiche del formato online, delle competenze e delle prospettive di carriera che attendono i laureati dopo il corso.

PostgreSQL e impostazioni di coerenza della scrittura per ogni connessione specifica

PostgreSQL e impostazioni di coerenza della scrittura per ogni connessione specifica
Noi di Compose gestiamo molti database, e questo ci permette di scoprire meglio le loro funzionalità e i loro limiti. Mentre impariamo ad apprezzare le caratteristiche funzionali dei nuovi database, a volte ci scappa di pensare a quanto sarebbe bello se tali funzionalità fossero presenti anche in strumenti più maturi con cui lavoriamo da tempo. Una delle nuove caratteristiche che avremmo voluto vedere in PostgreSQL era la coerenza scritta personalizzabile per connessione all'interno dell'intero cluster. E, come si è scoperto, ce l'abbiamo già, e oggi vogliamo condividere con voi informazioni su come potete utilizzarla.

Perché dovrei interessarmene?

Il modo in cui deve comportarsi un cluster dipende dalla tua applicazione. Prendiamo, ad esempio, un'app per il pagamento delle bollette. Avrai bisogno di una coerenza al 100% nel cluster, quindi dovrai attivare i commit sincroni affinché il tuo database attenda l'applicazione di tutte le modifiche. Tuttavia, se la tua applicazione è un social network in rapida evoluzione, probabilmente preferirai una risposta rapida alla coerenza al 100%. Per raggiungere questo obiettivo, puoi utilizzare nel tuo cluster commit asincroni.

Incontriamo il compromesso

Dovrai scendere a compromessi tra la coerenza dei dati e le prestazioni. PostgreSQL si allontana dalla coerenza, poiché la configurazione predefinita in questo caso risulta prevedibile e priva di sorprese inaspettate. E ora cominciamo a esaminare i compromessi.

Compromesso 1: Prestazioni

Se un cluster PostgreSQL non richiede coerenza, può funzionare in modo asincrono. Le scritture vengono effettuate sul leader del cluster, e le sue repliche riceveranno gli aggiornamenti dopo alcuni millisecondi. Quando il cluster PostgreSQL richiede coerenza, deve funzionare in modo sincrono. La scrittura sarà effettuata sul leader del cluster, che invierà aggiornamenti alle repliche e attenderà conferma che ciascuna di esse abbia eseguito la scrittura, prima di inviare una conferma al cliente che ha iniziato la scrittura, informandolo che è stata completata con successo. La differenza pratica tra questi approcci è che il metodo asincrono richiede due salti di rete, mentre quello sincrono ne richiede quattro.

Compromesso 2: Coerenza

Il risultato in caso di guasto del leader in questi due approcci sarà diverso. Se il lavoro viene eseguito in modo asincrono, quando si verifica un errore del genere, non tutte le registrazioni saranno registrate dalle repliche. Quanto andrà perso? Dipende dall'applicazione stessa e dall'efficacia della replica. La replica di Compose impedirà a una replica di diventare leader se la quantità di informazioni in essa è inferiore di 1 MB rispetto al leader, il che significa che potrebbero potenzialmente andare perse fino a 1 MB di registrazioni durante il funzionamento asincrono.

In modalità sincrona questo non accade. Se il leader fallisce, tutte le repliche vengono aggiornate, poiché ogni registrazione confermata sul leader deve essere confermata nelle repliche. Ecco la coerenza.

Il comportamento sincrono è utile in un'applicazione per il pagamento delle fatture, dove la coerenza è decisamente vantaggiosa per trovare un compromesso tra coerenza e prestazioni. Il dato più importante per tale applicazione è la validità dei dati. Ora pensate ai social network, dove l'obiettivo principale è mantenere l'attenzione degli utenti rispondendo alle loro richieste nel modo più rapido possibile. In questo caso, le prestazioni con un numero ridotto di salti nella rete e tempi di attesa minori per i commit hanno la priorità. Tuttavia, il compromesso tra prestazioni e coerenza non è l'unico a cui prestare attenzione.

Compromesso 3: Guasti

È molto importante comprendere come si comporta un cluster durante un guasto. Consideriamo la situazione in cui una o più repliche falliscono. Quando i commit vengono elaborati in modo asincrono, il leader continuerà a funzionare, ovvero accetterà e elaborerà le registrazioni senza attendere le repliche mancanti. Quando le repliche tornano nel cluster, raggiungono il leader. Con la replica sincrona, se le repliche non rispondono, il leader non avrà scelta e continuerà ad attendere la conferma del commit finché la replica non ritorna nel cluster e non può accettare e confermare la registrazione.

Una connessione per transazione?

Ogni applicazione necessita di un particolare tipo di combinazione tra coerenza e prestazioni. A meno che non si tratti dell'applicazione per il pagamento delle fatture, che immaginiamo essere completamente coerente, o della nostra quasi eterea applicazione per i social network. In tutti gli altri casi, ci saranno momenti in cui alcune operazioni devono essere sincrone e altre asincrone. Potresti non voler che il sistema attenda il completamento del messaggio inviato in chat, ma se in quella stessa applicazione avviene un pagamento, dovrà attendere.

Tutte queste decisioni, naturalmente, spettano allo sviluppatore dell'applicazione. Le scelte corrette su quando applicare un approccio piuttosto che un altro possono aiutare a massimizzare il cluster. È fondamentale che lo sviluppatore possa passare tra di essi a livello di SQL per le connessioni e per le transazioni.

Assicurare il controllo nella pratica

Per impostazione predefinita, PostgreSQL garantisce coerenza. Questo è controllato dal parametro del server synchronous_commit. Di default, è impostato su on, ma ha altre tre opzioni: local, remote_write o off.

Impostando il parametro su off si fermano tutti gli impegni sincronizzati, anche nel sistema locale. Il parametro in local definisce la modalità sincronizzata per il sistema locale, ma le scritture nelle repliche avvengono in modo asincrono. Remote_write va ancora oltre: le scritture nelle repliche vengono eseguite in modo asincrono, ma vengono restituite quando la replica ha accettato la scrittura, ma non l'ha registrata su disco.

Considerando l'ampia gamma di opzioni disponibili, scegliamo il comportamento e, ricordando che on – si tratta di scritture sincronizzate, scegliamo local per gli impegni asincroni sulla rete, mantenendo le scritture locali sincronizzate.

Ora, vi racconteremo come configurarlo in un attimo, ma immaginate di aver impostato synchronous_commit in local per il server. Ci siamo chiesti se fosse possibile modificare il parametro synchronous_commit al volo, ed è emerso che non solo è possibile, ma ci sono ben due modi per farlo. Il primo è impostare la sessione della vostra connessione nel modo seguente:

SET SESSION synchronous_commit TO ON;  
// I vostri scritti vanno qui

Tutte le scritture successive nella sessione confermeranno le operazioni di scrittura per le repliche, prima di restituire un risultato positivo al client connesso. A meno che, ovviamente, non si modifichi nuovamente l'impostazione synchronous_commit di nuovo. Si può omettere la parte SESSION nel team, poiché sarà nel valore predefinito.

Il secondo metodo è utile quando desideri semplicemente assicurarti di ottenere la replica sincrona per una singola transazione. In molti database di tipo "NoSQL" non esiste il concetto di transazione, ma in PostgreSQL esiste. In questo caso avvii una transazione e poi imposti synchronous_commit in on prima di eseguire la scrittura per la transazione. COMMIT registrerà la transazione utilizzando qualunque valore del parametro synchronous_commit, che è stato impostato in quel momento, anche se è meglio impostare la variabile in anticipo per garantire che altri sviluppatori comprendano che le scritture non sono asincrone.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Le tue scritture qui
COMMIT;  

Tutti i commit delle transazioni ora saranno confermati, come scritti nelle repliche prima che il database restituisca una risposta positiva al client connesso.

Configurazione di PostgreSQL

Prima di questo, immaginavamo un sistema PostgreSQL con synchronous_commit, impostato su local. Per rendere ciò reale dal lato del server, sarà necessario impostare due parametri di configurazione del server. Un altro parametro synchronous_standby_names entrerà in gioco quando synchronous_commit sarà in on. Definisce quali repliche hanno il diritto di eseguire commit sincroni, e lo imposteremo a *, che significa attivare tutte le repliche. Questi valori vengono generalmente configurati nel file di configurazione aggiungendo:

synchronous_commit = local  
synchronous_standby_names='*'

Impostando il parametro synchronous_commit su local, creiamo un sistema in cui i dischi locali rimangono sincronici, ma i commit delle repliche di rete sono di default asincroni, a meno che non decidiamo di rendere questi commit sincroni, come mostrato sopra.

Se hai seguito lo sviluppo del progetto Governor, avrai notato alcuni cambiamenti recenti (1, 2) che hanno permesso agli utenti di Governor di testare queste impostazioni e monitorare la loro coerenza.

Un paio di parole…

Letteralmente una settimana fa, ti avrei detto che non era possibile ottimizzare PostgreSQL in modo così dettagliato. Proprio allora Kurt, un membro del team della piattaforma Compose, ha insistito sul fatto che esisteva tale possibilità. Ha messo a tacere le mie obiezioni e ha trovato nella documentazione di PostgreSQL quanto segue:

PostgreSQL e impostazioni di coerenza della scrittura per ogni connessione specifica

Questa impostazione può essere modificata in qualsiasi momento. Il comportamento di una transazione è determinato dalla configurazione attiva al momento del commit. Pertanto, è possibile e utile che per alcune transazioni i commit avvengano in modo sincrono, mentre per altre in modo asincrono. Ad esempio, per consentire a una multistatement transazione di effettuare commit in modo asincrono, quando il valore predefinito è opposto, impostare SET LOCAL synchronous_commit TO OFF nella transazione.

Con questa piccola modifica nel file di configurazione, abbiamo dato agli utenti la possibilità di controllare la loro coerenza e prestazioni.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster