Impostazioni di coerenza di scrittura PostgreSQL e specifiche della connessione

La traduzione dell'articolo è stata preparata appositamente per gli studenti del corso "Banca dati". Sei interessato a svilupparti in questa direzione? Ti invitiamo a Giornata porte aperte, dove si parla nel dettaglio del programma, delle caratteristiche del format online, delle competenze e delle prospettive di carriera che attendono i laureati dopo la formazione.

Impostazioni di coerenza di scrittura PostgreSQL e specifiche della connessione

Impostazioni di coerenza di scrittura PostgreSQL e specifiche della connessione
In Compose ci occupiamo di molti database, il che ci dà l'opportunità di acquisire maggiore familiarità con le loro funzionalità e carenze. Man mano che impariamo ad amare le funzionalità dei nuovi database, a volte iniziamo a pensare a quanto sarebbe bello se funzionalità simili fossero presenti negli strumenti più maturi con cui lavoriamo da molto tempo. Una delle nuove funzionalità che volevo vedere in PostgreSQL era la coerenza di scrittura configurabile per connessione nell'intero cluster. E a quanto pare ce l'abbiamo già e oggi vogliamo condividere con te le informazioni su come puoi usarlo.

Perché ne ho bisogno?

Il modo in cui dovrebbe comportarsi il cluster dipende dall'applicazione. Prendiamo ad esempio un’app per il pagamento delle fatture. Avrai bisogno di una coerenza del XNUMX% in tutto il cluster, quindi dovrai abilitare i commit sincroni in modo che il tuo database attenda che vengano apportate tutte le modifiche. Tuttavia, se la tua applicazione è un social network in rapida crescita, probabilmente preferirai una risposta rapida piuttosto che una coerenza del XNUMX%. Per raggiungere questo obiettivo, puoi utilizzare commit asincroni nel tuo cluster.

Incontra il compromesso

È necessario trovare un compromesso tra coerenza dei dati e prestazioni. PostgreSQL si allontana dalla coerenza perché la configurazione predefinita è quindi prevedibile e senza sorprese inaspettate. Ora diamo un'occhiata ai compromessi.

Compromesso 1: prestazioni

Se il cluster PostgreSQL non richiede coerenza, può essere eseguito in modo asincrono. La scrittura viene effettuata al leader del cluster e gli aggiornamenti verranno inviati alle sue repliche pochi millisecondi dopo. Quando un cluster PostgreSQL richiede coerenza, deve essere eseguito in modo sincrono. La scrittura verrà effettuata al leader del cluster, che invierà un aggiornamento alle repliche e attenderà la conferma che ciascuna abbia scritto prima di inviare conferma al client che ha avviato la scrittura che è andata a buon fine. La differenza pratica tra questi approcci è che il metodo asincrono richiede due hop di rete, mentre il metodo sincrono ne richiede quattro.

Compromesso 2: Coerenza

Anche il risultato in caso di fallimento del leader in questi due approcci sarà diverso. Se il lavoro viene eseguito in modo asincrono, se si verifica un errore di questo tipo, non tutti i record verranno salvati dalle repliche. Quanto andrà perso? Dipende dall'applicazione stessa e dall'efficienza della replica. La replica di composizione impedirà a una replica di diventare leader se la quantità di informazioni in essa contenuta è inferiore di 1 MB rispetto a quella del leader, ovvero fino a 1 MB di record potrebbe andare perso durante l'operazione asincrona.

Ciò non avviene in modalità sincrona. Se il leader fallisce, tutte le repliche vengono aggiornate, poiché qualsiasi scrittura confermata sul leader deve essere confermata sulle repliche. Questa è coerenza.

Il comportamento sincrono ha senso in un'applicazione di fatturazione in cui la coerenza presenta un chiaro vantaggio nel compromesso tra coerenza e prestazioni. La cosa più importante per tale applicazione sono i dati validi. Pensiamo ora ad un social network in cui il compito principale è mantenere l’attenzione dell’utente rispondendo alle richieste il più rapidamente possibile. In questo caso, la priorità sarà data alle prestazioni con meno passaggi di rete e meno attese per i commit. Tuttavia, il compromesso tra prestazioni e coerenza non è l’unico a cui devi pensare.

Compromesso 3: crash

È molto importante capire come si comporta un cluster durante un guasto. Considera una situazione in cui una o più repliche falliscono. Quando i commit vengono elaborati in modo asincrono, il leader continuerà a funzionare, ovvero ad accettare ed elaborare le scritture, senza attendere le repliche mancanti. Quando le repliche ritornano 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 può accettare ed eseguire il commit della scrittura.

Una connessione per transazione?

