Chi segue già da un pò i miei how-to sa come la penso, sono abbastanza fissato con la sicurezza dei sistemi e del dato, sicurezza che viene garantita con un certo livello di ridondanza dell’architettura.
Oggi vedremo come creare un semplice cluster di databases MySQL, ridondato tramite la funzione di master-replica dello stesso software.
Una premessa è obbligatoria: per fare un vero cluster di db mysql ridondato ci vogliono minimo 4 macchine, o quantominimo 3, anche se non è la via più canonica di fare un cluster con un numero dispari di macchine, questo perchè cosi si può garantire in ogni momento che tutte le macchine abbiano la macchina master di riferimento (capirete tra poco cosa sto dicendo), anche in caso di guasto di uno dei nodi del cluster, questa guida si rifà ad un cluster finto di sole due macchine per pura semplicità, resta sottinteso che per qualsiasi dubbio ci sono i commenti o il forum.
Le macchine:
Come già detto utilizzeremo due macchine per il cluster, è preferibile avere macchine con due schede di rete o con minimo una dual-port, in quanto vi consiglio di collegare le due macchine con un cavo cross via [[back-to-back]], per svariati motivi, velocità, sicurezza, stabilità; perchè in quella interfaccia verranno allineati i dati del database.
Riporto i dati delle macchine cosi come li ho usati su due macchine virtuali in ufficio, voi ovviamente utilizzate i dati che avete dalle vostre macchine.
Server1:
IP: 192.168.0.193
utente_replica: slave1
password_replica: slave1Server2:
IP:192.168.0.44
utente_replica: slave2
password_replica:slave2Preparazione macchine e software:
Do per scontato che abbiate già installato mysql-server e mysql-client sulle vostre macchine, procediamo quindi con una prima configurazione di di mysql, eliminando il listening solo su localhost, e mettendo mysql in ascolto su tutte le interfaccie:
Notare bene: tutte le operazioni verranno descritte una volta, ma sono da replicarsi anche sulla seconda macchina con i dovuti accorgimenti.
[...]
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address = 127.0.0.1
[...]commentata questa opzione riavviamo mysql, e dopo logghiamoci via mysql-client e diamo i permessi di replica all'utente della macchina slave:
Server1:
mysql -u root -p
grant replication slave on *.* to 'slave2'@'%' identified by 'slave2';
flush privileges;
quitOra come ora abbiamo il db solo su Server1, per garantire la replica dobbiamo creare un database vuoto sul Server2, in questo esempio effettueremo la replica di un database chiamato portalinux.
Server2:
mysql -u root -p
create database portalinux;
quitSet-up della replica:
Adesso la base è pronta, dobbiamo solo configurare i due mysql per attivare i processi di master/slave su entrambe le macchine, la prima parte comporta la modifica del file di configurazione /etc/mysql/my.cnf inserendo alcune opzioni, tra quelle che andremo ad inserire dobbiamo sapere che due fra tutte sono le più importanti:
auto_increment_increment: controlla il fattore di incremento, tra due incrementi successivi (è un bel gioco di parole)
auto_increment_offset: determina lo starting point del valore della colonna auto_increment, cioè il valore iniziale.ponendo di avere un cluster costituito da N nodi, la prima delle due opzioni avra un valore = N, nel nostro esempio quindi sarà uguale a 2.
La seconda opzione invece avrà un valore diverso da N, e diverso in ogni macchina, per comodità io ho utilizzato un valore in base all'ordine logico che ho voluto dare alle macchine; quindi sul Server1 avrà valore = 1, e naturalmente sul server2 avrà valore = 2.
Questi parametri vanno inseriti insieme ad altri che vediamo in seguito, dobbiamo fare attenzione che quello che andiamo ad inserire non sia già inserito commentato od addirittura già attivo, quindi occhio...
Server1:
##############################
##mysql replica
###############################
server-id = 1
replicate-same-server-id = 0
auto-increment-increment = 2
auto-increment-offset = 1
master-host = 192.168.0.44
master-user = slave1
master-password = slave1
master-connect-retry = 60
replicate-do-db = portalinux
log_bin = /var/log/mysql/mysql-bin.log
binlog-do-db = portalinux
relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index
expire_logs_days = 10
max_binlog_size = 500M
##############################Server2:
##############################
##mysql replica
###############################
server-id = 2
replicate-same-server-id = 0
auto-increment-increment = 2
auto-increment-offset = 2
master-host = 192.168.0.193
master-user = slave2
master-password = slave2
master-connect-retry = 60
replicate-do-db = portalinux
log_bin = /var/log/mysql/mysql-bin.log
binlog-do-db = portalinux
relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index
expire_logs_days = 10
max_binlog_size = 500M
##############################Import del db:
Adesso è il turno della seconda parte della configurazione, dobbiamo loggarci via CLI ai due mysql e fare alcune operazioni, questa volta scriverò le operazioni da fare su tutti e due i server, in quanto in questo punto del tutorial le cose da fare sono diverse:
Server1:
Dobbiamo innanzitutto bloccare la lettura alle tabelle del database, e poi esportarlo per poi effettuare a manina il primo allineamento tra le due macchine:
mysql -u root -p
use portalinux;
flush tables with read lock;
show master status;Con l'ultimo comando vediamo lo stato del processo master sulla macchina 1, l'output sarà di questo genere:
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000065 | 98 | portalinux | |
+------------------+----------+--------------+------------------+
1 row in set (0.01 sec)ok...segnamoci da parte questi dati, e non chiudiamo la shell di mysql, altrimenti il lock sulle tabelle verrà rimosso e dovremo ripetere l'operazione; con la seconda shell effettuiamo l'export del db per poi copiarlo via scp sul Server2:
mysqldump -u root -p portalinux > portalinux.sql
scp portalinux.sql root@192.168.0.44:~/finito l'scp possiamo chiudere la seconda shell sulla macchina e rimuovere il lock sulle tabelle:
mysql> unlock tables;
Server2
Sulla seconda macchina adesso dobbiamo importare il dump del db appena copiato, prima però dobbiamo stoppare il processo slave di mysql:
mysqladmin -u root -p stop-slave
mysql -u root -p portalinux < portalinux.sql
mysql -u root -p
use portalinux;
flush tables with read lock;
show master status;mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000060 | 28858 | portalinux | |
+------------------+----------+--------------+------------------+
1 row in set (0.01 sec)anche qui, dobbiamo segnare e tenere da parte per dopo queste informazioni, infine possiamo sbloccare le tabelle:
mysql> unlock tables;
Settaggio processi slave sulle macchine:
Bene, adesso siamo sicuri che tutti e due i server sanno di essere il nodo master del cluster, per ultimare la procedura dobbiamo anche fargli sapere che, contemporaneamente, devono anche essere slave rispetto all'altra macchina:
Server2:
mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.44',MASTER_USER='slave2', /
MASTER_PASSWORD='slave2',MASTER_LOG_FILE='mysql-bin.000065',MASTER_LOG_POS=98;
Query OK, 0 rows affected (0.07 sec)ecco a cosa ci servivano quei parametri che ci siamo segnati e tenuti da parte, in questo comando dobbiamo inserire ciò che Server1 ci ha restituito, e viceversa faremo appunto su Server1.
E' il momento della verità, dobbiamo vedere se tutto è a posto, possiamo innanzitutto far partire il processo slave e poi controllare se tutto va come deve andare:
start slave;
show slave status;mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.193
Master_User: slave2
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000065
Read_Master_Log_Pos: 209
Relay_Log_File: slave-relay.000003
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000065
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: portalinux
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 209
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)quello che ci interessa l'ho evidenziato in grassetto, Slave I/O Running e Slave SQL Running devono avere entrambi come valore yes, altrimenti qualcosa è andato storto. In tal caso diamo un occhiata al syslog, che ci è molto amico e ci dirà chiaramente cosa sta succedendo.
Una volta effettuata questa stessa operazione su Server1 abbiamo finito, e possiamo testare il tutto semplicemente eliminando/creando/rinominando/aggiornando una tabella del db, noteremo come all'istante la stessa operazione verrà effettuata anche sull'altra macchina.
Da notare che cosi come l'abbiamo impostato noi il processo e bivalente, cioè possiamo decidere di aggiornare indiscriminatamente su Server1 o su Server2, in quanto essendo entrambe sia master che slave rispetto l'altra, i cambiamenti verranno registrati in entrambi i sensi.
Buona replica
| |












