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 будет добавляться скриптом)

Master-1

my.cnf
[mariadb]
server-id = 1
log-bin-index = mysql-bin.index
log_bin = mysql-bin
binlog_do_db = mikbill
bind-address = 192.168.10.100

Создаем пользователя репликации на обоих серверах

create user 'replication'@'%' identified by 'password';
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

/etc/init.d/mysql restart


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;

SHOW MASTER STATUS;

Теперь на 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;
START SLAVE;

SHOW SLAVE STATUS\G;

Запускаем GTID

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

Комментарии

Популярные сообщения из этого блога

mikbill расшифровка завершений сессий

Accel-ppp команды

Zabbix agent установка и настройка