Ogni applicazione necessita di un diverso tipo di combinazione di coerenza e prestazioni. A meno che, ovviamente, non si tratti della nostra app per il pagamento delle bollette, che immaginiamo essere del tutto coerente, o della nostra quasi effimera app di social networking. In tutti gli altri casi, ci saranno momenti in cui alcune operazioni dovranno essere sincrone e altre asincrone. Potresti non volere che il sistema aspetti finché un messaggio inviato alla chat non viene confermato, ma se un pagamento viene elaborato nella stessa applicazione, dovrai attendere.

Tutte queste decisioni, ovviamente, vengono prese dallo sviluppatore dell'applicazione. Prendere le giuste decisioni su quando utilizzare ciascun approccio ti aiuterà a ottenere il massimo dal tuo cluster. È importante che lo sviluppatore possa passare dall'uno all'altro a livello SQL per le connessioni e per le transazioni.

Garantire il controllo nella pratica

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

Quando si imposta il parametro su off tutti i commit sincroni vengono interrotti, anche sul sistema locale. Il parametro local specifica la modalità sincrona per il sistema locale, ma le scritture sulle repliche vengono eseguite in modo asincrono. Remote_write va ancora oltre: le scritture sulle repliche vengono effettuate in modo asincrono, ma vengono restituite quando la replica ha accettato la scrittura ma non l'ha scritta su disco.

Considerando la gamma di opzioni disponibili, scegliamo un comportamento e, tenendolo presente on – queste sono registrazioni sincrone, sceglieremo local per commit asincroni sulla rete, lasciando sincroni i commit locali.

Ora ti diremo come configurarlo tra un momento, ma immagina di configurarlo synchronous_commit в 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 anche due modi per farlo. Il primo è impostare la sessione della tua connessione come segue:

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

Tutte le scritture successive nella sessione confermeranno le scritture sulle repliche prima di restituire un risultato positivo al client connesso. A meno che, ovviamente, non cambi l'impostazione synchronous_commit Ancora. Puoi omettere una parte SESSION nel comando perché sarà nel valore predefinito.

Il secondo metodo è utile quando vuoi solo assicurarti di ottenere la replica sincrona per una singola transazione. In molti database di generazione NoSQL il concetto di transazioni non esiste, ma esiste in PostgreSQL. In questo caso si avvia una transazione e poi si imposta synchronous_commit в on prima di eseguire l'inserimento della transazione. COMMIT impegnerà la transazione utilizzando qualsiasi valore di parametro synchronous_commit, che era impostato in quel momento, anche se è meglio impostare la variabile in anticipo per assicurarsi che gli altri sviluppatori comprendano che le scritture non sono asincrone.

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

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

Configurazione di PostgreSQL

Prima di questo, abbiamo immaginato un sistema PostgreSQL con synchronous_commit, installato in local. Per rendere questo realistico sul lato server, dovrai impostare due opzioni di configurazione del server. Un altro parametro synchronous_standby_names entrerà in funzione quando synchronous_commit sarà dentro on. Determina quali repliche sono idonee per i commit sincroni e lo imposteremo su *, il che significa che tutte le repliche saranno coinvolte. Questi valori sono solitamente configurati in file di configurazione aggiungendo:

synchronous_commit = local  
synchronous_standby_names='*'

Impostando il parametro synchronous_commit nel significato local, creiamo un sistema in cui i dischi locali rimangono sincroni, ma i commit della replica di rete sono asincroni per impostazione predefinita. A meno che, ovviamente, non decidiamo di rendere questi commit sincroni, come mostrato sopra.

Se hai seguito lo sviluppo Progetto del governatore, potresti aver notato alcune modifiche recenti (1, 2), che ha consentito agli utenti di Governor di testare questi parametri e monitorarne la coerenza.

Ancora qualche parola...

Solo una settimana fa vi avrei detto che è impossibile mettere a punto PostgreSQL in modo così preciso. È stato allora che Kurt, membro del team della piattaforma Compose, ha insistito sul fatto che esistesse un'opportunità del genere. Ha calmato le mie obiezioni e le ha trovate nella documentazione di PostgreSQL il seguente:

Impostazioni di coerenza di scrittura PostgreSQL e specifiche della connessione

Questa impostazione può essere modificata in qualsiasi momento. Il comportamento di qualsiasi transazione è determinato dall'impostazione in vigore al momento del commit. Pertanto, è possibile e utile che alcune transazioni vengano eseguite in modo sincrono e per altre in modo asincrono. Ad esempio, per forzarne uno multistatement transazione per effettuare commit in modo asincrono quando il valore predefinito del parametro è opposto, impostare SET LOCAL synchronous_commit TO OFF in una transazione.

Con questa piccola modifica al file di configurazione, abbiamo dato agli utenti il ​​controllo sulla coerenza e sulle prestazioni.

Fonte: habr.com

Aggiungi un commento