PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Confronto dei bilanciatori di carico per PostgreSQL

Il bilanciamento del carico aumenta le prestazioni del sistema, soprattutto dal punto di vista dell'applicazione, consentendo a più computer di gestire gli stessi dati. Funziona in modo tale che il carico venga distribuito tra le query del client per replicare i nodi oltre al nodo principale o principale, mentre instrada le modifiche del database esclusivamente al solo nodo principale. Eventuali modifiche al nodo master vengono successivamente propagate a ciascuna replica utilizzando PostgreSQL Streaming Replication.

In che modo i bilanciatori di carico possono influire su PostgreSQL?

L'utilizzo del bilanciamento del carico indirizzerà le applicazioni client a connettersi al server di bilanciamento del carico e distribuirà le connessioni avviate ai nodi PostgreSQL disponibili a seconda del tipo di richieste di query. Questo aiuta a stressare il carico eccezionale su un particolare server PostgreSQL e promuove il bilanciamento del carico parallelo tra i nodi disponibili all'interno del cluster.

Utilizzando PostgreSQL, esistono già alcune soluzioni esistenti per farlo funzionare. Queste soluzioni possono funzionare senza problemi o il bilanciamento del carico può funzionare con la topologia corrente, con i nodi primari e di standby, ma il bilanciamento del carico è implementato nel livello dell'applicazione stesso. Il bilanciamento del carico affronta sfide con problemi di sincronizzazione che rappresentano la difficoltà fondamentale per i server che lavorano insieme. Poiché non esiste un'unica soluzione che elimini l'impatto del problema di sincronizzazione per tutti i casi d'uso, esistono più soluzioni. Ogni soluzione affronta questo problema in un modo diverso e riduce al minimo il suo impatto per un carico di lavoro specifico.

In questo blog, daremo un'occhiata a quei sistemi di bilanciamento del carico confrontandoli e quanto sono utili per il tuo carico di lavoro PostgreSQL.

Bilanciamento del carico HAProxy per PostgreSQL

HAProxy è un motore non bloccante basato su eventi che combina un proxy con uno strato I/O molto veloce e uno scheduler multi-thread basato su priorità. Poiché è progettato pensando all'obiettivo di inoltro dei dati, la sua architettura è progettata per funzionare in un processo leggero ottimizzato per spostare i dati il ​​più velocemente possibile con il minor numero di operazioni possibili. Si concentra sull'ottimizzazione dell'efficienza della cache della CPU mantenendo le connessioni alla stessa CPU il più a lungo possibile. In quanto tale, implementa un modello a più livelli che offre meccanismi di bypass a ogni livello assicurando che i dati non raggiungano livelli superiori a meno che non sia necessario. La maggior parte dell'elaborazione viene eseguita nel kernel. HAProxy fa del suo meglio per aiutare il kernel a svolgere il lavoro il più velocemente possibile fornendo alcuni suggerimenti o evitando determinate operazioni quando ritiene che potrebbero essere raggruppate in seguito. Di conseguenza, le cifre tipiche mostrano il 15% del tempo di elaborazione trascorso in HAProxy rispetto all'85% nel kernel in modalità di chiusura TCP o HTTP e circa il 30% per HAProxy rispetto al 70% per il kernel in modalità HTTP keep-alive.

HAProxy ha anche funzionalità aggiuntive per il bilanciamento del carico. Ad esempio, la funzione di proxy TCP ci consente di utilizzarla per le connessioni al database, in particolare per PostgreSQL, utilizzando il supporto del servizio di verifica integrato. Anche se è disponibile il supporto del servizio di database, non è sufficiente il controllo dello stato desiderato, soprattutto per un tipo di replica di cluster. L'approccio standard durante la distribuzione per la produzione consiste nell'utilizzare il controllo TCP, quindi dipendere da xinetd con HAProxy.

Profughi dell'utilizzo di HAProxy per PostgreSQL

