Con la replica MySQL
e' facile mantenere su server diversi una serie di database allineati
tra loro.
I database vengono utilizzati dalle applicazioni migliorando cosi'
le prestazioni, la scalabilita' e fornendo la massima affidabilita'.
Nelle configurazioni piu' complete la scelta
del server cui collegarsi e' effettuata da un load balancer (software o hardware)
e non dal driver o dall'applicazione.
In questa pagina presentiamo
una semplice tecnica basata su xinetd
per effettuare il routing corretto con un load balancer.
Nel seguito sono riportate alcune informazioni di interesse organizzate in paragrafi specifici: Introduzione, Installazione e configurazione, Esempi, Varie ed eventuali, ...
Il contenuto di questo documento e' tecnico. E' opportuna una conoscenza dell'architettura MySQL e della Replication.
Negli esempi che seguono vengono utilizzate le sintassi valide sugli ambienti piu' recenti ovvero: CentOS 7.3, MySQL 5.7 ed HAProxy 1.7 ma valgono per altri sistemi, programmi e versioni naturalmente... mutatis mudandis!
La funzionalita' di replica dati di MySQL e' molto utilizzata perche' e' semplice da configurare, aggiunge un carico ridotto ed e' molto flessibile.
Con la replica MySQL le architetture che si possono realizzare sono molteplici a seconda delle disponibilita' di risorse computazionali e degli obiettivi ricercati. Una tipica configurazione e' quella che utilizza molteplici Slave per fornire un'elevata scalabilita' sui carichi di lettura:
Nella configurazione presentata nella figura precedente le connessioni in lettura vengono bilanciate su decine (o centinaia) di DB server differenti permettendo di distribuire il carico ed ottenere prestazioni sempre ottimali. Naturalmente questo richiede che le applicazioni utilizzino connessioni differenti a seconda del tipo di richiesta: molte applicazioni MySQL hanno la possibilita' di configurare stringhe di connessione differenti appunto per questa ragione.
Molto piu' recente [NdE disponibile dal 2016-12 in MySQL 5.7.17] e' la Group Replication che consente di gruppi di replica in alta affidabilita' presentata nella figura a lato.
In questo caso e' possibile bilanciare anche le connessioni in
scrittura perche' la Group Replication effettua automaticamente
la failure detection e consente anche la configurazione Multi Primary.
Con la Group Replication le scelte possibili sono diverse...
a mio avviso la configurazione migliore e' quella di utilizzare
la configurazione Single-Primary indirizzando le scritture sul Master
e bilanciando le letture su tutti i nodi disponibili.
In questo modo si ha l'alta affidabilita',
l'automatismo per la gestione dei fault e
si bilancia comunque il carico.
Nella configurazione dei load balancer una semplice configurazione consiste nel verificare se la porta 3306 dei server e' in LISTEN. Tale configurazione del load balancer con MySQL e' adatta solo alle architetture piu' semplici perche' non copre tutte le possibili casistiche:
E' quindi necessario implementare una logica che tenga conto dello stato della base dati per istruire correttamente il load balancer.
In questa pagina illustriamo una semplice tecnica, basata sul demone xinetd, per produrre una pagina web sul DB server che indica se il database e' disponibile o meno. In questo modo la verifica da effettuare sul load balancer e' molto semplice: se la pagina restituisce OK la base dati puo' essere contattata!
Su CentOS 7 l'istallazione e l'avvio del servizio xinetd e' banale:
Ora possiamo effettuare la configurazione del nuovo servizio. Nel file /etc/xinetd.d/mysql_check impostiamo la configurazione:
# default: on # description: check to see if the node is a viable routing candidate service mysql_check { disable = no id = mysql-stream type = unlisted wait = no socket_type = stream flags = REUSE socket_type = stream port = 6446 wait = no user = mysql server = /var/lib/mysql-files/mysql_check.sh group = mysql server_args = NONE log_on_failure += USERID }
Non e' obbligatorio ma e' comunque educato dichiarare le porte utilizzate nel file /etc/services:
mysql_check 6446/tcp # MySQL Availability Check
Il cuore del controllo e' contenuto in questo script shell da riportare nel file /var/lib/mysql-files/mysql_check.sh:
#!/bin/bash M_USER=check_db M_PASS="Check.X00" M_HOST=localhost M_PORT=3306 # Simple check (can connect to MySQL) M_CHECK=`mysql -nsLNE --connect-timeout=5 --host=$M_HOST --port=$M_PORT --user="$M_USER" --password="$M_PASS" -e 'SELECT "OK" ' 2>/dev/null | grep -v '*'` if [ "$M_CHECK" == "OK" ] then # Member is a candidate ==> return HTTP 200 echo -en "HTTP/1.1 200 OK\r\n" echo -en "Content-Type: text/plain\r\n" echo -en "Connection: close\r\n" echo -en "Content-Length: 57\r\n" echo -en "\r\n" echo -en "Database Server is OK.\r\n" exit 0 else # Member is NOT a candidate ==> return HTTP 503 echo -en "HTTP/1.1 503 Service Unavailable\r\n" echo -en "Content-Type: text/plain\r\n" echo -en "Connection: close\r\n" echo -en "Content-Length: 61\r\n" echo -en "\r\n" echo -en "Database Server is not in a valid state.\r\n" exit 1 fi
Naturalmente va creato uno specifico utente sul DB oppure va utilizzata un'utenza attiva.
Con il riavvio del demone la configurazione e' attiva:
Dovrebbe essere chiaro che la verifica si effettua con un banale telnet sulla porta 6446 oppure con un browser!
Nella configurazione del controllo e' stata utilizzata una verifica molto
semplice, basta riuscire ad eseguire su MySQL la query: SELECT "OK".
E' una verifica appena piu' sofisticata rispetto alla semplice apertura
della porta 3306... ma basta cambiare la query per implementare il controllo
desiderato.
Il controllo per verificare se la base dati e' in sola lettura (quando si vuole effettuare il load balancing tra i soli Slave):
SELECT "OK" from dual where @@global.read_only=1
E' analogo il controllo per verificare se la base dati e' in scrittura (quando si vuole effettuare una transazione sul Master):
SELECT "OK" from dual where @@global.read_only=0
Se invece l'esigenza e' quella di indirizzare le scrittura
nella configurazione single-primary della Group Replication:
La configurazione del load balancer dipende dal... load balancer!
Ecco un esempio per HAProxy (file /etc/haproxy/haproxy.cfg):
Le configurazioni ed i controlli possibili sono innumerevoli
e dipendono dall'architettura presente e dalle funzionalita' desiderate.
L'idea di utilizzare xinetd non e' mia
(cfr. articolo Matt Lord)
e non e' neanche recente
(articolo Unai Rodriguez)...
Pero' e' una buona idea lo stesso e non ho trovato una pagina analoga in italiano!
La scelta del load balancer presenta molteplici possibilita'
in termini di funzionalita', prestazioni, costi, ...
Un'alternativa all'utilizzo dei load balancer e'
MySQL Router
che tuttavia nella versione attuale [NdE 2.0] non ha funzionalita' per la gestione
dell'alta affidabilita' ne si integra con la group replication.
Breaking news!
Titolo: Controllo disponibilita' di MySQL con xinetd
frontend mysql-gr-front
bind *:3306
mode tcp
default_backend mysql-gr-back
backend mysql-gr-back
mode tcp
balance leastconn
option httpchk
server mysql1 192.168.1.92:3306 check port 6446 inter 1000 rise 1 fall 2
server mysql2 192.168.1.93:3306 check port 6446 inter 1000 rise 1 fall 2
server mysql3 192.168.1.94:3306 check port 6446 inter 1000 rise 1 fall 2
Ad esempio si puo' voler dare precedenza a DB server locali,
escludere i nodi che effettuano backup o sono in manutenzione, ...
e' semplice modificare la query di controllo eseguita da xinetd
o le politiche di bilanciamento configurate sul load balancer
per ottenere il risultato voluto.
Varie ed eventuali
Tra i moltissimi fornitori di load balancer Hardware:
F5 BIG-IP Local Traffic Manager (LTM),
Citrix NetScaler,
Cisco,
Radware,
Kemp,
Barracuda,
...
Tra i moltissimi fornitori di load balancer Software generici:
HAProxy (un altro esempio),
NGINX,
...
Ed infine i load balancer specifici per MySQL:
ProxySQL,
Max Scale,
...
Per completare il quadro si deve ricordare che praticamente tutti i fornitori HW
hanno anche una versione SW, che tutti i balancer SW possono
essere installati su appliance e che per fare bilanciamento
non e' necessario un load balancer
(lo fanno anche il DNS ed i DB driver ma non si possono controllare).
Disponibile oggi in CA [NdA 12 aprile 2017]
la nuova versione di
MySQL Router 2.1 con il supporto della Group Replication e della HA.
Livello: Esperto
Data:
1 Gennaio 2017
Versione: 1.0.1 - 12 Aprile 2017
Autore: mail [AT] meo.bogliolo.name