MariaDB
 sql >> Database >  >> RDS >> MariaDB

Come eseguire e configurare ProxySQL 2.0 per MySQL Galera Cluster su Docker

ProxySQL è un proxy SQL intelligente e ad alte prestazioni che supporta MySQL, MariaDB e ClickHouse. Di recente, ProxySQL 2.0 è diventato GA e viene fornito con nuove interessanti funzionalità come letture coerenti GTID, SSL frontend, Galera e supporto nativo di MySQL Group Replication.

È relativamente facile eseguire ProxySQL come contenitore Docker. In precedenza abbiamo scritto su come eseguire ProxySQL su Kubernetes come contenitore di supporto o come servizio Kubernetes, basato su ProxySQL 1.x. In questo post del blog utilizzeremo la nuova versione ProxySQL 2.x che utilizza un approccio diverso per la configurazione di Galera Cluster.

Immagine Docker ProxySQL 2.x

Abbiamo rilasciato un nuovo contenitore di immagini Docker ProxySQL 2.0 ed è disponibile in Docker Hub. Il README fornisce una serie di esempi di configurazione in particolare per Galera e MySQL Replication, pre e post v2.x. Le righe di configurazione possono essere definite in un file di testo e mappate nel percorso del contenitore in /etc/proxysql.cnf per essere caricate nel servizio ProxySQL.

Il tag dell'immagine "latest" punta ancora a 1.x fino a quando ProxySQL 2.0 non diventa ufficialmente GA (non abbiamo ancora visto alcun blog/articolo di rilascio ufficiale dal team di ProxySQL). Ciò significa che ogni volta che installi l'immagine ProxySQL utilizzando l'ultimo tag di Diversinines, otterrai comunque la versione 1.x con essa. Prendi nota che le nuove configurazioni di esempio abilitano anche le statistiche web ProxySQL (introdotte in 1.4.4 ma ancora in versione beta), un semplice dashboard che riassume la configurazione generale e lo stato di ProxySQL stesso.

Supporto ProxySQL 2.x per il cluster Galera

Parliamo più in dettaglio del supporto nativo di Galera Cluster. La nuova tabella mysql_galera_hostgroups è composta dai seguenti campi:

  • writer_hostgroup : ID del gruppo host che conterrà tutti i membri che sono autori (read_only=0).
  • backup_writer_hostgroup : Se il cluster è in esecuzione in modalità multi-scrittore (ovvero sono presenti più nodi con read_only=0) e max_writers è impostato su un numero inferiore al numero totale di nodi, i nodi aggiuntivi vengono spostati in questo gruppo host del writer di backup.
  • reader_hostgroup : ID del gruppo host che conterrà tutti i membri che sono lettori (ovvero nodi che hanno read_only=1)
  • gruppo_host_offline : Quando il monitoraggio ProxySQL determina che un host è OFFLINE, l'host verrà spostato in offline_hostgroup.
  • attivo : un valore booleano (0 o 1) per attivare un gruppo host
  • max_scrittori : Controlla il numero massimo di nodi consentiti nel gruppo host del writer, come menzionato in precedenza, i nodi aggiuntivi verranno spostati nel backup_writer_hostgroup.
  • scrittore_è_anche_lettore : Quando 1, un nodo nel writer_hostgroup verrà inserito anche nel reader_hostgroup in modo che venga utilizzato per le letture. Se impostato su 2, i nodi di backup_writer_hostgroup verranno inseriti nel reader_hostgroup, invece dei nodi nel writer_hostgroup.
  • max_transactions_behind : determina il numero massimo di set di scritture che un nodo nel cluster può aver accodato prima che il nodo venga SHUNNED per evitare letture obsolete (questo è determinato interrogando la variabile wsrep_local_recv_queue Galera).
  • commenta : Campo di testo utilizzabile per qualsiasi finalità definita dall'utente

Ecco un esempio di configurazione per mysql_galera_hostgroups in formato tabella:

Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
       writer_hostgroup: 10
backup_writer_hostgroup: 20
       reader_hostgroup: 30
      offline_hostgroup: 9999
                 active: 1
            max_writers: 1
  writer_is_also_reader: 2
max_transactions_behind: 20
                comment: 