La cosa migliore con HAProxy è il suo peso leggero, facile da configurare e utilizzare, e fa il lavoro come previsto. L'utilizzo di HAProxy su un cluster PostgreSQL è stato implementato e distribuito più volte da grandi organizzazioni a varie PMI/PMI per il loro uso in produzione. È stato a lungo dimostrato per la produzione e l'elevata capacità di carico di lavoro non solo per i database ma anche con altri servizi di rete come applicazioni Web o per il bilanciamento del carico geografico (distribuire il traffico su più data center). Avendo HAProxy su PostgreSQL, consente agli utenti la capacità di limitare o limitare le risposte per parallelizzare e distribuire correttamente il carico a tutti i nodi disponibili nel cluster. Il meccanismo integrato con HAProxy consente inoltre all'utente di configurare l'alta disponibilità senza interruzioni e più facile da scalare se è necessario il carico ed evitare il singolo punto di errore (SPOF).

Contro dell'utilizzo di HAProxy per PostgreSQL

HAProxy non fornisce il filtraggio delle query né l'analisi delle query per identificare il tipo di istruzioni richieste. Manca la capacità di eseguire una divisione di lettura/scrittura su una singola porta. L'impostazione di un sistema di bilanciamento del carico su HAProxy richiede almeno di configurare porte diverse per le scritture e diverse per le letture. Ciò richiede modifiche all'applicazione per soddisfare le tue esigenze.

HAProxy supporta anche una funzionalità molto semplice con PostgreSQL per il controllo dello stato, ma questo determina solo se il nodo è attivo o meno, come se stesse semplicemente eseguendo il ping del nodo e attende una risposta di rimbalzo. Non identifica quale ruolo sta tentando un nodo di inoltrare le connessioni richieste dal client al nodo desiderato. Pertanto, non comprende o non comprende alcuna funzione in HAProxy per comprendere la topologia di replica. Sebbene un utente possa creare listener separati in base a porte diverse, aggiunge comunque modifiche all'interno dell'applicazione per soddisfare le esigenze di bilanciamento del carico. Ciò significa che l'utilizzo di uno script esterno con xinetd può essere la soluzione alternativa per soddisfare i requisiti. Tuttavia, non è integrato in HAProxy e può essere soggetto a errori umani.

Se un nodo o un gruppo di nodi deve essere messo in modalità di manutenzione, ti verrà richiesto anche di applicare le modifiche al tuo HAProxy, altrimenti può essere catastrofico.

Pgpool-II per il bilanciamento del carico di PostgreSQL

Pgpool-II è un software open source ed è adottato dalla massiccia comunità di PostgreSQL per l'implementazione del bilanciamento del carico e l'utilizzo di questo come middleware dall'applicazione fino al livello proxy, quindi distribuisce il carico dopo aver analizzato completamente il tipo di richiesta per query o connessione al database. Pgpool-II è stato lì per così tanto tempo dal 2003, originariamente chiamato Pgpool fino a quando non è diventato Pgpool-II nel 2006, che funge da testamento di uno strumento proxy molto stabile non solo per il bilanciamento del carico ma anche per tonnellate di fantastiche funzionalità .

Pgpool-II è conosciuto come il coltellino svizzero di PostgreSQL ed è un software proxy che si trova tra i server PostgreSQL e un client di database PostgreSQL. L'idea di base di PgPool-II è che si trova sul client, quindi le query di lettura devono essere inviate ai nodi di standby, mentre la scrittura o le modifiche vanno direttamente al primario. È una soluzione di bilanciamento del carico molto intelligente che non solo bilancia il carico, ma supporta anche l'alta disponibilità e fornisce pool di connessioni. Il meccanismo intelligente permette di bilanciare il carico tra master e slave. Quindi le scritture vengono caricate sul master, mentre le letture di elaborazione vengono dirette ai server di sola lettura disponibili, che sono i tuoi presunti nodi hot standby. Pgpool-II fornisce anche la replica logica. Sebbene il suo utilizzo e importanza siano diminuiti con il miglioramento delle opzioni di replica integrate sul lato server di PostgreSQL, questa rimane ancora un'opzione preziosa per le versioni precedenti di PostgreSQL. Inoltre, fornisce anche il pool di connessioni.

