La replica master/slave è un pattern noto tra i sistemi per la gestione dei dati, siano essi basati su database relazionali o meno (NoSQL). La caratteristica principale di tali sistemi è quella di avere una sorgente per la replicazione dei dati (il master) e uno o più punti su cui vengono replicati i dati (gli slave). Con questa configurazione il server master è accessibile in lettura e in scrittura, mentre i server slave sono abilitati esclusivamente alla lettura.
Nel momento in cui viene eseguita una query in scrittura sul master (INSERT
, UPDATE
, DELETE
, modifica della struttura di una tabella) le modifiche vengono importarte anche sugli slave che quindi rimarranno sincronizzati. Questo tipo di configurazione si presta bene a numerosi scenari reali come ad esempio:
- backup del database: sulla macchina secondaria avremo sempre una copia aggiornata (hot backup) della macchina primaria. Questo permette ad esempio di eseguire dei cold backup senza effettuare operazioni di lock su una macchina di produzione e quindi non interrompendone il funzionamento;
- operazioni intensive di analisi: se abbiamo la necessità di eseguire intense analisi sui dati potremmo voler evitare che queste interferiscano con il software installato su una macchina in produzione; in questo modo possiamo impostare un server slave dedicato all'analisi intensiva dei dati;
- load balancing: ogni macchina avrà tutto il necessario per l'esecuzione di un sito web, compresa una copia del database. In questo modo le query in lettura saranno eseguite in locale con prestazioni elevate, mentre per le query in scrittura sarà necessario usare il server primario. Un grosso vantaggio è la scalabilità che questo comporta, potendo aggiungere ulteriori macchine secondarie in base alle necessità di carico. In genere la macchina primaria è usata esclusivamente come server MySQL e non espone altri servizi;
- distribuzione geografica: vale lo stesso discorso del load balancing, ma le macchine sono distribuite in paesi diversi per avvicinarsi ai clienti. Ad esempio è possibile prevederne una in Europa, una negli Stati Uniti, una in Asia, e così via. Di contro le prestazioni in scrittura saranno rallentate dalla distanza tra i server, ma con una progettazione idonea anche questo è un problema superabile.
Replica Master/Slave su MySQL
In MySQL questo pattern è implementato tramite la copia di log tra master e slave effettuata usando un nuovo utente sul server master. Semplificando, quello che succede è questo:
- il server master aggiorna un file di log in locale per ogni modifica applicata ad un database abilitato per la replica;
- il server slave richiede tramite un utente impostato sul server master le modifiche dalla precedente posizione di sincronizzazione;
- il server slave applica le modifiche ricevute e aggiorna la posizione di sincronizzazione.
La scelta dei database da replicare dipende dalla configurazione del server master, ed è possibile decidere di replicare uno o più database. Questa modularità permette di ottenere le prestazioni migliori in base allo scenario che abbiamo intenzione di realizzare.
Configurare il server master
La prima cosa da fare è configurare MySQL sul server che prenderà il ruolo di master, modificando il file di configurazione: è necessario modificare le direttive già presenti perché riflettano la situazione illustrata di seguito, nonchè aggiungere alcune direttive non presenti. La replica master/slave è supportata anche da MariaDB e da PerconaDB, e teoricamente dovrebbe essere possibile ottenere la replica anche con una progettazione mista (ad esempio master con MySQL e slave con MariaDB) ma è consigliabile utilizzare una stessa versione su tutte le macchine.
Le versioni recenti di MySQL impostano di default l'indirizzo IP di ascolto sull'IP locale 127.0.0.1 per ragioni di sicurezza, impedendo l'accesso da remoto. Dato che la nostra intenzione è quella di spostare i dati dal server master al server slave è necessario che questi possano comunicare tramite un accesso esterno. Abbiamo due possibilità:
- configurare MySQL per mettersi in ascolto sull'indirizzo IP esterno, modificando la direttiva
bind-address
nel file di configurazione; - mantenere la configurazione attuale lasciando MySQL esclusivamente in ascolto sull'indirizzo IP locale, e avviare un tunnel SSH tra le due macchine.
La seconda possibilità è ottima dal punto di vista della sicurezza ma è più complessa da realizzare, per cui in questa fase vediamo come implementare la prima possibilità (approfondiremo l'altra più avanti nella guida). Quindi modifichiamo la direttiva bind-address
con il nostro indirizzo IP esterno o con l'IP 0.0.0.0 che imposta MySQL in ascolto su tutte le interfacce, interne e esterne.
A questo punto dobbiamo impostare la direttiva server-id
con un numero univoco per ogni macchina, che convenzionalmente per il master sarà uguale a 1. Con le direttive log_bin
e binlog_do_db
decidiamo rispettivamente dove salvare il file di log necessario alla replica, va bene la destinazione prevista di default nel file ma commentata, e quali database avviare alla replicazione. La direttiva binlod_do_db
può essere ripetuta più volte indicando i vari database che vogliamo replicare.
Questo esaurisce la configurazione minima da applicare al server master, il cui file my.cnf conterrà quindi queste direttive (non necessariamente con gli stessi valori mostrati di seguito):
bind-address = 0.0.0.0
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = database1
binlog_do_db = database2
binlog_do_db = database3
Creare l'utente abilitato alla replicazione
Modificato il file di configurazione, dopo aver riavviato il server MySQL, dobbiamo ancora creare l'utente necessario ai nostri scopi. Per questo colleghiamoci al server master con l'utente root tramite una shell o da remoto, ed eseguiamo la seguente query:
GRANT REPLICATION SLAVE ON *.* TO 'user_replica'@'%' IDENTIFIED BY 'password';
Ovviamente la query è personalizzabile, per cui al posto di user_replica possiamo scegliere il nome che preferiamo e che sarà usato da tutti i server che partecipano alla replica. Al posto di password, invece, inseriamo una password sicura dato che questo utente avrà accesso (remotamente) a tutti i dati.