MySQL репликация master-master + переключение IP alias
MySQL репликация master-master + переключение IP alias
Что получаем в итоге.
Два сервера. Один (главный) работает как обычный сервер mikbill плюс на нем запущена репликация (mariadb gtid), а также запущен алиас ip.
Второй сервер с установленным mikbill и скриптом, мониторящим по пингу первый сервер (тут возможны различные варианты, например на первом сервере можно добавить скрипт мониторящий службы(mysql) и выключающий ping в случае падения). В случае падения первого сервера на второй добавляется alias ip, который был на первом сервере(на этом ip висит админка, запросы radius), включается крон mikbill и он принимает на себя всю работу.
Когда первый сервер восстанавливается, то работа на него возвращается и синхронизируется с изменениями на втором сервере. Время переключения на тесте 10 секунд, можно пробовать меньше.
На обоих серверах настроена репликация master-master. Также используется параметр GTID, что из его описания сильно увеличивает устойчивость репликации.
Проверки.
Проверена работа при одновременном изменении данных в базах. В таком случае синхронизация происходит по логике где быстрее было изменение. (Тут теоретически возможен вариант с одновременной, активной работой серверов).
При остановки службы mysql и восстановлении синхронизация баз происходит.
При reboot проблем с синхронизацией не замечено.
Убийство сервиса mysql - синхронизация восстановилась при запуске.
Также настроена система полуавтоматической синхронизации баз и запуск репликации в случае рассинхронизации.
Можно добавить отправку сообщения в телеграмм в случае рассинхронизации.
Настройка.
Имеем два сервера
Master-1 - 192.168.10.100
Master-2 - 192.168.10.101
alias 192.168.10.103 (на первом жестко прописан, на втором alias будет добавляться скриптом)
alias 192.168.10.103 (на первом жестко прописан, на втором alias будет добавляться скриптом)
Master-1
my.cnf
[mariadb]
server-id = 1
[mariadb]
server-id = 1
log-bin-index = mysql-bin.index
log_bin = mysql-bin
binlog_do_db = mikbill
bind-address = 192.168.10.100
Создаем пользователя репликации на обоих серверах
grant replication slave on *.* to 'replication'@'%';
останавливаем крон
- service crond stop
смотрим позицию
- SHOW MASTER STATUS;
делаем резервную копию
Master-2
my.cnf[mariadb]
server-id = 2
log-bin-index = mysql-bin.index
log_bin = mysql-bin
binlog_do_db = mikbill
bind-address = 192.168.10.101
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO MASTER_HOST = '192.168.10.100', MASTER_USER = 'replication', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000008', MASTER_LOG_POS = 8029;
START SLAVE;
Теперь на Master-1
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO MASTER_HOST = '192.168.10.101', MASTER_USER = 'replication', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 5593;
Запускаем GTID
STOP SLAVE;
CHANGE MASTER TO MASTER_USE_GTID = current_pos;
START SLAVE;
STOP SLAVE;
CHANGE MASTER TO MASTER_USE_GTID = current_pos;
START SLAVE;
- mkdir /var/mikbill/custom_scripts/claster
- ln -s /var/mikbill/custom_scripts/claster /claster
- cd /var/mikbill/custom_scripts/claster
Делаем авторизацию по ключу
- nano ssh.sh
#!/bin/bash
REMOTE_HOST=172.18.0.11
PORT=22
ssh-keygen -t rsa
ssh-copy-id -i $HOME/.ssh/id_rsa.pub "-p $PORT $USER@$REMOTE_HOST"
ssh $USER@$REMOTE_HOST -p $PORT
- chmod +x ssh.sh
- nano upload_sql.sh
#!/bin/bash
REMOTEHOST="10.10.10.10"
ssh_user="mikbill"
HOME_DIR=$(cd $(dirname $0)&& pwd)
PATH_MIKBILL=/var/www/mikbill/admin/
service crond stop
service nginx stop
DB_USER=$(cat $PATH_MIKBILL'app/etc/config.xml'| grep username | awk '{ gsub("<username>"," "); print }' | awk '{ gsub("</username>"," "); print }' | awk '{print $1}')
DB_PASSWORD=$(cat $PATH_MIKBILL'app/etc/config.xml'| grep password | awk '{ gsub("<password>"," "); print }' | awk '{ gsub("</password>"," "); print }' | awk '{print $1}')
echo $DB_USER $DB_PASSWORD
rm -f $HOME_DIR/backup_mikbill.sql.gz
mysqldump --single-transaction -u $DB_USER -p$DB_PASSWORD mikbill | gzip > $HOME_DIR/backup_mikbill.sql.gz
scp backup_mikbill.sql.gz $ssh_user@$REMOTEHOST:/home/$ssh_user
service crond start
service nginx start
Cron на втором сервере отдельным файлом. Файл крона mikbill перемещаем в каталог с скриптами /var/mikbill/custom_scripts/claster/
*/1 * * * * root /var/mikbill/custom_scripts/claster/claster_cron.sh > /dev/null 2>&1
nano claster_cron.sh
#!/bin/bash
for (( i=0; i < 6; i++ ))
do
/var/mikbill/custom_scripts/claster/claster.sh
sleep 10
done
nano claster.sh
#!/bin/bash
MASTERHOST="192.168.10.100"
#log=/var/log/mikbill.log
#log=log
alias="eth1:0 192.168.10.103/29"
HOME_DIR=$(cd $(dirname $0)&& pwd)
log=HOME_DIR/log
cron=/etc/cron.d
mikbill_file="mikbill"
Master_enable () {
echo $cron/$mikbill_file
if [ -f "$cron/$mikbill_file" ]; then
echo "Файл существует, удаляем"
echo "$(date) Master is Up">>$log
rm -f $cron/$mikbill_file
/sbin/ifconfig $alias down
fi
}
Master_disable () {
if ! [ -f "$cron/$mikbill_file" ]; then
echo "$(date) Master is Down">>$log
ln -s $HOME_DIR/$mikbill_file $cron/$mikbill_file
/sbin/ifconfig $alias up
fi
}
count=$(ping -c 1 $MASTERHOST | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
echo $count
if [ $count -eq 0 ]; then
Master_disable
else
Master_enable
fi
*********Скрипты для быстрой синхронизации баз*********************************
Скрипт на первом сервере
#!/bin/bash
MYSQL_MASTER_HOST=192.168.10.100
MYSQL_USER=replication
MYSQL_PASS=PASS
MYSQL_USER_ROOT=root
MYSQL_PASS_ROOT=PASS
DB_NAME=mikbill
GET_QUERY (){
SQL=`mysql -D $DB_NAME -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT -e "$QUERY"`
}
/etc/init.d/crond stop
/etc/init.d/nginx stop
/etc/init.d/radiusd stop
#QUERY="FLUSH TABLES WITH READ LOCK;"
#GET_QUERY
#echo "FLUSH TABLES WITH READ LOCK;" | mysql -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT
read -n 1 -s -r -p "Press any key to continue"
FILE=`mysql -h $MYSQL_MASTER_HOST -u $MYSQL_USER -p$MYSQL_PASS -e 'show master status' | grep -v File | awk ' {print $1}'`
echo $FILE
POS=`mysql -h mysql -h $MYSQL_MASTER_HOST -u $MYSQL_USER -p$MYSQL_PASS -e 'show master status' | grep -v File | awk ' {print $2}'`
echo $POS
#QUERY="STOP SLAVE; RESET SLAVE; CHANGE MASTER TO MASTER_HOST = '$MYSQL_MASTER_HOST', MASTER_USER = '$MYSQL_USER', MASTER_PASSWORD = '$MYSQL_PASS', MASTER_LOG_FILE = '$FILE', MASTER_LOG_POS = $POS; CHANGE MASTER TO MASTER_USE_GTID = current_pos; START SLAVE;"
QUERY="STOP SLAVE; RESET SLAVE; CHANGE MASTER TO MASTER_HOST = '$MYSQL_MASTER_HOST', MASTER_USER = '$MYSQL_USER', MASTER_PASSWORD = '$MYSQL_PASS', MASTER_LOG_FILE = '$FILE', MASTER_LOG_POS = $POS; START SLAVE;"
GET_QUERY
QUERY="STOP SLAVE; CHANGE MASTER TO MASTER_USE_GTID = current_pos; START SLAVE;"
GET_QUERY
/etc/init.d/crond start
/etc/init.d/nginx start
/etc/init.d/radiusd start
#echo "UNLOCK TABLES;" | mysql -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT
#QUERY="UNLOCK TABLES;"
#GET_QUERY
*******************************************************************
Скрипт на втором сервере
#!/bin/bash
MYSQL_MASTER_HOST=192.168.10.100
MYSQL_SLAVE_HOST=192.168.10.101
MYSQL_USER=replication
MYSQL_PASS=PASS
MYSQL_USER_ROOT=root
MYSQL_PASS_ROOT=PASS
DB_NAME=mikbill
#ssh_login=ltrmikbill
#ssh ssh_login@$MYSQL_MASTER_HOST 'service crond stop'
GET_QUERY (){
SQL=`mysql -D $DB_NAME -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT -e "$QUERY"`
}
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
MYSQL_MASTER_CONN="-h${MYSQL_MASTER_HOST} ${MYSQL_CONN}"
MYSQL_SLAVE_CONN="-h${MYSQL_SLAVE_HOST} ${MYSQL_CONN}"
MYSQLDUMP_OPTIONS="$DB_NAME --master-data=1"
MYSQLDUMP_OPTIONS="${MYSQLDUMP_OPTIONS} --single-transaction"
MYSQLDUMP_OPTIONS="${MYSQLDUMP_OPTIONS} --flush-privileges"
MYSQLDUMP_OPTIONS="${MYSQLDUMP_OPTIONS} --skip-tz-utc"
RELOAD_FILE=MySQLData.sql
echo "STOP SLAVE;" > ${RELOAD_FILE}
#echo "MASTER_USE_GTID = current_pos" >> ${RELOAD_FILE}
echo "CHANGE MASTER TO master_host='${MYSQL_MASTER_HOST}'," >> ${RELOAD_FILE}
#echo "CHANGE MASTER TO MASTER_USE_GTID = current_pos" >> ${RELOAD_FILE}
#echo "MASTER_USE_GTID = current_pos" >> ${RELOAD_FILE}
echo "master_port=3306," >> ${RELOAD_FILE}
echo "master_user='${MYSQL_USER}'," >> ${RELOAD_FILE}
echo "master_password='${MYSQL_PASS}'," >> ${RELOAD_FILE}
FILE=`mysql -h $MYSQL_MASTER_HOST -u $MYSQL_USER -p$MYSQL_PASS -e 'show master status' | grep -v File | awk ' {print $1}'`
echo $FILE
POS=`mysql -h mysql -h $MYSQL_MASTER_HOST -u $MYSQL_USER -p$MYSQL_PASS -e 'show master status' | grep -v File | awk ' {print $2}'`
echo $POS
echo "master_log_file='$FILE'," >> ${RELOAD_FILE}
echo "master_log_pos=$POS;" >> ${RELOAD_FILE}
#echo "DROP DATABASE $DB_NAME;" | mysql -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT
#echo "CREATE DATABASE $DB_NAME;" | mysql -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT
mysqldump ${MYSQL_MASTER_CONN} ${MYSQLDUMP_OPTIONS} >> ${RELOAD_FILE}
#echo "CHANGE MASTER TO MASTER_USE_GTID = current_pos" >> ${RELOAD_FILE}
echo "START SLAVE;" >> ${RELOAD_FILE}
mysql -u $MYSQL_USER_ROOT -p$MYSQL_PASS_ROOT --default_character_set koi8r $DB_NAME < ${RELOAD_FILE}
read -n 1 -s -r -p "Press any key to continue"
QUERY="STOP SLAVE; CHANGE MASTER TO MASTER_USE_GTID = current_pos; START SLAVE;"
GET_QUERY
Комментарии
Отправить комментарий