MySQL multi master replikacija

Iš Žinynas.
21:34, 28 sausio 2017 versija, sukurta \dev\null (Aptarimas | indėlis) (sunkumų išvengimas)
(skirt) ← Ankstesnė versija | Dabartinė versija (skirt) | Vėlesnė versija → (skirt)
Jump to navigation Jump to search

Strategija padaryti du identiškus MySQL serverius, pasinaudojant MySQL multi master replikacija. Techniškai tai du serveriai veikiantys kaip Master > Slave ir atvirkščiai. Kiekvienas jų yra tiek Master tiek Slave, ir taip sukuriamas atbulinis duomenų sinchronizavimo mechanizmas užtikrinantis 100% replikaciją. Taip pat šiame straipsnyje aprašomos galimai iškylančios problemos bei jų sprendimas, kad replikacija būtų kuo stabilesnė.

Naudosime du serverius:

  • node1 - Y.Y.Y.Y
  • node2 - X.X.X.X

Pasiruošimas[keisti]

Pirmaiusia reikėtų žinoti jog prieš pradedant visą replikavimo procesą reikia perkopijuoti produkcinės DB duomenis į Slave serverį, tai galima padaryti paprastu mysqldump, arba jeigu versijos yra identiškos tiesiog saugiu sftp ryšiu perkelti MySQL failus (/var/lib/mysql) į Slave serverį. Pastaruoju atveju turite išjungti Master MySQL serverį, kad saugiai tai padaryti, išjungti trumpam vistiek reiks, dėl MySQL konfigūracijos keitimo. Bet jeigu manote, kad kopijuojamų duomenų yra perdaug 10-50GB> tuomet galite viską dumpinti į didelį sql'ą. Sukišti į Slave serverį, kol pirmajį Master'į laikysite su užlokintą nuo pakeitimų (su įjungtu binary logu).

mysql> FLUSH TABLES WITH READ LOCK;

Persikopijavus ir paleidus Slave serverį, galima daryti "quit" pastarojoje sesijoje, ir lentelės atsirakins.

Master configas (buvęs productionas)[keisti]

/etc/mysql/mysql.conf.d/mysqld.cnf Atkreipkite dėmesį į paryškintas eilutes

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0
[mysqld]
# * Basic Settings
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address = 0.0.0.0
# * Fine Tuning
key_buffer_size         = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover-options  = BACKUP
query_cache_limit       = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
server-id               = 1
binlog_format = mixed
log_bin                 = /var/log/mysql/mysql-bin.log
expire_logs_days        = 10
max_binlog_size=10G
# keli hackai padesiantys lengviau replikuoti mysql
innodb_flush_log_at_trx_commit=1
sync_binlog=1
slave_exec_mode=IDEMPOTENT
relay_log_info_repository=TABLE

Po konfigūracijos pakeitimo perkrauname mysql:

service mysql restart

Kitas master configas (naujasis slave)[keisti]

/etc/mysql/mysql.conf.d/mysqld.cnf

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0
[mysqld]
# * Basic Settings
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address            = 0.0.0.0
# * Fine Tuning
key_buffer_size         = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover-options  = BACKUP
# * Query Cache Configuration
query_cache_limit       = 1M
query_cache_size        = 16M
# * Logging and Replication
general_log_file        = /var/log/mysql/mysql.log
general_log             = 1
log_error = /var/log/mysql/error.log
server-id               = 2
binlog_format = mixed
log_bin                 = /var/log/mysql/mysql-bin.log
max_binlog_size=10G
expire_logs_days        = 10
relay-log=mysqld-relay-bin
report-host=node1
slave_exec_mode=IDEMPOTENT
relay_log_info_repository=TABLE

Po konfigūracijos pakeitimo perkrauname mysql:

service mysql restart

Replikacija[keisti]

Pirmajame serveryje pasileidžiame mysql klienta (pasijungiame kaip root), antrajame taip pat, iš pirmojo pažiūrime master status:

SHOW MASTER STATUS;