ProxySQL esegue i controlli di integrità di Galera monitorando il seguente stato/variabile MySQL:

  • sola_lettura - Se ON, ProxySQL raggrupperà l'host definito in reader_hostgroup a meno che writer_is_also_reader non sia 1.
  • wsrep_desync - Se ON, ProxySQL contrassegnerà il nodo come non disponibile, spostandolo in offline_hostgroup.
  • wsrep_reject_queries - Se questa variabile è attiva, ProxySQL contrassegnerà il nodo come non disponibile, spostandolo in offline_hostgroup (utile in alcune situazioni di manutenzione).
  • wsrep_sst_donor_rejects_queries - Se questa variabile è attiva, ProxySQL contrassegnerà il nodo come non disponibile mentre il nodo Galera funge da donatore SST, spostandolo in offline_hostgroup.
  • wsrep_local_state - Se questo stato restituisce un valore diverso da 4 (4 significa sincronizzato), ProxySQL contrassegnerà il nodo come non disponibile e lo sposterà in offline_hostgroup.
  • wsrep_local_recv_queue - Se questo stato è maggiore di max_transactions_behind, il nodo verrà evitato.
  • wsrep_cluster_status - Se questo stato ritorna diverso da Primario, ProxySQL contrassegnerà il nodo come non disponibile e lo sposterà in offline_hostgroup.

Detto questo, combinando questi nuovi parametri in mysql_galera_hostgroups insieme a mysql_query_rules, ProxySQL 2.x ha la flessibilità per adattarsi a molti più casi d'uso di Galera. Ad esempio, si possono avere gruppi host a scrittore singolo, multi-scrittore e multi-lettore definiti come gruppo host di destinazione di una regola di query, con la possibilità di limitare il numero di autori e controllare meglio il comportamento delle letture non aggiornate.

Confrontalo con ProxySQL 1.x, in cui l'utente doveva definire in modo esplicito uno scheduler per chiamare uno script esterno per eseguire i controlli di integrità del back-end e aggiornare lo stato dei server di database. Ciò richiede una personalizzazione dello script (l'utente deve aggiornare l'utente/password/porta dell'amministratore di ProxySQL) in più dipendeva da uno strumento aggiuntivo (client MySQL) per connettersi all'interfaccia di amministrazione di ProxySQL.

Ecco un esempio di configurazione dell'utilità di pianificazione dello script di controllo dello stato di Galera in formato tabella per ProxySQL 1.x:

Admin> select * from scheduler\G
*************************** 1. row ***************************
         id: 1
     active: 1
interval_ms: 2000
   filename: /usr/share/proxysql/tools/proxysql_galera_checker.sh
       arg1: 10
       arg2: 20
       arg3: 1
       arg4: 1
       arg5: /var/lib/proxysql/proxysql_galera_checker.log
    comment:

Inoltre, poiché il thread dello scheduler di ProxySQL esegue qualsiasi script in modo indipendente, sono disponibili molte versioni di script di controllo dello stato. Tutte le istanze ProxySQL distribuite da ClusterControl utilizzano lo script predefinito fornito dal pacchetto di installazione di ProxySQL.

In ProxySQL 2.x, le variabili max_writers e writer_is_also_reader possono determinare il modo in cui ProxySQL raggruppa dinamicamente i server MySQL back-end e influenzeranno direttamente la distribuzione della connessione e l'instradamento delle query. Ad esempio, considera i seguenti server back-end MySQL:

Admin> select hostgroup_id, hostname, status, weight from mysql_servers;
+--------------+--------------+--------+--------+
| hostgroup_id | hostname     | status | weight |
+--------------+--------------+--------+--------+
| 10           | DB1          | ONLINE | 1      |
| 10           | DB2          | ONLINE | 1      |
| 10           | DB3          | ONLINE | 1      |
+--------------+--------------+--------+--------+

Insieme alla seguente definizione di gruppi host Galera:

Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
       writer_hostgroup: 10
backup_writer_hostgroup: 20
       reader_hostgroup: 30
      offline_hostgroup: 9999
                 active: 1
            max_writers: 1
  writer_is_also_reader: 2
max_transactions_behind: 20
                comment: 

Considerando che tutti gli host sono attivi e funzionanti, molto probabilmente ProxySQL raggrupperà gli host come segue:

Vediamoli uno per uno:

Configurazione Descrizione
writer_is_also_reader=0
  • Raggruppa gli host in 2 gruppi host (writer e backup_writer).
  • Writer fa parte del backup_writer.
  • Dato che lo scrittore non è un lettore, niente nel gruppo host 30 (lettore) perché nessuno degli host è impostato con read_only=1. Non è una pratica comune in Galera abilitare il flag di sola lettura.
