PostgreSQL e impostazioni di coerenza della scrittura per ciascuna connessione specifica

Traduzione dell'articolo preparata appositamente per gli studenti del corso «Basi di Dati». Ti interessa svilupparti in questo campo? Ti invitiamo a Giornata di Porte Aperte, dove parleremo dettagliatamente 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 ciascuna connessione specifica

PostgreSQL e impostazioni di coerenza della scrittura per ciascuna connessione specifica
Noi di Compose abbiamo a che fare con molte basi di dati, e proprio questo ci dà l'opportunità di approfondire la loro funzionalità e i loro limiti. Man mano che impariamo ad apprezzare le caratteristiche funzionali delle nuove basi di dati, a volte iniziamo a pensare a come sarebbe bello se tali funzioni fossero presenti anche negli strumenti più maturi con cui lavoriamo da tempo. Una delle nuove funzionalità che avremmo voluto vedere in PostgreSQL era la coerenza scritturale configurabile per connessione in tutto il cluster. E, a quanto pare, ce l'abbiamo già, e oggi vogliamo condividere con te informazioni su come puoi utilizzarla.

A cosa mi serve?

Il modo in cui deve comportarsi un cluster dipende dalla tua applicazione. Prendiamo, ad esempio, un'applicazione per il pagamento delle bollette. Avrai bisogno di coerenza totale nel cluster, quindi dovrai abilitare i commit sincronizzati 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 rispetto alla coerenza totale. Per raggiungere questo obiettivo, puoi utilizzare nel tuo cluster commit asincroni.

Ecco il compromesso

Dovrai scendere a compromessi tra la coerenza dei dati e le prestazioni. PostgreSQL tende verso la coerenza, poiché la configurazione predefinita risulta così prevedibile, senza sorprese inaspettate. E ora iniziamo a esplorare questi compromessi.

Compromesso 1: Prestazioni

Se al cluster PostgreSQL non è richiesta coerenza, può tranquillamente operare in modo asincrono. La scrittura avviene sul leader del cluster e le sue repliche riceveranno gli aggiornamenti dopo alcuni millisecondi. Quando al cluster PostgreSQL è richiesta coerenza, deve operare in modo sincrono. La scrittura sarà eseguita sul leader del cluster, che invierà l'aggiornamento alle repliche e attenderà una conferma che ognuna di esse ha registrato l'operazione, prima di inviare la conferma al cliente che ha avviato la scrittura, informandolo che l'operazione è andata a buon fine. La differenza pratica tra questi approcci è che il metodo asincrono richiede due salti di rete, mentre il sincrono ne richiede quattro.

Compromesso 2: Coerenza

Il risultato in caso di guasto del leader in questi due approcci sarà diverso. Se l'operazione è eseguita in modo asincrono, in caso di errore, non tutte le scritture saranno registrate dalle repliche. Quanto sarà perso? Dipende dall'applicazione stessa e dall'efficacia della replicazione. La replicazione di Compose impedirà alla replica di diventare leader nel caso in cui la quantità di informazioni in essa sia inferiore di 1 MB rispetto al leader, il che significa che potrebbero andare perse fino a 1 MB di scritture durante l'operatività asincrona.

In modalità sincrona questo non accade. Se il leader fallisce, tutte le repliche vengono aggiornate, poiché ogni scrittura confermata dal leader deve essere confermata anche nelle repliche. Ecco qua: coerenza.

Il comportamento sincrono ha senso utilizzarlo in un'applicazione per la gestione dei pagamenti, dove la coerenza ha un chiaro vantaggio nel cercare un compromesso tra coerenza e prestazioni. La cosa più importante per un'applicazione di questo tipo sono i dati validi. Ora, pensate a un social network, dove l'obiettivo principale è mantenere l'attenzione dell'utente, rispondendo alle richieste il più rapidamente possibile. In tal caso, le prestazioni con un numero inferiore di salti di rete e un'attesa minore per i commit avranno la priorità. Tuttavia, il compromesso tra prestazioni e coerenza non è l'unico di cui tenere conto.

Compromesso 3: Guasti

È molto importante capire come si comporta un cluster durante un guasto. Consideriamo la situazione in cui una o più repliche si guastano. Quando i commit vengono elaborati in modo asincrono, il leader continua a funzionare, cioè accetta ed elabora le scritture senza aspettare le repliche mancanti. Quando le repliche tornano nel cluster, raggiungono il leader. Con la replicazione sincronizzata, se le repliche non rispondono, il leader non avrà scelta e continuerà a aspettare la conferma del commit finché la replica non tornerà nel cluster e non potrà accettare e confermare la scrittura.