Duodame leidimą replikacijai:

grant replication slave on *.* to 'repl'@'Y.Y.Y.Y' identified by 'SLAPTAŽODIS‘;

Antrajame serveryje rašome:

change master to master_host = 'X.X.X.X', master_user='repl', master_password='SLAPTAŽODIS', master_log_file='mysql-bin.000005', master_log_pos=769; 

Butinai užrašome tikslų master log ir log pos iš pirmojo serverio master statuso (nuo tos vietos jis pradės replikuotis), paleidžiame slave

start slave;

Taip pat leidžiame prėima pirmajam serveriui būti šito serverio slave'u:

grant replication slave on *.* to 'repl2’@’X.X.X.X' identified by 'SLAPTAŽODIS‘;

Taip pat pažiūrime master status'ą

mysql> show master status;
+------------------+-----------+--------------+------------------+-------------------+
| File             | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 254 |              |                  |                   |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

Pirmajame serveryje darome atgalinę replikaciją (užrašydami antrojo serverio master statuso binary failą bei jo poziciją:

change master to master_host = 'Y.Y.Y.Y', master_user='repl2', master_password='SLAPTAŽODIS', master_log_file='mysql-bin.000002', master_log_pos=254; 
start slave;

Replikacija turetų pradėti vykti, jeigu abiejuose serveriuose matome (parašius show slave status\G;)

 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes

Jeigu nepavyko, kartojame ir būtinai žiūrime logą /var/log/mysql/error.log

Laikui bėgant problemos dėl incremental ID'u bei kitų bėdų[keisti]

Nors su šiais konfigais turėtume to išvengti bet dėl visa pikta, kas valandą ant crontab'o galime užkabinti šį scriptą kuris išspręs problemas bent jau kol ateis adminas:

#/bin/bash
mysql_user=root
mysql_host=localhost
mysql_port=3306
mysql_socket=/var/run/mysqld/mysqld.sock

cmd=mysql
[ -n "$mysql_host"  ] && cmd="$cmd --host=$mysql_host"
[ -n "$mysql_port"  ] && cmd="$cmd --port=$mysql_port"
[ -n "$mysql_socket"  ] && cmd="$cmd --socket=$mysql_socket"
[ -n "$mysql_user"  ] && cmd="$cmd --user=$mysql_user"
#[ -n "$mysql_pass"  ] && cmd="$cmd --password=$mysql_pass"
#echo $cmd
while(true);
do
Last_SQL_Error=`$cmd -e "show slave status\G" | grep "Last_SQL_Error:" | awk 'BEGIN{FS=":"}{print $2}' | tr -d ' '`
#Last_SQL_Error=""
if [ -z "$Last_SQL_Error" ]; then
break
fi
Master_UUID=`$cmd -e "show slave status\G" | grep "Master_UUID" | awk 'BEGIN{FS=":"}{print $2}'`
Executed_Gtid_Set=`$cmd -e "show slave status\G" | grep "Executed_Gtid_Set" | grep $Master_UUID  | awk 'BEGIN{FS=" "}{print $2}'`
Executed_id_Last=`echo $Executed_Gtid_Set |  awk 'BEGIN{FS=":"}{print $NF}' |  awk 'BEGIN{FS="-"}{print $2}'`
Executed_Gtid_Last=${Master_UUID}:${Executed_id_Last}
Executed_id_Next=`echo $Executed_id_Last + 1 | bc`
GTID_NEXT=${Master_UUID}:${Executed_id_Next}
$cmd << EOF
stop slave;
SET GTID_NEXT='$GTID_NEXT';
BEGIN;
COMMIT;
SET GTID_NEXT='AUTOMATIC';
start slave;
EOF
echo $Last_SQL_Error
echo $Executed_Gtid_Set
echo $GTID_NEXT
sleep 1
done

Problemos[keisti]

Jai iškyla problemų ar sutrinka replikacija ir reikia ją perkrauti pasiskaitom čia kaip išvengti sunkumų.

Kiti dalykai[keisti]