writer_is_also_reader=1
  • Raggruppa gli host in 3 gruppi host (scrittore, scrittore_backup e lettore).
  • La variabile read_only=0 in Galera non ha alcun effetto, quindi anche lo scrittore è nel gruppo host 30 (lettore)
  • Writer non fa parte di backup_writer.
writer_is_also_reader=2
  • Simile a writer_is_also_reader=1, tuttavia, writer fa parte di backup_writer.

Con questa configurazione, si possono avere varie scelte per la destinazione del gruppo host per soddisfare carichi di lavoro specifici. Le scritture "hotspot" possono essere configurate per passare a un solo server per ridurre i conflitti multi-master, le scritture non in conflitto possono essere distribuite equamente sugli altri master, la maggior parte delle letture può essere distribuita uniformemente su tutti i server MySQL o non writer, letture critiche può essere inoltrato ai server più aggiornati e le letture analitiche possono essere inoltrate a una replica slave.

Distribuzione proxySQL per il cluster Galera

In questo esempio, supponiamo di avere già un cluster Galera a tre nodi distribuito da ClusterControl come mostrato nel diagramma seguente:

Le nostre applicazioni Wordpress sono in esecuzione su Docker mentre il database Wordpress è ospitato sul nostro Cluster Galera in esecuzione su server bare-metal. Abbiamo deciso di eseguire un contenitore ProxySQL insieme ai nostri contenitori Wordpress per avere un migliore controllo sull'instradamento delle query del database di Wordpress e utilizzare appieno la nostra infrastruttura di cluster di database. Poiché il rapporto di lettura-scrittura è di circa l'80%-20%, vogliamo configurare ProxySQL su:

  • Inoltra tutte le scritture a un nodo Galera (meno conflitti, concentrati sulla scrittura)
  • Bilancia tutte le letture sugli altri due nodi Galera (migliore distribuzione per la maggior parte del carico di lavoro)

Innanzitutto, crea un file di configurazione ProxySQL all'interno dell'host Docker in modo da poterlo mappare nel nostro contenitore:

$ mkdir /root/proxysql-docker
$ vim /root/proxysql-docker/proxysql.cnf

Quindi, copia le seguenti righe (spiegheremo le righe di configurazione più in basso):

datadir="/var/lib/proxysql"

admin_variables=
{
    admin_credentials="admin:admin"
    mysql_ifaces="0.0.0.0:6032"
    refresh_interval=2000
    web_enabled=true
    web_port=6080
    stats_credentials="stats:admin"
}

mysql_variables=
{
    threads=4
    max_connections=2048
    default_query_delay=0
    default_query_timeout=36000000
    have_compress=true
    poll_timeout=2000
    interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
    default_schema="information_schema"
    stacksize=1048576
    server_version="5.1.30"
    connect_timeout_server=10000
    monitor_history=60000
    monitor_connect_interval=200000
    monitor_ping_interval=200000
    ping_interval_server_msec=10000
    ping_timeout_server=200
    commands_stats=true
    sessions_sort=true
    monitor_username="proxysql"
    monitor_password="proxysqlpassword"
    monitor_galera_healthcheck_interval=2000
    monitor_galera_healthcheck_timeout=800
}

mysql_galera_hostgroups =
(
    {
        writer_hostgroup=10
        backup_writer_hostgroup=20
        reader_hostgroup=30
        offline_hostgroup=9999
        max_writers=1
        writer_is_also_reader=1
        max_transactions_behind=30
        active=1
    }
)

