MySQL MHA

目录

1、概念介绍

MHA 简介

MHA 工作原理

MHA 软件组成

2、前期准备

机器规划

SSH 免密登录

安装 MHA

3、搭建主从复制

动态加载半同步复制模块

配置 Master 节点

配置 Slave 节点

Master 节点查看半同步信息

4、配置 MHA

创建配置文件

检查 SSH 配置

检查整个主从复制情况

查看MHA Manager 的状态

启动 MHA Master 监控

关闭 MHA Master 监控

模拟故障监控

5、使用 VIP 配合 MHA

在 Master 上配置VIP

Manager 配置文件中启用脚本

编写 /usr/bin/master_ip_failover perl脚本

检查 SSH 配置

检查整个集群复制环境状况

开启 MHA Manager 监控

模拟故障——Master宕机


1、概念介绍
MHA 简介

官方介绍:https://code.google.com/p/mysql-master-ha/

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。

该软件由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。

在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.5开始的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。MHA 适合任何存储引擎, 只要能主从复制的存储引擎它都支持,不限于支持事物的 innodb 引擎。

MHA 工作原理

相对比其它HA软件,MHA的目的在于维持 MySQL Replication 中 Master 库的高可用性,其最大特点是可以修复多个Slave之间的差异日志,最终使所有Slave保持数据一致然后从中选择一个充当新的Master,并将其它Slave指向它

从宕机崩溃的master保存二进制日志事件(binlog events);

识别含有最新更新的slave;

应用差异的中继日志(relay log)到其他的slave;

应用从master保存的二进制日志事件(binlog events);

提升一个slave为新的master;

使其他的slave连接新的master进行复制;

MHA 软件组成

MHA软件由两部分组成,Manager工具包和Node工具包

Manager 工具包

masterha_manger

启动MHA

masterha_stop

停止MHA

masterha_check_status

检测当前MHA运行状态

masterha_check_ssh

检查MHA的SSH配置状况

masterha_check_repl

检查MySQL复制状况

masterha_master_monitor

检测master是否宕机

masterha_master_switch

控制故障转移(自动或者手动)

masterha_conf_host

添加或删除配置的server信息

Node 工具包:node 工具通常由MHA Manager的脚本触发,无需人为操作

save_binary_logs

保存和复制master的二进制日志

apply_diff_relay_logs

识别差异的中继日志事件并将其差异的事件应用于其他的slave

filter_mysqlbinlog

去除不必要的ROLLBACK事件(MHA已不再使用这个工具)

purge_relay_logs

清除中继日志(不会阻塞SQL线程)

注意:为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL 5.5的半同步复制。(不是必须)

2、前期准备
机器规划

主机名

IP

角色

功能

软件

node-01

192.168.137.101

HA-Manager

管理节点

manager、node

node-02

192.168.137.102

Master

主节点,写入

mha4msql-node

node-03

192.168.137.103

Slave

从节点,读取

mha4msql-node

node-04

192.168.137.104

Slave

从节点,读取

mha4msql-node

注意:所有机器都关闭防火墙和selinux、并且做时间同步ntpdate ntp1.aliyun.com

SSH 免密登录
# 配置主机清单
cat >> /etc/hosts <<EOF
192.168.137.101 node-01
192.168.137.102 node-02
192.168.137.103 node-03
192.168.137.104 node-04
EOF

# 生成ssh秘钥
ssh-keygen

# 根据所在主机不同将秘钥传递到其他3台主机
ssh-copy-id node-0?
ssh-copy-id node-0?
ssh-copy-id node-0?
安装 MHA

所有节点配置 epel扩展源:yum install -y epel-release

上传软件到 Manger管理节点,将node软件包拷贝到Master、Slave节点

for ip in 102 103 104;do scp /root/mha4mysql-node-0.57-0.el7.noarch.rpm 192.168.137.$ip:/root/;done

在所有节点上安装 mha4mysql-node 软件包 和 依赖环境

for ip in 101 102 103 104; do ssh 192.168.137.$ip "yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager --skip-broken --nogpgcheck;rpm -ivh mha4mysql-node-0.57-0.el7.noarch.rpm"; done

# 安装完成后会在/usr/bin/目录下生成以下脚本文件
 ll /usr/bin/{app*,filter*,purge*,save*}

在node-01 节点安装 MHA-Manager

# 安装MHA Manger依赖的perl模块
[root@node-01 ~] yum install -y  perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch \
perl-Parallel-ForkManager perl-Time-HiRes perl-ExtUtils-CBuilder \
perl-ExtUtils-MakeMaker perl-CPAN

# 安装MHA Manager软件包
rpm -ivh mha4mysql-manager-0.57-0.el7.noarch.rpm

# 安装完成后会在/usr/bin目录下面生成以下脚本文件
ll /usr/bin/masterha*

