共计 29140 个字符,预计需要花费 73 分钟才能阅读完成。
MHA(Master HighAvailability)目前在 MySQL 高可用方面是一个相对成熟的解决方案,它由日本 DeNA 公司 youshimaton(现就职于 Facebook 公司)开发,是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。在 MySQL 故障切换过程中,MHA 能做到在 0~30 秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA 能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA里有两个角色一个是 MHA Node(数据节点)另 一个是MHA Manager(管理节点)。
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 服务器上,因此可以保证所有节点的数据一致性。
注:从 MySQL5.5 开始,MySQL以插件的形式支持半同步复制。如何理解半同步呢?首先我们来看看异步,全同步的概念:
异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果 crash 掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会受到严重的影响。
半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到 relay log 中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个 TCP/IP 往返的时间。所以,半同步复制最好在低延时的网络中使用。
下面来看看半同步复制的原理图:
总结:异步与半同步异同
默认情况下 MySQL 的复制是异步的,Master上所有的更新操作写入 Binlog 之后并不确保所有的更新都被复制到 Slave 之上。异步操作虽然效率高,但是在 Master/Slave 出现问题的时候,存在很高数据不同步的风险,甚至可能丢失数据。
MySQL5.5引入半同步复制功能的目的是为了保证在 master 出问题的时候,至少有一台 Slave 的数据是完整的。在超时的情况下也可以临时转入异步复制,保障业务的正常使用,直到一台 salve 追赶上之后,继续切换到半同步模式。
工作原理:
相较于其它 HA 软件,MHA的目的在于维持 MySQL Replication 中Master库的高可用性,其最大特点是可以修复多个 Slave 之间的差异日志,最终使所有 Slave 保持数据一致,然后从中选择一个充当新的 Master,并将其它Slave 指向它。
–从宕机崩溃的 master 保存二进制日志事件(binlogevents)。
–识别含有最新更新的slave。
–应用差异的中继日志 (relay log) 到其它slave。
–应用从 master 保存的二进制日志事件(binlogevents)。
–提升一个 slave 为新master。
–使其它的 slave 连接新的 master 进行复制。
目前 MHA 主要支持一主多从的架构,要搭建 MHA, 要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器。
部署环境如下:
角色 | Ip | 主机名 | os |
master | 192.168.137.134 | master | CentOS 6.5 x86_64 |
Candidate | 192.168.137.130 | Candidate | |
slave+manage | 192.168.137.146 | slave |
其中 master 对外提供写服务,Candidate 为备选 master,管理节点放在纯 slave 机器上。master 一旦宕机,Candidate 提升为主库
一、基础环境准备
1、在 3 台机器上配置 epel 源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
rpm -ivh http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
2、建立 ssh 无交互登录环境,
[root@master ~]#ssh-keygen -t rsa -P ”
chmod 600 .ssh/*
cat .ssh/id_rsa.pub >.ssh/authorized_keys
scp -p .ssh/id_rsa .ssh/authorized_keys 192.168.137.130:/root/.ssh
scp -p .ssh/id_rsa .ssh/authorized_keys 192.168.137.146:/root/.ssh
二、配置 mysql 半同步复制
注意:mysql 主从复制操作此处不做演示
master 授权:
grant replication slave,replication client on *.* to ‘repl’@’192.168.137.%’ identified by ‘123456’;
grant all on *.* to ‘mhauser’@’192.168.137.%’ identified by ‘123456’;
Candidate 授权:
grant replication slave,replication client on *.* to ‘repl’@’192.168.137.%’ identified by ‘123456’;
grant all on *.* to ‘mhauser’@’192.168.137.%’ identified by ‘123456’;
slave 授权:
grant all on *.* to ‘mhauser’@’192.168.137.%’ identified by ‘123456’;
如果用 mysql 默认的异步模式,当主库硬件损坏宕机造成的数据丢失,因此在配置 MHA 的同时建议配置成 MySQL 的半同步复制。
注:mysql 半同步插件是由谷歌提供,具体位置 /usr/local/mysql/lib/plugin/ 下,一个是 master 用的 semisync_master.so,一个是 slave 用的 semisync_slave.so,
mysql> show variables like ‘%plugin_dir%’;
+—————+——————————+
| Variable_name | Value |
+—————+——————————+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+—————+——————————+
1、分别在主从节点上安装相关的插件(master,Candidate,slave)
在 MySQL 上安装插件需要数据库支持动态载入。检查是否支持,用如下检测:
mysql> show variables like ‘%have_dynamic_loading%’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| have_dynamic_loading | YES
所有 mysql 数据库服务器,安装半同步插件(semisync_master.so,semisync_slave.so)
mysql> install plugin rpl_semi_sync_master soname ‘semisync_master.so’;
mysql> install plugin rpl_semi_sync_slave soname ‘semisync_slave.so’;
检查 Plugin 是否已正确安装:
mysql> show plugins;
或
mysql> select * from information_schema.plugins;
查看半同步相关信息
mysql> show variables like ‘%rpl_semi_sync%’;
rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32
上图可以看到半同复制插件已经安装,只是还没有启用,所以是 OFF
2、修改 my.cnf 文件,配置主从同步:
注:若主 MYSQL 服务器已经存在,只是后期才搭建从 MYSQL 服务器,在置配数据同步前应先将主 MYSQL 服务器的要同步的数据库拷贝到从 MYSQL 服务器上(如先在主 MYSQL 上备份数据库,再用备份在从 MYSQL 服务器上恢复)
master mysql 主机:
server-id = 1
log-bin=mysql-bin
binlog_format=mixed
log-bin-index=mysql-bin.index
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
relay_log_purge=0
relay-log= relay-bin
relay-log-index = relay-bin.index
注:
rpl_semi_sync_master_enabled=1 1 表是启用,0 表示关闭
rpl_semi_sync_master_timeout=10000:毫秒单位,该参数主服务器等待确认消息 10 秒后,不再等待,变为异步方式。
Candidate 主机:
server-id = 2
log-bin=mysql-bin
binlog_format=mixed
log-bin-index=mysql-bin.index
relay_log_purge=0
relay-log= relay-bin
relay-log-index = slave-relay-bin.index
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
注:relay_log_purge=0,禁止 SQL 线程在执行完一个 relay log 后自动将其删除,对于 MHA 场景下,对于某些滞后从库的恢复依赖于其他从库的 relaylog,因此采取禁用自动删除功能
Slave 主机:
Server-id = 3
log-bin = mysql-bin
relay-log = relay-bin
relay-log-index = slave-relay-bin.index
read_only = 1
rpl_semi_sync_slave_enabled = 1
查看半同步相关信息
mysql> show variables like ‘%rpl_semi_sync%’;
查看半同步状态:
mysql> show status like ‘%rpl_semi_sync%’;
| Rpl_semi_sync_master_clients | 2 |
重点关注的参数:
rpl_semi_sync_master_status:显示主服务是异步复制模式还是半同步复制模式
rpl_semi_sync_master_clients:显示有多少个从服务器配置为半同步复制模式
rpl_semi_sync_master_yes_tx:显示从服务器确认成功提交的数量
rpl_semi_sync_master_no_tx:显示从服务器确认不成功提交的数量
rpl_semi_sync_master_tx_avg_wait_time:事务因开启 semi_sync,平均需要额外等待的时间
rpl_semi_sync_master_net_avg_wait_time:事务进入等待队列后,到网络平均等待时间
三、配置 mysql-mha
所有 mysql 节点安装
rpm -ivh perl-DBD-MySQL-4.013-3.el6.i686.rpm [yum -y install perl-DBD-MySQL]
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
2. manage 需安装依赖的 perl 包
rpm -ivh perl-Config-Tiny-2.12-7.1.el6.noarch.rpm
rpm -ivh perl-DBD-MySQL-4.013-3.el6.i686.rpm [yum -y install perl-DBD-MySQL]
rpm -ivh compat-db43-4.3.29-15.el6.x86_64.rpm
rpm -ivh perl-Mail-Sender-0.8.16-3.el6.noarch.rpm
rpm -ivh perl-Parallel-ForkManager-0.7.9-1.el6.noarch.rpm
rpm -ivh perl-TimeDate-1.16-11.1.el6.noarch.rpm
rpm -ivh perl-MIME-Types-1.28-2.el6.noarch.rpm
rpm -ivh perl-MailTools-2.04-4.el6.noarch.rpm
rpm -ivh perl-Email-Date-Format-1.002-5.el6.noarch.rpm
rpm -ivh perl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm -ivh perl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm -ivh perl-MIME-Lite-3.027-2.el6.noarch.rpm
rpm -ivh perl-Mail-Sendmail-0.79-12.el6.noarch.rpm
rpm -ivh perl-Log-Dispatch-2.27-1.el6.noarch.rpm
yum install -y perl-Time-HiRes-1.9721-144.el6.x86_64
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
3. 配置 mha
配置文件位于管理节点,通常包括每一个 mysql server 的主机名,mysql 用户名,密码,工作目录等等。
mkdir /etc/masterha/
vim /etc/masterha/app1.cnf
[server default]
user=mhauser
password=123456
manager_workdir=/data/masterha/app1
manager_log=/data/masterha/app1/manager.log
remote_workdir=/data/masterha/app1
ssh_user=root
repl_user=repl
repl_password=123456
ping_interval=1
[server1]
hostname=192.168.137.134
port=3306
master_binlog_dir=/usr/local/mysql/data
candidate_master=1
[server2]
hostname=192.168.137.130
port=3306
master_binlog_dir=/usr/local/mysql/data
candidate_master=1
[server3]
hostname=192.168.137.146
port=3306
master_binlog_dir=/usr/local/mysql/data
no_master=1
配关配置项的解释:
manager_workdir=/masterha/app1// 设置 manager 的工作目录
manager_log=/masterha/app1/manager.log// 设置 manager 的日志
user=manager// 设置监控用户 manager
password=123456 // 监控用户 manager 的密码
ssh_user=root //ssh 连接用户
repl_user=mharep // 主从复制用户
repl_password=123.abc// 主从复制用户密码
ping_interval=1 // 设置监控主库,发送 ping 包的时间间隔,默认是 3 秒,尝试三次没有回应的时候自动进行 failover
master_binlog_dir=/usr/local/mysql/data // 设置 master 保存 binlog 的位置,以便 MHA 可以找到 master 的日志,我这里的也就是 mysql 的数据目录
candidate_master=1// 设置为候选 master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库。
检测各节点间 ssh 互信通信配置是否 ok
masterha_check_ssh –conf=/etc/masterha/app1.cnf
结果:All SSH connection tests passed successfully.
检测各节点间主从复制是否 ok
masterha_check_repl –conf=/etc/masterha/app1.cnf
结果:MySQL Replication Health is OK.
在验证时,若遇到这个错误:Can’t exec “mysqlbinlog” ……
解决方法是在所有服务器上执行:
ln -s /usr/local/mysql/bin/* /usr/local/bin/
启动 manager:
nohup /usr/bin/masterha_manager –conf=/etc/masterha/app1.cnf –remove_dead_master_conf –ignore_last_failover > /etc/masterha/manager.log 2>&1 &
–remove_dead_master_conf 为主从切换后,老的主库 IP 将会从配置文件中移除
–ignore_last_failover 忽略生成的切换完成文件,若不忽略,则 8 小时内无法再次切换
–ignore_fail_on_start
## 当有 slave 节点宕掉时,MHA 默认是启动不了的,加上此参数即使有节点宕掉也能启动 MHA,
关闭 MHA:
masterha_stop –conf=/etc/masterha/app1.cnf
查看 MHA 状态:
masterha_check_status –conf=/etc/masterha/app1.cnf
app1 (pid:45128) is running(0:PING_OK), master:192.168.137.134
4. 模拟故障转移
停掉 master,
/etc/init.d/mysqld stop
查看 MHA 日志 /data/masterha/app1/manager.log
—– Failover Report —–
app1: MySQL Master failover 192.168.137.134(192.168.137.134:3306) to 192.168.137.1
30(192.168.137.130:3306) succeeded
Master 192.168.137.134(192.168.137.134:3306) is down!
Check MHA Manager logs at zifuji:/data/masterha/app1/manager.log for details.
Started automated(non-interactive) failover.
The latest slave 192.168.137.130(192.168.137.130:3306) has all relay logs for reco
very.
Selected 192.168.137.130(192.168.137.130:3306) as a new master.
192.168.137.130(192.168.137.130:3306): OK: Applying all logs succeeded.
192.168.137.146(192.168.137.146:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
192.168.137.146(192.168.137.146:3306): OK: Applying all logs succeeded. Slave star
ted, replicating from 192.168.137.130(192.168.137.130:3306)
192.168.137.130(192.168.137.130:3306): Resetting slave info succeeded.
Master failover to 192.168.137.130(192.168.137.130:3306) completed successfully.
3. 查看 slave 复制状态
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.137.130
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2017-05/143691p2.htm
MHA Manager 端日常主要操作步骤
1)检查是否有下列文件,有则删除。
发生主从切换后,MHAmanager 服务会自动停掉,且在 manager_workdir(/data/masterha/app1/app1.failover.complete)目录下面生成文件 app1.failover.complete,若要启动 MHA,必须先确保无此文件)
find / -name ‘app1.failover.complete’
rm -f /data/masterha/app1/app1.failover.complete
2)检查 MHA 当前置:
# masterha_check_repl –conf=/etc/masterha/app1.cnf
3)启动 MHA:
#nohup masterha_manager –conf=/etc/masterha/app1.cnf&>/etc/masterha/manager.log &
当有 slave 节点宕掉时,默认是启动不了的,加上 –ignore_fail_on_start 即使有节点宕掉也能启动 MHA,如下:
#nohup masterha_manager –conf=/etc/masterha/app1.cnf –ignore_fail_on_start&>/etc/masterha/manager.log &
4)停止 MHA:masterha_stop –conf=/etc/masterha/app1.cnf
5)检查状态:
# masterha_check_status –conf=/etc/masterha/app1.cnf
6)检查日志:
#tail -f /etc/masterha/manager.log
7)主从切换, 原主库后续工作
vim /etc/my.cnf
read_only=ON
relay_log_purge = 0
MySQL> reset slave all;
mysql> reset master;
/etc/init.d/mysqld restart
mysql> CHANGE MASTER TO MASTER_HOST=’192.168.137.130′,MASTER_USER=’repl’,MASTER_PASSWORD=’123456′;
## 与新主库做主从复制
masterha_check_status –conf=/etc/masterha/app1.cnf
app1 (pid:45950) is running(0:PING_OK), master:192.168.137.130
注意:如果正常,会显示 ”PING_OK”,否则会显示 ”NOT_RUNNING”,这代表 MHA 监控没有开启。
定期删除中继日志
在配置主从复制中,slave 上设置了参数 relay_log_purge=0,所以 slave 节点需要定期删除中继日志,建议每个 slave 节点删除中继日志的时间错开。
corntab -e
0 5 * * * /usr/local/bin/purge_relay_logs – -user=root –password=pwd123 –port=3306 –disable_relay_log_purge >>/var/log/purge_relay.log 2>&1
5、配置 VIP
ip 配置可以采用两种方式,一种通过 keepalived 的方式管理虚拟 ip 的浮动;另外一种通过脚本方式启动虚拟 ip 的方式(即不需要 keepalived 或者 heartbeat 类似的软件)。
1、keepalived 方式管理虚拟 ip,keepalived 配置方法如下:
在 master 和 Candidate 主机上安装 keepalived
安装依赖包:
[root@master ~]# yum install openssl-devel libnfnetlink-devel libnfnetlink popt-devel kernel-devel -y
wget http://www.keepalived.org/software/keepalived-1.2.20.tar.gz
ln -s /usr/src/kernels/2.6.32-642.1.1.el6.x86_64 /usr/src/linux
tar -xzf keepalived-1.2.20.tar.gz;cd keepalived-1.2.20
./configure –prefix=/usr/local/keepalived;make && make install
ln -s /usr/local/keepalived/sbin/keepalived /usr/bin/keepalived
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived
mkdir /etc/keepalived
ln -s /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf
chmod 755 /etc/init.d/keepalived
chkconfig –add keepalived
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
service keepalived restart
echo 1 > /proc/sys/net/ipv4/ip_forward
修改 Keepalived 的配置文件(在 master 上配置)
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
guopeng@163.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id mysql-ha1
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.137.100
}
}
在候选 master(Candidate)上配置
[root@Candidate keepalived-1.2.20]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id mysql-ha2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.137.100
}
}
启动 keepalived 服务,在 master 上启动并查看日志
/etc/init.d/keepalived start
tail -f/var/log/messages
Aug 14 01:05:25 minion Keepalived_vrrp[39720]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.137.100
[root@master ~]# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:57:66:49 brd ff:ff:ff:ff:ff:ff
inet 192.168.137.134/24 brd 192.168.137.255 scope global eth0
inet 192.168.137.100/32 scope global eth0
inet6 fe80::20c:29ff:fe57:6649/64 scope link
valid_lft forever preferred_lft forever
[root@Candidate ~]# ip addr show dev eth0 ## 此时备选 master 上是没有虚拟 ip 的
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:a5:b4:85 brd ff:ff:ff:ff:ff:ff
inet 192.168.137.130/24 brd 192.168.137.255 scope global eth0
inet6 fe80::20c:29ff:fea5:b485/64 scope link
valid_lft forever preferred_lft forever
注意:
上面两台服务器的 keepalived 都设置为了 BACKUP 模式,在 keepalived 中 2 种模式,分别是 master->backup 模式和 backup->backup 模式。这两种模式有很大区别。在 master->backup 模式下,一旦主库宕机,虚拟 ip 会自动漂移到从库,当主库修复后,keepalived 启动后,还会把虚拟 ip 抢占过来,即使设置了非抢占模式(nopreempt)抢占 ip 的动作也会发生。在 backup->backup 模式下,当主库宕机后虚拟 ip 会自动漂移到从库上,当原主库恢复和 keepalived 服务启动后,并不会抢占新主的虚拟 ip,即使是优先级高于从库的优先级别,也不会发生抢占。为了减少 ip 漂移次数,通常是把修复好的主库当做新的备库。
2、MHA 引入 keepalived(MySQL 服务进程挂掉时通过 MHA 停止 keepalived):
要想把 keepalived 服务引入 MHA,我们只需要修改切换时触发的脚本文件 master_ip_failover 即可,在该脚本中添加在 master 发生宕机时对 keepalived 的处理。
编辑脚本 /scripts/master_ip_failover,修改后如下。
manager 编辑脚本文件:
mkdir /scripts
vim /scripts/master_ip_failover
#!/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.100’;
my $ssh_start_vip = “/etc/init.d/keepalived start”;
my $ssh_stop_vip = “/etc/init.d/keepalived stop”;
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”;
exit 0;
}
else {
&usage();
exit 1;
}
}
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 {
“Usage: master_ip_failover –command=start|stop|stopssh|status –orig_master_h
ost=host –orig_master_ip=ip –orig_master_port=port –new_master_host=host –new_
master_ip=ip –new_master_port=port\n”;
}
现在已经修改这个脚本了,接下来我们在 /etc/masterha/app1.cnf 中调用故障切换脚本
停止 MHA:
masterha_stop –conf=/etc/masterha/app1.cnf
在配置文件 /etc/masterha/app1.cnf 中启用下面的参数(在[server default 下面添加])
master_ip_failover_script=/scripts/master_ip_failover
启动 MHA:
#nohup masterha_manager –conf=/etc/masterha/app1.cnf &>/etc/masterha/manager.log &
检查状态:
]# masterha_check_status –conf=/etc/masterha/app1.cnf
app1 (pid:51284) is running(0:PING_OK), master:192.168.137.134
检查集群复制状态是否有报错:
]# masterha_check_repl –conf=/etc/masterha/app1.cnf
192.168.137.134(192.168.137.134:3306) (current master)
+–192.168.137.130(192.168.137.130:3306)
+–192.168.137.146(192.168.137.146:3306)
Tue May 9 14:40:57 2017 – [info] Checking replication health on 192.168.137.130..
Tue May 9 14:40:57 2017 – [info] ok.
Tue May 9 14:40:57 2017 – [info] Checking replication health on 192.168.137.146..
Tue May 9 14:40:57 2017 – [info] ok.
Tue May 9 14:40:57 2017 – [info] Checking master_ip_failover_script status:
Tue May 9 14:40:57 2017 – [info] /scripts/master_ip_failover –command=status –ssh_user=root –orig_master_host=192.168.137.134 –orig_master_ip=192.168.137.134 –orig_master_port=3306
IN SCRIPT TEST====/etc/init.d/keepalived stop==/etc/init.d/keepalived start===
Checking the Status of the script.. OK
Tue May 9 14:40:57 2017 – [info] OK.
Tue May 9 14:40:57 2017 – [warning] shutdown_script is not defined.
Tue May 9 14:40:57 2017 – [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.
注意: /scripts/master_ip_failover 添加或者修改的内容意思是当主库数据库发生故障时,会触发 MHA 切换,MHA Manager 会停掉主库上的 keepalived 服务,触发虚拟 ip 漂移到备选从库,从而完成切换。
当然可以在 keepalived 里面引入脚本,这个脚本监控 mysql 是否正常运行,如果不正常,则调用该脚本杀掉 keepalived 进程(参考 MySQL 高可用性 keepalived+mysql 双主)。
测试:在 master 上停掉 mysql
[root@master ~]# /etc/init.d/mysqld stop
Shutting down MySQL………… [OK]
到 slave(192.168.137.146)查看 slave 的状态:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.137.130
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
从上图可以看出 slave 指向了新的 master 服务器 192.168.137.130(在故障切换前指向的是 192.168.137.134)
查看 vip 绑定:
在 192.168.137.134 上查看 vip 绑定
[root@master ~]# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:57:66:49 brd ff:ff:ff:ff:ff:ff
inet 192.168.137.134/24 brd 192.168.137.255 scope global eth0
inet6 fe80::20c:29ff:fe57:6649/64 scope link
valid_lft forever preferred_lft forever
在 192.168.137.130 上查看 vip 绑定
[root@Candidate ~]# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:a5:b4:85 brd ff:ff:ff:ff:ff:ff
inet 192.168.137.130/24 brd 192.168.137.255 scope global eth0
inet 192.168.137.100/32 scope global eth0
从上面的显示结果可以看出 vip 地址漂移到了 192.168.137.130
主从切换后续工作:现在 Candidate 变成主,需对原 master 重新做只从复制操作
- 修复成从库
- 启动 keepalived
- rm -fr app1.failover.complete
- 启动 manager
3、通过脚本实现 VIP 切换
如果使用脚本管理 vip 的话,需要手动在 master 服务器上绑定一个 vip
]#/sbin/ifconfig eth0:0 192.168.137.100/24
vim /scripts/master_ip_failover
my $vip = ‘192.168.137.100/24’;
my $key = ‘0’;
my $ssh_start_vip = “/sbin/ifconfigeth0:$key $vip”;
my $ssh_stop_vip = “/sbin/ifconfigeth0:$key down”;
之后的操作同上述 keepalived 操作
为了防止脑裂发生,推荐生产环境采用脚本的方式来管理虚拟 ip,而不是使用 keepalived 来完成。到此为止,基本 MHA 集群已经配置完毕。
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-05/143691.htm
MHA(Master HighAvailability)目前在 MySQL 高可用方面是一个相对成熟的解决方案,它由日本 DeNA 公司 youshimaton(现就职于 Facebook 公司)开发,是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。在 MySQL 故障切换过程中,MHA 能做到在 0~30 秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA 能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA里有两个角色一个是 MHA Node(数据节点)另 一个是MHA Manager(管理节点)。
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 服务器上,因此可以保证所有节点的数据一致性。
注:从 MySQL5.5 开始,MySQL以插件的形式支持半同步复制。如何理解半同步呢?首先我们来看看异步,全同步的概念:
异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果 crash 掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会受到严重的影响。
半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到 relay log 中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个 TCP/IP 往返的时间。所以,半同步复制最好在低延时的网络中使用。
下面来看看半同步复制的原理图:
总结:异步与半同步异同
默认情况下 MySQL 的复制是异步的,Master上所有的更新操作写入 Binlog 之后并不确保所有的更新都被复制到 Slave 之上。异步操作虽然效率高,但是在 Master/Slave 出现问题的时候,存在很高数据不同步的风险,甚至可能丢失数据。
MySQL5.5引入半同步复制功能的目的是为了保证在 master 出问题的时候,至少有一台 Slave 的数据是完整的。在超时的情况下也可以临时转入异步复制,保障业务的正常使用,直到一台 salve 追赶上之后,继续切换到半同步模式。
工作原理:
相较于其它 HA 软件,MHA的目的在于维持 MySQL Replication 中Master库的高可用性,其最大特点是可以修复多个 Slave 之间的差异日志,最终使所有 Slave 保持数据一致,然后从中选择一个充当新的 Master,并将其它Slave 指向它。
–从宕机崩溃的 master 保存二进制日志事件(binlogevents)。
–识别含有最新更新的slave。
–应用差异的中继日志 (relay log) 到其它slave。
–应用从 master 保存的二进制日志事件(binlogevents)。
–提升一个 slave 为新master。
–使其它的 slave 连接新的 master 进行复制。
目前 MHA 主要支持一主多从的架构,要搭建 MHA, 要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器。
部署环境如下:
角色 | Ip | 主机名 | os |
master | 192.168.137.134 | master | CentOS 6.5 x86_64 |
Candidate | 192.168.137.130 | Candidate | |
slave+manage | 192.168.137.146 | slave |
其中 master 对外提供写服务,Candidate 为备选 master,管理节点放在纯 slave 机器上。master 一旦宕机,Candidate 提升为主库
一、基础环境准备
1、在 3 台机器上配置 epel 源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
rpm -ivh http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
2、建立 ssh 无交互登录环境,
[root@master ~]#ssh-keygen -t rsa -P ”
chmod 600 .ssh/*
cat .ssh/id_rsa.pub >.ssh/authorized_keys
scp -p .ssh/id_rsa .ssh/authorized_keys 192.168.137.130:/root/.ssh
scp -p .ssh/id_rsa .ssh/authorized_keys 192.168.137.146:/root/.ssh
二、配置 mysql 半同步复制
注意:mysql 主从复制操作此处不做演示
master 授权:
grant replication slave,replication client on *.* to ‘repl’@’192.168.137.%’ identified by ‘123456’;
grant all on *.* to ‘mhauser’@’192.168.137.%’ identified by ‘123456’;
Candidate 授权:
grant replication slave,replication client on *.* to ‘repl’@’192.168.137.%’ identified by ‘123456’;
grant all on *.* to ‘mhauser’@’192.168.137.%’ identified by ‘123456’;
slave 授权:
grant all on *.* to ‘mhauser’@’192.168.137.%’ identified by ‘123456’;
如果用 mysql 默认的异步模式,当主库硬件损坏宕机造成的数据丢失,因此在配置 MHA 的同时建议配置成 MySQL 的半同步复制。
注:mysql 半同步插件是由谷歌提供,具体位置 /usr/local/mysql/lib/plugin/ 下,一个是 master 用的 semisync_master.so,一个是 slave 用的 semisync_slave.so,
mysql> show variables like ‘%plugin_dir%’;
+—————+——————————+
| Variable_name | Value |
+—————+——————————+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+—————+——————————+
1、分别在主从节点上安装相关的插件(master,Candidate,slave)
在 MySQL 上安装插件需要数据库支持动态载入。检查是否支持,用如下检测:
mysql> show variables like ‘%have_dynamic_loading%’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| have_dynamic_loading | YES
所有 mysql 数据库服务器,安装半同步插件(semisync_master.so,semisync_slave.so)
mysql> install plugin rpl_semi_sync_master soname ‘semisync_master.so’;
mysql> install plugin rpl_semi_sync_slave soname ‘semisync_slave.so’;
检查 Plugin 是否已正确安装:
mysql> show plugins;
或
mysql> select * from information_schema.plugins;
查看半同步相关信息
mysql> show variables like ‘%rpl_semi_sync%’;
rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32
上图可以看到半同复制插件已经安装,只是还没有启用,所以是 OFF
2、修改 my.cnf 文件,配置主从同步:
注:若主 MYSQL 服务器已经存在,只是后期才搭建从 MYSQL 服务器,在置配数据同步前应先将主 MYSQL 服务器的要同步的数据库拷贝到从 MYSQL 服务器上(如先在主 MYSQL 上备份数据库,再用备份在从 MYSQL 服务器上恢复)
master mysql 主机:
server-id = 1
log-bin=mysql-bin
binlog_format=mixed
log-bin-index=mysql-bin.index
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
relay_log_purge=0
relay-log= relay-bin
relay-log-index = relay-bin.index
注:
rpl_semi_sync_master_enabled=1 1 表是启用,0 表示关闭
rpl_semi_sync_master_timeout=10000:毫秒单位,该参数主服务器等待确认消息 10 秒后,不再等待,变为异步方式。
Candidate 主机:
server-id = 2
log-bin=mysql-bin
binlog_format=mixed
log-bin-index=mysql-bin.index
relay_log_purge=0
relay-log= relay-bin
relay-log-index = slave-relay-bin.index
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
注:relay_log_purge=0,禁止 SQL 线程在执行完一个 relay log 后自动将其删除,对于 MHA 场景下,对于某些滞后从库的恢复依赖于其他从库的 relaylog,因此采取禁用自动删除功能
Slave 主机:
Server-id = 3
log-bin = mysql-bin
relay-log = relay-bin
relay-log-index = slave-relay-bin.index
read_only = 1
rpl_semi_sync_slave_enabled = 1
查看半同步相关信息
mysql> show variables like ‘%rpl_semi_sync%’;
查看半同步状态:
mysql> show status like ‘%rpl_semi_sync%’;
| Rpl_semi_sync_master_clients | 2 |
重点关注的参数:
rpl_semi_sync_master_status:显示主服务是异步复制模式还是半同步复制模式
rpl_semi_sync_master_clients:显示有多少个从服务器配置为半同步复制模式
rpl_semi_sync_master_yes_tx:显示从服务器确认成功提交的数量
rpl_semi_sync_master_no_tx:显示从服务器确认不成功提交的数量
rpl_semi_sync_master_tx_avg_wait_time:事务因开启 semi_sync,平均需要额外等待的时间
rpl_semi_sync_master_net_avg_wait_time:事务进入等待队列后,到网络平均等待时间
三、配置 mysql-mha
所有 mysql 节点安装
rpm -ivh perl-DBD-MySQL-4.013-3.el6.i686.rpm [yum -y install perl-DBD-MySQL]
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
2. manage 需安装依赖的 perl 包
rpm -ivh perl-Config-Tiny-2.12-7.1.el6.noarch.rpm
rpm -ivh perl-DBD-MySQL-4.013-3.el6.i686.rpm [yum -y install perl-DBD-MySQL]
rpm -ivh compat-db43-4.3.29-15.el6.x86_64.rpm
rpm -ivh perl-Mail-Sender-0.8.16-3.el6.noarch.rpm
rpm -ivh perl-Parallel-ForkManager-0.7.9-1.el6.noarch.rpm
rpm -ivh perl-TimeDate-1.16-11.1.el6.noarch.rpm
rpm -ivh perl-MIME-Types-1.28-2.el6.noarch.rpm
rpm -ivh perl-MailTools-2.04-4.el6.noarch.rpm
rpm -ivh perl-Email-Date-Format-1.002-5.el6.noarch.rpm
rpm -ivh perl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm -ivh perl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm -ivh perl-MIME-Lite-3.027-2.el6.noarch.rpm
rpm -ivh perl-Mail-Sendmail-0.79-12.el6.noarch.rpm
rpm -ivh perl-Log-Dispatch-2.27-1.el6.noarch.rpm
yum install -y perl-Time-HiRes-1.9721-144.el6.x86_64
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
3. 配置 mha
配置文件位于管理节点,通常包括每一个 mysql server 的主机名,mysql 用户名,密码,工作目录等等。
mkdir /etc/masterha/
vim /etc/masterha/app1.cnf
[server default]
user=mhauser
password=123456
manager_workdir=/data/masterha/app1
manager_log=/data/masterha/app1/manager.log
remote_workdir=/data/masterha/app1
ssh_user=root
repl_user=repl
repl_password=123456
ping_interval=1
[server1]
hostname=192.168.137.134
port=3306
master_binlog_dir=/usr/local/mysql/data
candidate_master=1
[server2]
hostname=192.168.137.130
port=3306
master_binlog_dir=/usr/local/mysql/data
candidate_master=1
[server3]
hostname=192.168.137.146
port=3306
master_binlog_dir=/usr/local/mysql/data
no_master=1
配关配置项的解释:
manager_workdir=/masterha/app1// 设置 manager 的工作目录
manager_log=/masterha/app1/manager.log// 设置 manager 的日志
user=manager// 设置监控用户 manager
password=123456 // 监控用户 manager 的密码
ssh_user=root //ssh 连接用户
repl_user=mharep // 主从复制用户
repl_password=123.abc// 主从复制用户密码
ping_interval=1 // 设置监控主库,发送 ping 包的时间间隔,默认是 3 秒,尝试三次没有回应的时候自动进行 failover
master_binlog_dir=/usr/local/mysql/data // 设置 master 保存 binlog 的位置,以便 MHA 可以找到 master 的日志,我这里的也就是 mysql 的数据目录
candidate_master=1// 设置为候选 master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库。
检测各节点间 ssh 互信通信配置是否 ok
masterha_check_ssh –conf=/etc/masterha/app1.cnf
结果:All SSH connection tests passed successfully.
检测各节点间主从复制是否 ok
masterha_check_repl –conf=/etc/masterha/app1.cnf
结果:MySQL Replication Health is OK.
在验证时,若遇到这个错误:Can’t exec “mysqlbinlog” ……
解决方法是在所有服务器上执行:
ln -s /usr/local/mysql/bin/* /usr/local/bin/
启动 manager:
nohup /usr/bin/masterha_manager –conf=/etc/masterha/app1.cnf –remove_dead_master_conf –ignore_last_failover > /etc/masterha/manager.log 2>&1 &
–remove_dead_master_conf 为主从切换后,老的主库 IP 将会从配置文件中移除
–ignore_last_failover 忽略生成的切换完成文件,若不忽略,则 8 小时内无法再次切换
–ignore_fail_on_start
## 当有 slave 节点宕掉时,MHA 默认是启动不了的,加上此参数即使有节点宕掉也能启动 MHA,
关闭 MHA:
masterha_stop –conf=/etc/masterha/app1.cnf
查看 MHA 状态:
masterha_check_status –conf=/etc/masterha/app1.cnf
app1 (pid:45128) is running(0:PING_OK), master:192.168.137.134
4. 模拟故障转移
停掉 master,
/etc/init.d/mysqld stop
查看 MHA 日志 /data/masterha/app1/manager.log
—– Failover Report —–
app1: MySQL Master failover 192.168.137.134(192.168.137.134:3306) to 192.168.137.1
30(192.168.137.130:3306) succeeded
Master 192.168.137.134(192.168.137.134:3306) is down!
Check MHA Manager logs at zifuji:/data/masterha/app1/manager.log for details.
Started automated(non-interactive) failover.
The latest slave 192.168.137.130(192.168.137.130:3306) has all relay logs for reco
very.
Selected 192.168.137.130(192.168.137.130:3306) as a new master.
192.168.137.130(192.168.137.130:3306): OK: Applying all logs succeeded.
192.168.137.146(192.168.137.146:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
192.168.137.146(192.168.137.146:3306): OK: Applying all logs succeeded. Slave star
ted, replicating from 192.168.137.130(192.168.137.130:3306)
192.168.137.130(192.168.137.130:3306): Resetting slave info succeeded.
Master failover to 192.168.137.130(192.168.137.130:3306) completed successfully.
3. 查看 slave 复制状态
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.137.130
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2017-05/143691p2.htm