Pgpool-II ha un'architettura più complessa di PgBouncer per supportare tutte le funzionalità che fa. Poiché entrambi supportano il pool di connessioni, quest'ultimo non ha funzionalità di bilanciamento del carico.

Pgpool-II può gestire più server PostgreSQL. L'utilizzo della funzione di replica consente di creare un backup in tempo reale su 2 o più dischi fisici, in modo che il servizio possa continuare senza arrestare i server in caso di guasto del disco. Poiché Pgpool-II è anche un pool di connessioni in grado di fornire limitazioni alle connessioni in eccesso. C'è un limite al numero massimo di connessioni simultanee con PostgreSQL e le connessioni vengono rifiutate dopo questo numero di connessioni. L'impostazione del numero massimo di connessioni, tuttavia, aumenta il consumo di risorse e influisce sulle prestazioni del sistema. pgpool-II ha anche un limite al numero massimo di connessioni, ma le connessioni extra verranno accodate invece di restituire immediatamente un errore.

Nel bilanciamento del carico, se un database viene replicato, l'esecuzione di una query SELECT su qualsiasi server restituirà lo stesso risultato. pgpool-II sfrutta la funzione di replica per ridurre il carico su ciascun server PostgreSQL distribuendo le query SELECT tra più server, migliorando il throughput complessivo del sistema. Nella migliore delle ipotesi, le prestazioni migliorano proporzionalmente al numero di server PostgreSQL. Il bilanciamento del carico funziona meglio in una situazione in cui molti utenti eseguono molte query contemporaneamente.

Utilizzando la funzione di query parallela, i dati possono essere suddivisi tra più server, in modo che una query possa essere eseguita su tutti i server contemporaneamente per ridurre il tempo di esecuzione complessivo. La query parallela funziona al meglio durante la ricerca di dati su larga scala.

Profughi dell'utilizzo di Pgpool per PostgreSQL

È un tipo di software ricco di funzionalità non solo per il bilanciamento del carico. Le funzionalità principali e il supporto di questo strumento è altamente on-demand che fornisce pool di connessioni, un PgBouncer alternativo, replica nativa, ripristino online, memorizzazione nella cache delle query in memoria, failover automatico e alta disponibilità con il suo processo secondario che utilizza watchdog. Questo strumento è stato così vecchio ed è continuamente supportato in modo massiccio dalla comunità di PostgreSQL, quindi affrontare i problemi non può essere difficile cercare aiuto. La documentazione è tua amica qui quando cerchi domande, ma cercare aiuto nella comunità non è difficile, e il fatto che questo strumento sia un open-source, quindi puoi usarlo liberamente purché rispetti la licenza BSD.

Pgpool-II ha anche un parser SQL. Ciò significa che è in grado di analizzare accuratamente gli SQL e riscrivere la query. Ciò consente a Pgpool-II di aumentare il parallelismo a seconda della richiesta di query.

Contro dell'utilizzo di Pgpool per PostgreSQL

