Mysql基于GTID的主主复制

环境:centos7.5 关闭selinux/firewalld
主库A:mysql-a.example.com 10.3.8.247
主库B:mysql-a.example.com 10.3.8.248
两台主机都要在/etc/hosts文件中添加:
10.3.8.247 mysql-a mysql-a.example.com
10.3.8.248 mysql-b mysql-b.example.com
禁用防火墙/selinux:
systemctl diable firewalld
sed -i ‘/^SELINUX=/s/enforcing/disabled/’ /etc/sysconfig/selinux
reboot

配置时间同步:
[root@mysql-a ~]# sed -i “s/centos/cn/” /etc/chrony.conf
[root@mysql-a ~]# systemctl restart chronyd
[root@mysql-b ~]# sed -i ‘1i\server mysql-a iburst prefer’ /etc/chrony.conf
[root@mysql-b ~]# systemctl restart chronyd

安装MySQL5.7:
wget http://mirrors.aliyun.com/repo/Centos-7.repo -P /etc/yum.repos.d/
rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
wget http://mirrors.ustc.edu.cn/mysql-ftp/Downloads/MySQL-5.7/mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
rpm -e mariadb-libs.x86_64 --nodeps
yum localinstall mysql-community-common-5.7.24-1.el7.x86_64.rpm -y
yum localinstall mysql-community-libs-5.7.24-1.el7.x86_64.rpm -y
yum localinstall mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm -y
yum localinstall mysql-community-client-5.7.24-1.el7.x86_64.rpm -y
yum localinstall mysql-community-server-5.7.24-1.el7.x86_64.rpm -y

systemctl enable mysqld
systemctl start mysqld
grep “password” /var/log/mysqld.log
mysqladmin -u用户名 -p’旧密码’ password 新密码
注意mysqld.log中的密码包含各种字符,需要用单引号括起来防止特殊字符解析成其它意义。

如果要将数据存放于指定目录,可如下设置:
mysqld --initialize --user=mysql --datadir=/data/mysql #新版的初始化方式
chown -R mysql:mysql /data/mysql
主库A
[root@mysql-a ~]# vim /etc/my.cnf

[mysqld]
server_id=247     #自定义,要与其它库不同
gtid_mode=ON      #开启gtid模块
enforce_gtid_consistency=true    #强制同步数据
log_bin=mysql-bin-247		#开启二进制日志
binlog_checksum = none
binlog_format = mixed
sync_binlog = 1		#有更新就立即写入硬盘,默认是0,操作系统自动定期写入硬盘
master_info_repository=TABLE 		#将主服务器信息存储在表中
relay_log_info_repository=TABLE 		#将中继日志信息存储在表中
auto_increment_increment=2    #步进值,1、3、5、7......一般有n台主MySQL就填n
auto_increment_offset=1       #起始值。一般填第n台主MySQL。此时为第一台主MySQL
slave_parallel_type=logical_clock  #MySQL5.7新增加的值,配置基于表的组提交并行复制,默认值为database(基于库进行多线程复制,MySQL5.6),建议改为logical_clock,提高复制的效率。

重启主库A
[root@mysql-a ~]# systemctl restart mysql

创建授权用户
[root@mysql-a ~]# mysql -uroot -pmySQL@789
mysql> GRANT replication slave,replication client ON . TO ‘rep-b’@‘10.3.8.248’ IDENTIFIED BY ‘Repl-B.248’;
mysql> GRANT replication slave,replication client ON . TO ‘rep-a’@‘10.3.8.247’ IDENTIFIED BY ‘Repl-A.247’;
mysql> flush privileges;
第一个帐号是从库B用来连接主库A的,第二个帐号是从库A用来连接主库B的。
主库B
[root@mysql-b ~]# vim /etc/my.cnf

[mysqld]
server_id=248		#自定义,要与其它库不同
gtid_mode=ON      #开启gtid模块
enforce_gtid_consistency=true    #强制同步数据
log_bin=mysql-bin-248		#开启二进制日志
binlog_checksum = none
binlog_format = mixed
sync_binlog = 1	
master_info_repository=TABLE
relay_log_info_repository=TABLE
auto_increment_increment=2   #步进值,2、4、6、8......一般有n台主MySQL就填n,
auto_increment_offset=2   #起始值。一般填第n台主MySQL。此时为第2台主MySQL
slave_parallel_type=logical_clock

重启主库B
[root@mysql-b ~]# systemctl restart mysql