3、搭建主从复制
动态加载半同步复制模块

为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL的半同步复制。

mysql半同步插件是由谷歌提供,具体位置/usr/local/mysql/lib/plugin/下,一个是master用的semisync_master.so,一个是slave用的semisync_slave.so,下面我们就来具体配置一下。

# 查看插件位置
mysql>  show variables like "%plugin_dir%";

# 检查mysql是否支持动态载入模块
mysql> show variables like '%have_dynamic_loading%';

所有node节点(Master、Slave)安装半同步插件

# node-02、03、04 所有Node节点安装半同步插件
mysql -uroot -p123456  -e "install plugin rpl_semi_sync_master soname 'semisync_master.so';install plugin rpl_semi_sync_slave soname 'semisync_slave.so';"

# 检查node-02、03、04 Plugin是否已正确安装
mysql -uroot -p123456  -e "show plugins;" | grep rpl_semi_sync*

查看半同步相关信息

查看半同步相关信息
mysql -uroot -p123456  -e "show variables like '%rpl_semi_sync%';"

上图可以看到半同复制插件已经安装,只是还没有启用,所以是off

配置 Master 节点

配置my.cnf:vim /etc/my.cnf

[mysqld]
datadir=/var/lib/mysql
# 编译的时候指定的位置
socket=/usr/local/mysql/mysql.sock

server-id=1
log-bin=/data/mysql/log/mysql-bin
log-bin-index=/data/mysql/log/mysql-bin.index
binlog_format=mixed
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
relay_log_purge=0
relay-log=/data/mysql/log/relay-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
binlog-do-db=HA #可以被从服务器复制的库。二进制需要同步的数据库名 
log_slave_updates=1 #只有开启log_slave_updates,从库binlog才会记录主库同步的操作日志
---------------------------------------------------------------



# 创建二进制日志目录
mkdir -p /data/mysql/log
chown -R mysql:mysql /data/mysql
# 重启服务
systemctl restart mysqld

配置参数

解释

rpl_semi_sync_master_enabled=1

1表是启用,0表示关闭

rpl_semi_sync_master_timeout=10000

毫秒单位,该参数表示主服务器等待确认消息,10秒后,不再等待,变为异步方式。

创建需要同步的数据库

mysql -uroot -p123456
mysql> create database HA;
mysql> use HA;
mysql> create table testHA(id int,name varchar(20));
mysql> insert into testHA values(1,'tom1');

创建授权账号

mysql> create user slave@'192.168.137.%' identified with mysql_native_password by '123456';
mysql> grant replication slave on *.* to slave@'192.168.137.%';

mysql> create user root@'192.168.137.%' identified with mysql_native_password by '123456';
mysql> grant all privileges on *.* to root@'192.168.137.%';

mysql> flush privileges;	

查看Master 状态

mysql> show master status;

导出HA数据库到从服务器

 mysqldump -uroot -p123456 -B HA>HA.sql
 for ip in 103 104;do scp HA.sql root@192.168.137.$ip:/root/;done

配置 Slave 节点

此配置应用在 两个Slave节点 node-03、04

导入数据库:mysql -uroot -p123456 <HA.sql

编写配置文件:vim /etc/my.cnf

[mysqld]
datadir=/var/lib/mysql
# 编译的时候指定的位置
socket=/usr/local/mysql/mysql.sock

# Slave节点的server-id依次往后排
server-id=2
log-bin=/data/mysql/log/mysql-bin
log-bin-index=/data/mysql/log/mysql-bin.index
binlog_format=mixed
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
relay_log_purge=0
relay-log=/data/mysql/log/relay-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
binlog-do-db=HA
log_slave_updates=1 #只有开启log_slave_updates,从库binlog才会记录主库同步的操作日志
--------------------------------------------------------------



# 创建二进制日志目录
mkdir -p /data/mysql/log
chown -R mysql:mysql /data/mysql
# 重启服务
systemctl restart mysqld

创建授权账号

因为所有的从服务器都可能提升为主服务器,所以从服务器也需要创建同步账号。

mysql> create user slave@'192.168.137.%' identified with mysql_native_password by '123456';
mysql> grant replication slave on *.* to slave@'192.168.137.%';

mysql> create user root@'192.168.137.%' identified with mysql_native_password by '123456';
mysql> grant all privileges on *.* to root@'192.168.137.%';

mysql> flush privileges;	

建立主从关系

mysql> stop slave;
mysql> change master to master_host='192.168.137.102',master_user='slave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=157;
mysql> start slave;
mysql> show slave status\G;

两台slave服务器设置read_only

从库对外提供读服务,只所以没有写进配置文件,是因为slave随时会提升为master

mysql -uroot -p123456 -e 'set global read_only=1'
Master 节点查看半同步信息
# 查看半同步相关信息
mysql -uroot -p123456 -e "show variables like '%rpl_semi_sync%';"