mm adesso ho la situazione
mm adesso ho la situazione un pò più chiara, effettivamente adesso la latenza è abbastanza strana, il syslog delle macchine ti dice qualcosa?
come sono collegate le interfaccie di rete tra le due macchine? c’è uno switch in mezzo o sono in back-to-back?
ciao,
le due macchine sono
ciao,
le due macchine sono connesse con uno switch in FC. Non credo che il problema è nella connessione, perché a riavvio il server 1 replica subito sul server 2.
Ho fatto però qualche ricerca nel syslog e non ci sono informazioni utili, tranne un Warning che non ho capito (te lo scrivo dopo).
Ho riguardato la documentazione di MySQL ed ho visto che c’è un paramentro chiamanto "slave-net-timeout" che di default è settato a 3600 secondi. L’ho impostato a 60 secondi ed ora la replica avviene preticamente in modo immediato.
Impostando nuovamente il paramentro a 3600 e riprovando, in effetti impiega molto tempo (anche se mi sembra meno di 1 ora). Farò altre prove, ma forse la latenza era legata a questo…
Per quanto riguarda infine il warning nel syslog a cui facevo riferimento, è:
—————————————————–
[Warning] The syntax for replication startup options is deprecated and will be removed in MySQL 5.2. Please use ‘CHANGE MASTER’ instead.
—————————————————–
Secondo te a cosa fa riferimento? La "connessione" dello slave verso il master al momento della configurazione l’ho fatto con "CHANGE MASTER".
fai cosi, sulla macchina che
fai cosi, sulla macchina che tarda a replicarsi dai un "reset slave" e riconfigurala con change master to ecc ecc
ciao,
ma se riavvii uno dei
ciao,
ma se riavvii uno dei due nodi (es si spegne per qualche motivo), quando riparte lo slave che resta acceso riesce a sincronizzarsi automaticamente con il master che si riavvia?
certo la sincronizzazione è
certo la sincronizzazione è istantanea.
io ho fatto una prova per stressarlo un pò, uno script che inseriva un miliore di record all’interno di una tabella, a turno ho riavviato i due server un paio di volte durante l’inserimento in corso, a fine esperimento entrambe le tabelle avevano un milione di record
certo devi impostare l’ha in modo da non fare "respawnare" la macchina master quando torna su, nel senso che quando torna su, lo stato di ha della macchina deve rimanere slave altrimenti se si riprende tutto il traffico non riesce ad allinearsi in tempo.
capito…
Io ho fatto
capito…
Io ho fatto qualche test, ma la parte slave del server che resta acceso impiega un pò di tempo a capire che il nuovo file del binario del master è cambiato. Da controlli impiega almeno 1-2 minuti.
Hai riscontri in merito?
si è normale perchè mysql
si è normale perchè mysql quando viene (ri)avviato blocca la lettura su tutte le tabelle per effettuare un check di consistenza (se abiliti i log vedrai una marea di check table al riavvio), finiti i check sblocca le tabelle ed allora inizia il riallineamento.
da me ci impiega pochi secondi, ma dipende da tanti fattori, grandezza del db, prestazioni della macchina, velocità rete ecc ecc….cmq sia che ci impieghi 2 secondi che due minuti non importa perchè a fine check il riallineamento è automatico
grazie per la risposta.
grazie per la risposta. Volevo chiederti un’altra cosa, spero di non approfittare troppo
Poniamo che il master 1 si spenga e nel frattempo sul master 2 vengano inseriti 50 record. Prima che il master 1 riparta, si spegne anche il master 2… Al riavvio dei due server, il master 1 prenderà comunque i 50 record dal master 2, oppure dato che anche il master 2 è ripartito ed ha aggiornato il riferimento al file dei log binari i 50 record restano solo sul master 2?
bella domanda….alla quale
bella domanda….alla quale non so rispondere, a rigor di logica mi viene da dire che i 50 record vengano allineati.
però se pensi che ci sia un rischio del genere ti conviene puntare su un cluster "vero" con 4 macchine mysql…
a dire il vero era solo
a dire il vero era solo curiosità. Penso che sia una evenienza remota, magari poi faccio qualche prova.
Una cosa che mi lascia perplesso è il tanto (almeno 30 minuti, ma credo anche di più) che impiegano i due server a sincronizzarsi dopo lo spegnimento "bruto" di un server. Ho 5 DB per un totale di 120MB e mi sembra davvero molto il tempo che impiega. Anche l’hardware non è male… Hai qualche altro suggerimento per me? Posso ottimizzare/verificare qualcosa, oppure devo rassegnarmi a questi "tempi"?
Per quanto riguarda il cluster, fai riferimento a 4 macchine i replica, oppure un cluster ndb? OnLine non ho letto molti pareri positivi su questa soluzione.
grazie davvero per il tempo che mi stai dedicando.
faccio riferimento alle 4
faccio riferimento alle 4 macchine in replica come da documentazione mysql.
in effetti 30 minuti sono un pò troppi, i db per caso hanno un botto di tabelle al loro interno? quando riavvi mysql vedi errori nei file di log?
ciao,
ho riprovato ora ed
ciao,
ho riprovato ora ed impiega sempre circa 30 minuti. Le tabelle saranno in tutto 60-70, suddivise tra i vari DB.
Nei log non vedo errori, solo che ad un certo punto il server che ho riavviato scrive nel LOG:
————————————————————————
090131 18:24:11 148 Connect replication@10.10.10.1 on
148 Query SET NAMES utf8
148 Query SELECT UNIX_TIMESTAMP()
148 Query SHOW VARIABLES LIKE ‘SERVER_ID’
148 Query SHOW SLAVE HOSTS
148 Binlog Dump Log: ‘mysql-bin.000014′ Pos: 98
———————————————————————–
Sembra quasi che si connetta al server che è rimasto accesso e gli chieda a quale "dump log" fa riferimento. Il nuovo file binario sul server che è ripartito è mysql-bin.000015, mente quello che si vede ( ‘mysql-bin.000014′) era il file attivo prima che riavviassi il server. Anche se poi non vedo nulla nei log, probabilmente il server che ho riavviato segnala all’altro che il file binario a cui far riferimento non è più il ‘mysql-bin.000014′ ma il ‘mysql-bin.000015′
Nel log file del server che è rimasto acceso vedo pressoché nello stesso momento le query di insert che avevo lanciato sulla macchina che avevo riavviato, poco dopo il riavvio e null’altro che possa essere "utile".
Riepilogando:
- ho due master-master con ip 10.10.10.1 e 10.10.10.2
- sono sincronizzati e riavvio completamente il server 10.10.10.2
- prima del riavvio inserisco dei record sul 10.10.10.1
- al riavvio il server 10.10.10.2 "prende" i record che avevo inserito nel 10.10.10.1 subito dopo
- inserisco dei record sul 10.10.10.2 ma vengono replicati sul 10.10.10.1 solo dopo circa 30 minuti
Non capisco davvero da cosa possa dipendere questa "latenza".