双主复制实现思路:先配置主A从B,成功后再配置主B从A
进入B库:
[root@mysql-b ~]# mysql -uroot -pmySQL@789
mysql> CHANGE master TO
MASTER_HOST=‘10.3.8.247’, #主库A的ip
MASTER_USER=‘rep-b’, #授权复制用户
MASTER_PASSWORD=‘Repl-B.248’, #授权用户的密码
MASTER_AUTO_POSITION=1; #自动同步
mysql> start slave;
mysql> show slave status\G;
注意slave_IO_Running和slave_SQL_Running 必须为yes

进入A库:
[root@mysql-a ~]# mysql -uroot -pmySQL@789
mysql> CHANGE master TO
MASTER_HOST=‘10.3.8.248’, #主库B的ip
MASTER_USER=‘rep-a’, #授权复制用户
MASTER_PASSWORD=‘Repl-A.247’, #授权用户的密码
MASTER_AUTO_POSITION=1; #自动同步
mysql> start slave;
mysql> show slave status\G;
注意slave_IO_Running和slave_SQL_Running 必须为yes

高并发写的场景,慎用双主模式

关于binlog-do-db和binlog-ignore-db
binlog-do-db=CU //它是用于主从同步时,给master用的配置参数,来说明需要复制哪些库给从库
binlog-ignore-db=mysql //安全起见,无论如何不从主同步系统DB

关于replicate-do-db和replicate-ignore-db
replicate-do-db=CU //从主读取的库,在从库端设置
replicate-ignore-db=mysql //安全起见,无论如何不从主同步系统DB

关于log-slave-updates=1
1.从库只开启log-bin功能,不添加log-slave-updates参数,从库从主库复制的数据不会写入log-bin日志。
2.从库开启log-slave-updates参数后,从库从主库复制的数据会写入log-bin日志文件里。
3.直接向从库写入数据时,是会写入log-bin日志的。
4.一主一从时,不需要这个参数,而“主—从—从”级联复制时,中间的从库需要启动这个参数。
5.双主时,也不需要这个参数,但如果增加从库,则连接从库的主库同时是个中间库,要加这个参数。
6.MySQL5.7可以不启用此参数,5.7版本使用了gtid_executed表记录同步复制的信息,避免两次写入relay-log和binlog,降低了从库磁盘I/O

如果想切换为普通模式,必须在my.cnf里,同时在master和slave上注销掉以下参数:
gtid_mode = ON
enforce_gtid_consistency = 1
并且重启mysql进程才生效。在易用性上,MySQL5.7 GTID还是美中不足。
双主Keepalived
Keepalived有多种方式实现HA,比如lvs(TCP_CHECK)方式,track_script方式等,这里用track_script。
两台主机上安装keepalived及设置日志:
#yum install -y keepalived
#vi /etc/sysconfig/keepalived
#KEEPALIVED_OPTIONS="-D" //注释掉,修改成如下
KEEPALIVED_OPTIONS="-D -d -S 0"
#vi /etc/rsyslog.conf,新增加:
local0.* /var/log/keepalived.log
重启日志服务:
#systemctl restart rsyslog

主机mysql-a配置keepalived
[root@mysql-a keepalived]# cat keepalived.conf

global_defs {
   router_id mysql-a
}

vrrp_script chk_mysql
{	//这个{必须单独一行,否则脚本不会执行
    script "/etc/keepalived/mysql_chk.sh" 
    weight -10
    interval 2
    timeout 2
    fall 2
}
注意vrrp_script这一段必须在vrrp_instance段落之前,否则不会执行
注意interval和timeout的值,要考虑脚本的处理时间。interval的值小了会造成上一次脚本还没执行完又开始执行同样的脚本。timeout的值太小了可能脚本还没执行完就被判断超时失败。

vrrp_instance mysql {
    state BACKUP
    interface eth0
    virtual_router_id 99
    priority 100
    advert_int 1
nopreempt   //非抢占模式
    authentication {
        auth_type PASS
        auth_pass ABCD
    }
    virtual_ipaddress {
        10.3.8.249/24
    }
    track_script {
        chk_mysql
    }

    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
    notify_stop "/etc/keepalived/notify.sh stop"
}

检查脚本mysql_chk.sh
[root@mysql-a keepalived]# cat mysql_chk.sh

#!/bin/bash
#check if mysql is available return 0, otherwise return 1
GATEWAY=10.3.8.254
MYSQL_USER="root"
MYSQL_PWD="mySQL@789"
YM=$(date '+%Y-%m')
LOGFILE="/var/log/mysql-check-$YM.log"
DATE=$(date +"%F %T")