mysql_servers =
(
    { address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)

mysql_query_rules =
(
    {
        rule_id=100
        active=1
        match_pattern="^SELECT .* FOR UPDATE"
        destination_hostgroup=10
        apply=1
    },
    {
        rule_id=200
        active=1
        match_pattern="^SELECT .*"
        destination_hostgroup=30
        apply=1
    },
    {
        rule_id=300
        active=1
        match_pattern=".*"
        destination_hostgroup=10
        apply=1
    }
)

mysql_users =
(
    { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
    { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)

Ora, facciamo una visita ad alcune delle sezioni più di configurazione. In primo luogo, definiamo la configurazione dei gruppi host Galera come di seguito:

mysql_galera_hostgroups =
(
    {
        writer_hostgroup=10
        backup_writer_hostgroup=20
        reader_hostgroup=30
        offline_hostgroup=9999
        max_writers=1
        writer_is_also_reader=1
        max_transactions_behind=30
        active=1
    }
)

Il gruppo host 10 sarà il writer_hostgroup, il gruppo host 20 per il backup_writer e il gruppo host 30 per il lettore. Impostiamo max_writers su 1 in modo da poter avere un hostgroup a scrittore singolo per il gruppo host 10 a cui devono essere inviate tutte le scritture. Quindi, definiamo writer_is_also_reader a 1 che renderà anche tutti i nodi Galera come lettori, adatti per query che possono essere equamente distribuite a tutti i nodi. Hostgroup 9999 è riservato per offline_hostgroup se ProxySQL rileva nodi Galera non operativi.

Quindi, configuriamo i nostri server MySQL con il gruppo host 10 predefinito:

mysql_servers =
(
    { address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)

Con le configurazioni di cui sopra, ProxySQL "vedrà" i nostri gruppi host come di seguito:

Quindi, definiamo l'instradamento della query tramite regole di query. In base al nostro requisito, tutte le letture devono essere inviate a tutti i nodi Galera tranne lo scrittore (gruppo host 20) e tutto il resto viene inoltrato al gruppo host 10 per singolo scrittore:

mysql_query_rules =
(
    {
        rule_id=100
        active=1
        match_pattern="^SELECT .* FOR UPDATE"
        destination_hostgroup=10
        apply=1
    },
    {
        rule_id=200
        active=1
        match_pattern="^SELECT .*"
        destination_hostgroup=20
        apply=1
    },
    {
        rule_id=300
        active=1
        match_pattern=".*"
        destination_hostgroup=10
        apply=1
    }
)

Infine, definiamo gli utenti MySQL che verranno passati attraverso ProxySQL:

mysql_users =
(
    { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
    { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)

Impostiamo transaction_persistent su 0 in modo che tutte le connessioni provenienti da questi utenti rispettino le regole di query per il routing di lettura e scrittura. In caso contrario, le connessioni finirebbero per colpire un gruppo host che vanifica lo scopo del bilanciamento del carico. Non dimenticare di creare prima quegli utenti su tutti i server MySQL. Per l'utente ClusterControl, è possibile utilizzare la funzione Gestisci -> Schemi e utenti per creare quegli utenti.

Ora siamo pronti per iniziare il nostro container. Mapperemo il file di configurazione ProxySQL come bind mount all'avvio del contenitore ProxySQL. Pertanto, il comando di esecuzione sarà:

$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
severalnines/proxysql:2.0

Infine, modifica il database di Wordpress che punta alla porta del contenitore ProxySQL 6033, ad esempio:

$ docker run -d \
--name wordpress \
--publish 80:80 \
--restart=unless-stopped \
-e WORDPRESS_DB_HOST=proxysql2:6033 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_HOST=passw0rd \
wordpress

A questo punto, la nostra architettura è simile a questa:

Se vuoi che il contenitore ProxySQL sia persistente, mappa /var/lib/proxysql/ su un volume Docker o associa il montaggio, ad esempio:

$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
-v proxysql-volume:/var/lib/proxysql \
severalnines/proxysql:2.0

Tieni presente che l'esecuzione con l'archiviazione persistente come sopra renderà il nostro /root/proxysql/proxysql.cnf obsoleto al secondo riavvio. Ciò è dovuto alla configurazione multilivello di ProxySQL per cui se esiste /var/lib/proxysql/proxysql.db, ProxySQL salterà le opzioni di caricamento dal file di configurazione e caricherà invece tutto ciò che è nel database SQLite (a meno che non si avvii il servizio proxysql con --initial bandiera). Detto questo, la successiva gestione della configurazione di ProxySQL deve essere eseguita tramite la console di amministrazione ProxySQL sulla porta 6032, invece di utilizzare il file di configurazione.

Monitoraggio

Registro del processo ProxySQL per impostazione predefinita registrando su syslog e puoi visualizzarli utilizzando il comando docker standard:

$ docker ps
$ docker logs proxysql2

Per verificare il gruppo host corrente, interroga la tabella runtime_mysql_servers:

$ docker exec -it proxysql2 mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt='Admin> '
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname     | status |
+--------------+--------------+--------+
| 10           | 192.168.0.21 | ONLINE |
| 30           | 192.168.0.21 | ONLINE |
| 30           | 192.168.0.22 | ONLINE |
| 30           | 192.168.0.23 | ONLINE |
| 20           | 192.168.0.22 | ONLINE |
| 20           | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+

Se lo scrittore selezionato si interrompe, verrà trasferito al offline_hostgroup (HID 9999):

Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname     | status |
+--------------+--------------+--------+
| 10           | 192.168.0.22 | ONLINE |
| 9999         | 192.168.0.21 | ONLINE |
| 30           | 192.168.0.22 | ONLINE |
| 30           | 192.168.0.23 | ONLINE |
| 20           | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+

Le modifiche alla topologia di cui sopra possono essere illustrate nel diagramma seguente:

Abbiamo anche abilitato l'interfaccia utente delle statistiche web con admin-web_enabled=true. Per accedere all'interfaccia utente web, vai semplicemente all'host Docker nella porta 6080, ad esempio:http://192.168.0.200:8060 e ti verrà chiesto con nome utente/password pop-up. Inserisci le credenziali come definito in admin-stats_credentials e dovresti vedere la seguente pagina:

Monitorando la tabella del pool di connessioni MySQL, possiamo ottenere una panoramica della distribuzione delle connessioni per tutti i gruppi host:

Admin> select hostgroup, srv_host, status, ConnUsed, MaxConnUsed, Queries from stats.stats_mysql_connection_pool order by srv_host;
+-----------+--------------+--------+----------+-------------+---------+
| hostgroup | srv_host     | status | ConnUsed | MaxConnUsed | Queries |
+-----------+--------------+--------+----------+-------------+---------+
| 20        | 192.168.0.23 | ONLINE | 5        | 24          | 11458   |
| 30        | 192.168.0.23 | ONLINE | 0        | 0           | 0       |
| 20        | 192.168.0.22 | ONLINE | 2        | 24          | 11485   |
| 30        | 192.168.0.22 | ONLINE | 0        | 0           | 0       |
| 10        | 192.168.0.21 | ONLINE | 32       | 32          | 9746    |
| 30        | 192.168.0.21 | ONLINE | 0        | 0           | 0       |
+-----------+--------------+--------+----------+-------------+---------+

L'output sopra mostra che il gruppo host 30 non elabora nulla perché le nostre regole di query non hanno questo gruppo host configurato come gruppo host di destinazione.

Le statistiche relative ai nodi Galera possono essere visualizzate nella tabella mysql_server_galera_log:

Admin>  select * from mysql_server_galera_log order by time_start_us desc limit 3\G
*************************** 1. row ***************************
                       hostname: 192.168.0.23
                           port: 3306
                  time_start_us: 1552992553332489
                success_time_us: 2045
              primary_partition: YES
                      read_only: NO
         wsrep_local_recv_queue: 0
              wsrep_local_state: 4
                   wsrep_desync: NO
           wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
                          error: NULL
*************************** 2. row ***************************
                       hostname: 192.168.0.22
                           port: 3306
                  time_start_us: 1552992553329653
                success_time_us: 2799
              primary_partition: YES
                      read_only: NO
         wsrep_local_recv_queue: 0
              wsrep_local_state: 4
                   wsrep_desync: NO
           wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
                          error: NULL
*************************** 3. row ***************************
                       hostname: 192.168.0.21
                           port: 3306
                  time_start_us: 1552992553329013
                success_time_us: 2715
              primary_partition: YES
                      read_only: NO
         wsrep_local_recv_queue: 0
              wsrep_local_state: 4
                   wsrep_desync: NO
           wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
                          error: NULL

Il set di risultati restituisce lo stato di stato/variabile MySQL correlato per ogni nodo Galera per un determinato timestamp. In questa configurazione, abbiamo configurato il controllo dello stato di Galera in modo che venga eseguito ogni 2 secondi (monitor_galera_healthcheck_interval=2000). Pertanto, il tempo massimo di failover sarebbe di circa 2 secondi se si verifica una modifica della topologia al cluster.

Riferimenti

  • Supporto di ProxySQL Native Galera
  • Soluzione HA e clustering:ProxySQL come router intelligente per Galera e Group Replication
  • Immagine ProxySQL Docker di Multiplenines
  • Come monitorare ProxySQL con Prometheus e ClusterControl