# 查看半同步状态
mysql -uroot -p123456 -e "show status like '%rpl_semi_sync%';"

半同步状态参数

解释

Rpl_semi_sync_master_clients

显示有多少个从服务器配置为半同步复制模式

Rpl_semi_sync_master_status

显示主服务是异步复制模式还是半同步复制模式

rpl_semi_sync_master_net_avg_wait_time

事务进入等待队列后,到网络平均等待时间(即master 等待slave 回复的平均等待时间。单位毫秒.)

Rpl_semi_sync_master_tx_avg_wait_time

事务因开启 semi_sync ,平均需要额外等待的时间 (即master 花在每个事务上的平均等待时间)

Rpl_semi_sync_master_net_wait_time

master 总的等待时间

Rpl_semi_sync_master_no_times

master 关闭半同步复制的次数。

rpl_semi_sync_master_yes_tx

显示从服务器确认成功提交的数量 (即master成功接收到slave的回复的次数。)

rpl_semi_sync_master_no_tx

显示从服务器确认不成功提交的数量 (即master 等待超时的次数)

Rpl_semi_sync_master_tx_wait_time

master 花在所有事物上的等待时间

Rpl_semi_sync_master_net_waits

master 等待slave 回复的的总的等待次数。

Rpl_semi_sync_master_timefunc_failures

记录master调用类似 gettimeofday()等函数的失败次数

Rpl_semi_sync_master_tx_waits

master总的等待次数

Rpl_semi_sync_master_wait_sessions

当前有多少个session 因为slave 的回复而造成等待

4、配置 MHA
创建配置文件
# 创建MHA工作目录
mkdir -p /etc/masterha
mkdir -p /var/log/masterha/app1

# 编辑MHA配置文件
vim /etc/masterha/app1.cnf
[server default]
manager_workdir=/var/log/masterha/app1  
manager_log=/var/log/masterha/app1/manager.log
master_binlog_dir=/data/mysql/log
#master_ip_failover_script=/usr/bin/master_ip_failover
#master_ip_online_change_script=/usr/bin/master_ip_online_change

user=root
password=123456
ping_interval=1
remote_workdir=/tmp
repl_user=slave
repl_password=123456
report_script=/usr/local/send_report
shutdown_script=""
ssh_user=root

[server1]
hostname=192.168.137.102
port=3306

[server2]
hostname=192.168.137.103
port=3306

[server3]
hostname=192.168.137.104
port=3306

配置文件参数

说明

manager_workdir=/var/log/masterha/app1

设置manager的工作目录

manager_log=

/var/log/masterha/app1/manager.log

设置manager的日志

master_binlog_dir=/data/mysql/log

设置master 保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录,注:所有mysql的binlog文件路径都要与该路径一致。

master_ip_failover_script= /usr/bin/master_ip_failover

设置自动故障切换时候的脚本

master_ip_online_change_script=

/usr/bin/master_ip_online_change

设置手动切换时候的切换脚本

user=root

设置监控用户manager

password=123456

监控用户manager的密码

ping_interval=1

设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行failover

remote_workdir=/tmp

设置远端mysql在发生切换时binlog的保存位置

repl_user=slave

设置复制环境中的复制用户名

repl_password=123456

设置复制用户的密码

report_script=/usr/local/send_report

设置发生切换后发送的报警的脚本

shutdown_script=""

设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用)

ssh_user=root

设置ssh的登录用户名

candidate_master=1

设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave

check_repl_delay=0

默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

检查 SSH 配置

检查MHA Manger到所有MHA Node的SSH连接状态:

 masterha_check_ssh --conf=/etc/masterha/app1.cnf

注意:如果报错,请检查你所有节点是不是都配置了SSH免密登陆

检查整个主从复制情况
masterha_check_repl --conf=/etc/masterha/app1.cnf

# 这是因为之前健康检查报错,需要删除之前健康检查的文件
rm -rf /var/log/masterha/app1/app1.master_status.health

查看MHA Manager 的状态
 masterha_check_status --conf=/etc/masterha/app1.cnf

注意:如果正常,会显示"PING_OK",否则会显示"NOT_RUNNING",这代表MHA监控没有开启

启动 MHA Master 监控
# 开启MHA Manager监控
nohup masterha_manager --conf=/etc/masterha/app1.cnf \
--remove_dead_master_conf  --ignore_last_failover < /dev/null > \
/var/log/masterha/app1/manager.log 2>&1 &

启动参数

说明

--remove_dead_master_conf

该参数代表当发生主从切换后,老的主库的ip将会从配置文件中移除。

--manger_log

日志存放位置

--ignore_last_failover

在缺省情况下,如果MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover故障转移,该参数代表忽略上次MHA触发切换产生的文件。默认情况下,MHA发生切换后会在日志目录,也就是上面设置的/data产生app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后删除该文件,为了方便,这里设置为--ignore_last_failover。