mysql_alive=$(ss -tnl | grep -w 3306 >/dev/null 2>&1; echo $?)
[ $mysql_alive -eq 1 ] && echo "$DATE: mysql is not alive." >> $LOGFILE && exit 1

PING=$(ping -c 1 -w 2 $GATEWAY >/dev/null; echo $?)
[ $PING -eq 1 ] && echo "$DATE: ping $GATEWAY FAILD !!" >> $LOGFILE && exit 1

DB_STATUS=$(mysql -u${MYSQL_USER} -p${MYSQL_PWD} -e "show slave status\G")
[ -z "$DB_STATUS" ] && echo "$DATE: To run 'show slave status' faild"  >> $LOGFILE && exit 1

RUNNING=$(echo "$DB_STATUS" | egrep 'Slave_SQL_Running:|Slave_IO_Running:')
COUNT=$(echo "$RUNNING" | grep -o 'Yes' | wc -l)
[ $COUNT -ne 2 ] && echo -e "$DATE: Replication Faild:\n $RUNNING" >> $LOGFILE

exit 0

对复制状态异常只写日志,不作其它处理,因为涉及的情况比较复杂,人工处理才安全。

Keepalived事件通知脚本
[root@mysql-a keepalived]# cat notify.sh

#!/bin/bash

sendmail (){
    subject="keepalived state is translated."
    content="`date +'%F %T'`: `hostname`'s state change to $1"
    echo $content | mail -s "$subject" [email protected]
}

case "$1" in
    master)
        sendmail master ;;
    backup)
        sendmail backup ;;
    fault)
        sendmail fault ;;
    stop)
        sendmail stop ;;
    *)
        echo "Usage:$0 master|backup|fault|stop";;
esac

赋予脚本执行权限:
[root@mysql-a keepalived]# chmod +x mysql_chk.sh notify.sh
[root@mysql-a keepalived]# systemctl start keepalived

主机mysql-b配置keepalived
[root@mysql-b ~]# cat /etc/keepalived/notify.sh
与主机mysql-a的notify.sh完全相同
[root@mysql-b ~]# cat /etc/keepalived/keepalived.conf

global_defs {
   router_id mysql-b
}
vrrp_instance mysql {
    state BACKUP
    interface eth0
    virtual_router_id 99
    priority 95
......其余不变,略......
}

[root@mysql-b ~]# cat /etc/keepalived/mysql_chk.sh

#!/bin/bash
#check if mysql is available return 0, otherwise shutdown keepalived 
#成功返回0,否则关闭keepalived

GATEWAY=10.3.8.254
MYSQL_USER="root"
MYSQL_PWD="mySQL@789"
YM=$(date '+%Y-%m')
LOGFILE="/var/log/mysql-check-$YM.log"
DATE=$(date +"%F %T")

mysql_alive=$(ss -tnl | grep -w 3306 >/dev/null 2>&1; echo $?)
if [ $mysql_alive -eq 1 ];then
    echo "$DATE: mysql is not alive,keepalived shutdown." >> $LOGFILE
    systemctl stop keepalived
fi

PING=$(ping -c 2 -w 2 $GATEWAY >/dev/null; echo $?)
if [ $PING -eq 1 ];then
    echo "$DATE: ping $GATEWAY FAILD !! keepalived shutdown." >> $LOGFILE
    systemctl stop keepalived
fi

DB_STATUS=$(mysql -u${MYSQL_USER} -p${MYSQL_PWD} -e "show slave status\G")
if [ -z "$DB_STATUS" ];then
    echo "$DATE: To run 'show slave status' faild,keepalived shutdown."  >> $LOGFILE
    systemctl stop keepalived
fi

RUNNING=$(echo "$DB_STATUS" | egrep 'Slave_SQL_Running:|Slave_IO_Running:')
COUNT=$(echo "$RUNNING" | grep -o 'Yes' | wc -l)
[ $COUNT -ne 2 ] && echo -e "$DATE: Replication Faild:\n $RUNNING" >> $LOGFILE

exit 0

[root@mysql-b ~]# systemctl start keepalived

在keepalived主节点配置了state BACKUP的条件下,keepalived备节点降级(95→85)后,低于主节点(100或90),不会发生VIP漂移(所以备节点配置weight -10没什么意义),也不会触发任何notify事件。想要发生VIP漂移,只有在mysql_chek.sh里停止keepalived服务。重启keepalived服务也不可取,因为会检测脚本会再次重启keepalived,陷入循环重启。

猜你喜欢

转载自blog.csdn.net/liuyuhui_gdtyj/article/details/85010725
今日推荐