Pgpool-II non offre STONITH (spara all'altro nodo nella testa) che fornisce un meccanismo di scherma dei nodi. Se il server PostgreSQL si guasta, mantiene la disponibilità del servizio. Pgpool-II può anche essere il singolo punto di errore (SPOF). Una volta che il nodo si interrompe, la connettività e la disponibilità del database si interrompono da quel punto. Sebbene ciò possa essere risolto avendo ridondanza con Pgpool-II e dovendo utilizzare il watchdog per coordinare più nodi Pgpool-II, ciò aggiunge ulteriore lavoro.

Per il pool di connessioni, sfortunatamente, per coloro che si concentrano solo sul pool di connessioni, ciò che Pgpool-II non fa molto bene è il pool di connessioni, soprattutto per un numero limitato di client. Poiché ogni processo figlio ha il proprio pool e non c'è modo di controllare quale client si connette a quale processo figlio, troppo viene lasciato alla fortuna quando si tratta di riutilizzare le connessioni.

Utilizzo del driver JDBC per il bilanciamento del carico di PostgreSQL

Java Database Connectivity (JDBC) è un'API (Application Programming Interface) per il linguaggio di programmazione Java, che definisce come un client può accedere a un database. Fa parte della piattaforma Java Standard Edition e fornisce metodi per interrogare e aggiornare i dati in un database ed è orientato ai database relazionali.

Il driver PostgreSQL JDBC (PgJDBC in breve) consente ai programmi Java di connettersi a un database PostgreSQL utilizzando codice Java standard indipendente dal database. È un driver JDBC open source scritto in Pure Java (Tipo 4) e comunica nel protocollo di rete nativo PostgreSQL. Per questo motivo, il driver è indipendente dalla piattaforma; una volta compilato, il driver può essere utilizzato su qualsiasi sistema.

Non è paragonabile alle soluzioni di bilanciamento del carico che abbiamo indicato in precedenza. Quindi, questo strumento è l'API dell'interfaccia di programmazione dell'applicazione che ti consente di connetterti dalla tua applicazione per qualsiasi tipo di linguaggio di programmazione scritto che supporti JDBC o almeno abbia un adattatore per la connessione con JDBC. D'altra parte, è più favorevole con le applicazioni Java.

Il bilanciamento del carico con JDBC è piuttosto ingenuo ma può fare il lavoro. Fornito con i parametri di connessione che possono attivare il meccanismo di bilanciamento del carico che questo strumento ha da offrire,

  • targetServerType:consente di aprire connessioni solo ai server con stato/ruolo richiesto in base al fattore di definizione per i server PostgreSQL. I valori consentiti sono any, primary, master (obsoleto), slave (obsoleto), secondary, preferSlave e preferSecondary. Lo stato o il ruolo è determinato osservando se il server consente scritture o meno.
  • hostRecheckSeconds - controlla per quanto tempo in secondi la conoscenza di uno stato host viene memorizzata nella cache globale JVM. Il valore predefinito è 10 secondi.
  • loadBalanceHosts:consente di configurare se il primo host viene sempre provato (se impostato su false) o se le connessioni vengono scelte casualmente (se impostato su true)

Quindi usando loadBalanceHosts che accetta un valore booleano. loadBalanceHosts è disabilitato durante la sua modalità predefinita e gli host sono connessi nell'ordine indicato. Se gli host abilitati vengono scelti casualmente dall'insieme dei candidati idonei. La sintassi di base quando ci si connette al database utilizzando jdbc è la seguente,

  • jdbc:postgresql:database
  • jdbc:postgresql:/
  • jdbc:postgresql://host/database
  • jdbc:postgresql://host/
  • jdbc:postgresql://host:porta/database
  • jdbc:postgresql://host:port/

Dato che loadBalanceHosts e la connessione ricevono più host configurati proprio come di seguito,

jdbc:postgresql://host1:port1,host2:port2,host3:port3/database

Ciò consente a JDBC di scegliere casualmente dall'insieme di candidati idonei.

Profughi dell'utilizzo di PgJDBC per PostgreSQL

Non è necessario richiedere middleware o proxy come bilanciatori di carico. Questo processo aggiunge un ulteriore aumento delle prestazioni dal frontend dell'applicazione poiché non esiste un livello aggiuntivo per ogni richiesta da superare. Se hai delle applicazioni pronte e scritte per supportare l'interfacciamento a JDBC, questo può essere vantaggioso e se non hai bisogno di più middleware soprattutto se il tuo budget è limitato e vuoi limitare solo i processi dedicati al suo unico scopo e funzione. A differenza delle applicazioni ad alto traffico e ad alta richiesta, potrebbe richiedere server proxy che fungano da bilanciatori del carico e potrebbe richiedere risorse extra per gestire correttamente richieste elevate di connessioni, il che richiede anche un'elaborazione della CPU e della memoria.

Contro dell'utilizzo di PgJDBC per PostgreSQL

Devi impostare il tuo codice per ogni connessione da richiedere. È un'interfaccia di programmazione dell'applicazione, il che significa che c'è del lavoro da affrontare, specialmente se la tua applicazione è molto impegnativa su ogni richiesta da inviare ai server appropriati. Non esiste alta disponibilità, scalabilità automatica e presenta un singolo punto di errore.

Che ne dici di wrapper o strumenti implementati con libpq per il bilanciamento del carico di PostgreSQL?

libpq è l'interfaccia del programmatore di applicazioni C per PostgreSQL. libpq è un insieme di funzioni di libreria che consentono ai programmi client di passare query al server di backend PostgreSQL e di ricevere i risultati di queste query.

libpq è anche il motore sottostante per molte altre interfacce di applicazioni PostgreSQL, comprese quelle scritte per C++, PHP, Perl, Python, Tcl, Swift ed ECPG. Quindi alcuni aspetti del comportamento di libpq saranno importanti per te se usi uno di quei pacchetti.

libpq non automatizza il bilanciamento del carico e non è da considerarsi uno strumento per soluzioni di bilanciamento del carico. Tuttavia, è in grado di connettersi ai successivi server disponibili se i server precedenti elencati per la connessione non riescono. Ad esempio, se sono disponibili due nodi hot standby, se il primo nodo è troppo occupato e non risponde al valore di timeout corrispondente, si connette al successivo nodo disponibile nella connessione specificata. Si basa sul tipo di attributi di sessione specificati. Questo si basa sul parametro target_session_attrs.

Il parametro target_session_attrs accetta valori di lettura-scrittura e qualsiasi valore predefinito se non specificato. Ciò che fa il parametro target_session_attrs è che, se impostato su lettura-scrittura, solo una connessione in cui vengono accettate transazioni di lettura-scrittura durante la connessione. La query SHOW Transaction_read_only verrà inviata in caso di connessione riuscita. Se il risultato è attivo, la connessione verrà chiusa, il che significa che il nodo viene identificato come una replica o non elabora le scritture. Se sono stati specificati più host nella stringa di connessione, tutti i server rimanenti verranno provati proprio come se il tentativo di connessione non fosse riuscito. Il valore predefinito di questo parametro, any, che indica che tutte le connessioni sono accettabili. Sebbene fare affidamento su target_session_attrs non sia sufficiente per il bilanciamento del carico, potresti essere in grado di simulare una modalità round robin. Vedi il mio codice C di esempio qui sotto usando libpq,

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include <unistd.h>

#include <libpq-fe.h>




const char* _getRoundRobinConn() {

   char* h[2];

   h[0] = "dbname=node40 host=192.168.30.40,192.168.30.50";

   h[1] = "dbname=node50 host=192.168.30.50,192.168.30.40";



   time_t t;

   //srand((unsigned)time(&t));

   sleep(1.85);

   srand((unsigned)time(NULL));



   return h[rand() % 2];

}



void

_connect()

{

  PGconn *conn;

  PGresult *res;

  char strConn[120];




  snprintf(strConn, 1000, "user=dbapgadmin password=dbapgadmin %s target_session_attrs=any", _getRoundRobinConn());

  //printf("\nstrConn value is: %s\n", strConn);



  conn = PQconnectdb(strConn);



  res = PQexec(conn, "SELECT current_database(), inet_client_addr();");



  if ( PQresultStatus(res)==PGRES_TUPLES_OK )

  {

    printf("current_database = %s on %s\n", PQgetvalue(res, 0, 0),

PQhost(conn));

  } else {



    printf("\nFailed... Message Code is: %d\n", PQresultStatus(res));

  }



  PQclear(res);

  PQfinish(conn);



}



int main(void)

{

  int i;

  for (i=0 ; i<5 ; i++)

    _connect();



  return 0;

}

Il risultato rivela,

[email protected]:/home/vagrant# gcc -I/usr/include/postgresql -L/usr/lib/postgresql/12/lib libpq_conn.c -lpq -o libpq_conn; ./libpq_conn

current_database = node40 on 192.168.30.40

current_database = node40 on 192.168.30.40

current_database = node50 on 192.168.30.50

current_database = node40 on 192.168.30.40

current_database = node50 on 192.168.30.50

Tieni presente che, se il nodo .40 (il nodo principale) non funziona, indirizzerà sempre la connessione a .50 purché il valore target_session_attrs sia qualsiasi.

In tal caso, puoi semplicemente crearne uno tuo liberamente con l'aiuto di libpq. Sebbene il processo di fare affidamento su libpq e/o sui suoi wrapper sia semplicemente troppo grezzo per dire che questo può fornire il meccanismo di bilanciamento del carico desiderato con una distribuzione uniforme ai nodi che hai. Sicuramente, questo approccio e la codifica possono essere migliorati, ma il pensiero è che questo è gratuito e open source e puoi programmare senza fare affidamento su middleware e progettare liberamente il modo in cui funzionerà il tuo bilanciamento del carico.

Profughi dell'utilizzo di libpq per PostgresQL

libpq library è l'interfaccia dell'applicazione del programmatore costruita nel linguaggio di programmazione C. Tuttavia, la libreria è stata implementata in vari linguaggi come wrapper in modo che i programmatori possano comunicare con il database PostgreSQL usando i loro linguaggi preferiti. Puoi creare direttamente la tua applicazione utilizzando le tue lingue preferite e poi elencare in basso i server a cui intendi inviare le query ma solo dopo l'altro, in caso di guasto o timeout invia il tuo carico ai nodi disponibili su cui intendi distribuire il carico. È disponibile in linguaggi come Python, Perl, PHP, Ruby, Tcl o Rust.

Contro dell'utilizzo di libpq per PostgresQL

L'implementazione saggia per il parallelismo del carico non è perfetta e devi scrivere il tuo meccanismo di bilanciamento del carico per codice. Non c'è alcuna configurazione che puoi usare o personalizzare poiché è tutta da sola un'interfaccia di programmazione per il database PostgreSQL con l'aiuto di target_session_attrs param. Ciò significa che, quando si compone una connessione al database, è necessario disporre di una serie di connessioni di lettura che vanno ai nodi di replica/standby, quindi scrivere query che vanno al writer o al nodo primario nel codice, sia che si trovi nell'applicazione sia che si debba creare la tua API per gestire la soluzione di bilanciamento del carico.

L'utilizzo di questo approccio non richiede o fa affidamento su un middleware dal punto di vista dell'applicazione front-end al database come back-end. Ovviamente è leggero, ma quando si invia l'elenco dei server al momento della connessione, non significa che il carico sia compreso e inviato in modo uniforme a meno che non sia necessario aggiungere il codice per questo approccio. Questo aggiunge solo problemi, ma ci sono già soluzioni esistenti, quindi perché è necessario reinventare la ruota?

Conclusione

L'implementazione dei sistemi di bilanciamento del carico con PostgreSQL può essere impegnativa, ma dipende dal tipo di applicazione e dai costi con cui hai a che fare. A volte, per un'elevata richiesta di carico, è necessario che un middleware agisca da proxy per distribuire correttamente il carico e supervisiona anche lo stato o l'integrità del nodo. D'altra parte, potrebbe richiedere risorse del server o deve essere eseguito su un server dedicato o richiede CPU e memoria extra per soddisfare le esigenze e questo aggiunge costi. Quindi, c'è anche un modo semplice ma che richiede tempo ma offre la distribuzione del carico sui server disponibili che hai già. Tuttavia, richiede capacità di programmazione e comprensione delle funzionalità dell'API.