# 再次查看MHA Manager监控
masterha_check_status --conf=/etc/masterha/app1.cnf

# 查看启动日志
tail -20 /var/log/masterha/app1/manager.log

"Ping(SELECT) succeeded, waiting until MySQL doesn't respond.."说明整个系统已经开始监控了

关闭 MHA Master 监控
masterha_stop --conf=/etc/masterha/app1.cnf

模拟故障监控
# 开启监控
nohup masterha_manager --conf=/etc/masterha/app1.cnf \
--remove_dead_master_conf  --ignore_last_failover < /dev/null > \
/var/log/masterha/app1/manager.log 2>&1 &

打开新窗口观察日志:tail -0f /var/log/masterha/app1/manager.log

模拟主库挂掉:systemctl stop mysqld

登录node-04查看状态

查看node-03主从状态

mysql -uroot -p123456 -e "show processlist\G;"

发现只剩下node-04 的slave,MHA把原先的master(cong11)踢掉了

5、使用 VIP 配合 MHA

使用VIP 可以实现mysql master服务器的高可用。

vip配置可以采用两种方式,一种通过keepalived的方式管理虚拟ip的浮动;另外一种通过脚本方式启动虚拟ip的方式(即不需要keepalived或者heartbeat类似的软件)。

为了防止脑裂发生,推荐生产环境采用脚本的方式来管理虚拟ip,而不是使用keepalived来完成。

在 Master 上配置VIP

实验环境已恢复到 node-02 是主,03、04为从

ifconfig ens33:1  192.168.137.88 netmask 255.255.255.0 up
ifconfig ens33:1

Manager 配置文件中启用脚本
vim /etc/masterha/app1.cnf
[server default]
manager_workdir=/var/log/masterha/app1  
manager_log=/var/log/masterha/app1/manager.log
master_binlog_dir=/data/mysql/log
master_ip_failover_script=/usr/bin/master_ip_failover
#master_ip_online_change_script=/usr/bin/master_ip_online_change

user=root
password=123456
ping_interval=1
remote_workdir=/tmp
repl_user=slave
repl_password=123456
report_script=/usr/local/send_report
shutdown_script=""
ssh_user=root

[server1]
hostname=192.168.137.102
port=3306

[server2]
hostname=192.168.137.103
port=3306

[server3]
hostname=192.168.137.104
port=3306
编写 /usr/bin/master_ip_failover perl脚本

注意

  • 一定要删除此脚本文件里面的空行
  • 使用的vip是192.168.137.88/24
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
    $command,          $ssh_user,        $orig_master_host, $orig_master_ip,
    $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port
);
my $vip = '192.168.137.88/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";
GetOptions(
    'command=s'          => \$command,
    'ssh_user=s'         => \$ssh_user,
    'orig_master_host=s' => \$orig_master_host,
    'orig_master_ip=s'   => \$orig_master_ip,
    'orig_master_port=i' => \$orig_master_port,
    'new_master_host=s'  => \$new_master_host,
    'new_master_ip=s'    => \$new_master_ip,
    'new_master_port=i'  => \$new_master_port,
);
exit &main();
sub main {
    print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
    if ( $command eq "stop" || $command eq "stopssh" ) {
        my $exit_code = 1;
        eval {
            print "Disabling the VIP on old master: $orig_master_host \n";
            &stop_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn "Got Error: $@\n";
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "start" ) {
        my $exit_code = 10;
        eval {
            print "Enabling the VIP - $vip on the new master - $new_master_host \n";
            &start_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn $@;
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "status" ) {
        print "Checking the Status of the script.. OK \n";
        #`ssh $ssh_user\@cluster1 \" $ssh_start_vip \"`;
        exit 0;
    }
    else {
        &usage();
        exit 1;
    }
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
    print
    "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
chmod +x /usr/bin/master_ip_failover
检查 SSH 配置
masterha_check_ssh --conf=/etc/masterha/app1.cnf

检查整个集群复制环境状况

需要删除之前健康检查的文件

rm -rf /var/log/masterha/app1/app1.master_status.health
masterha_check_repl --conf=/etc/masterha/app1.cnf

开启 MHA Manager 监控
nohup masterha_manager --conf=/etc/masterha/app1.cnf \
--remove_dead_master_conf  --ignore_last_failover < /dev/null > \
/var/log/masterha/app1/manager.log 2>&1 &

# 查看MHA Manager监控是否正常
masterha_check_status --conf=/etc/masterha/app1.cnf

模拟故障——Master宕机
# 打开新窗口观察日志
tail -0f /var/log/masterha/app1/manager.log

# 关闭mysql主服务器
systemctl stop mysqld

# 在node-04(slave)查看主是否切换成功
mysql -uroot -p123456 -e "show slave status\G"

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值