Una connessione per transazione?

Ogni applicazione ha bisogno di un tipo speciale di combinazione tra coerenza e prestazioni. A meno che non si tratti ovviamente della nostra applicazione per il pagamento delle fatture, che immaginiamo essere completamente coerente, o della nostra applicazione per social network quasi effimera. In tutti gli altri casi ci saranno momenti in cui alcune operazioni devono essere sincronizzate e altre asincrone. Potresti non volere che il sistema aspetti che un messaggio inviato in chat venga confermato, ma se in quella stessa applicazione avviene un pagamento, allora dovrai aspettare.

Tutte queste decisioni, ovviamente, ricadono sullo sviluppatore dell'applicazione. Le giuste decisioni su quando applicare un approccio piuttosto che un altro aiuteranno a ottenere il massimo dal cluster. È importante che lo sviluppatore possa alternare tra di essi a livello di SQL per le connessioni e per le transazioni.

Garantire il controllo nella pratica

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

Se il parametro è impostato su off , tutti i commit sincronizzati vengono interrotti, anche nella sistema locale. Il parametro in local definisce la modalità sincronizzata per il sistema locale, ma le scritture sulle repliche avvengono in modo asincrono. Remote_write va ancora oltre: le scritture sulle repliche avvengono in modo asincrono, ma vengono restituite quando la replica ha accettato la scrittura, ma non l'ha ancora registrata su disco.

Considerando l'attuale gamma di opzioni, scegliamo il comportamento e, tenendo presente che on – sono scritture sincrone, sceglieremo local per i commit asincroni sulla rete, lasciando i commit locali sincronizzati.

Ora vi spiegheremo come configurarlo in un attimo, ma immaginate che abbiamo installato synchronous_commit in local per il server. Ci siamo chiesti se fosse possibile modificare il parametro synchronous_commit al volo, e si è scoperto che non solo è possibile, ma ci sono addirittura due modi per farlo. Il primo è impostare la sessione della vostra connessione nel seguente modo:

SET SESSION synchronous_commit TO ON;  
// Le vostre scritture 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, naturalmente, non cambiate di nuovo l'impostazione. synchronous_commit È possibile omettere la parte SESSION nel comando, poiché sarà impostata sul valore predefinito.

Il secondo metodo è utile quando si desidera assicurarsi di ottenere una replica sincrona per una transazione. In molti database di generazione "NoSQL" non esiste il concetto di transazione, ma esiste in PostgreSQL. In questo caso eseguite una transazione e poi impostate synchronous_commit in on prima di eseguire la scrittura per la transazione. COMMIT confermerà la transazione, utilizzando qualsiasi valore del parametro synchronous_commit, che è stato impostato in quel momento, anche se è meglio impostare la variabile in anticipo, in modo che gli altri sviluppatori comprendano che le scritture non sono asincrone.

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

Ora tutti i commit delle transazioni saranno confermati, come scritti nelle repliche, ancor 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. Affinché questo sia reale sul lato 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. Esso definisce quali repliche hanno diritto a commit sincroni, e lo imposteremo su *, il che significherà coinvolgere tutte le repliche. Questi valori vengono generalmente configurati in file di configurazione aggiungendo:

synchronous_commit = local  
synchronous_standby_names='*'

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

Se avete seguito l'evoluzione del progetto Governor, potreste aver notato alcuni cambiamenti recenti (1, 2), che hanno permesso agli utenti di Governor di testare queste impostazioni e di controllarne la coerenza.

Altre due parole…

Letteralmente una settimana fa, ti avrei detto che era impossibile ottimizzare così finemente PostgreSQL. È stato allora che Kurt, un membro del team della piattaforma Compose, ha insistito sul fatto che esisteva questa possibilità. Ha placato le mie obiezioni e ha trovato nella documentazione di PostgreSQL quanto segue:

PostgreSQL e impostazioni di coerenza della scrittura per ciascuna connessione specifica

Questo parametro può essere modificato in qualsiasi momento. Il comportamento di ogni transazione è determinato dall'impostazione 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 costringere una multistatement transazione a eseguire commit in modo asincrono, quando il valore predefinito è l'opposto, impostare SET LOCAL synchronous_commit TO OFF nella transazione.

Con una piccola modifica al 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