共计 10087 个字符,预计需要花费 26 分钟才能阅读完成。
MHA 介绍
MHA(Master High Availability)目前在 MySQL 高可用方面是一个相对成熟的解决方案
,它由日本 DeNA 公司 youshimaton(现就职于 Facebook 公司)开发,是一套优秀的作为 MySQL 高可用性环境下 故障切换和主从提升的高可用软件
。在 MySQL 故障切换过程中,MHA 能做到在 0~30 秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA 能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA 还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中
(通过将从库提升为主库), 大概0.5- 2 秒 内即可完成
自动故障检测和自动故障转移
MHA 能够在一个已经存在的复制环境中监控 MySQL, 当检测到 Master 故障后能够实现自动故障转移,通过鉴定出最“新”的 Salve 的 relay log,并将其应用到所有的 Slave
,这样 MHA 就能够保证各个 slave 之间的数据一致性,即使有些 slave 在主库崩溃时还没有收到最新的 relay log 事件。一个 slave 节点能否成为候选的主节点可通过在配置文件中配置它的优先级。由于 master 能够保证各个 slave 之间的数据一致性,所以所有的 slave 节点都有希望成为主节点。在通常的 replication 环境中由于复制中断而极容易产生的数据一致性问题,在 MHA 中将不会发生
。
注:在 MHA 的高可用环境的,主库宕机了,MHA 服务将停止,如何恢复 MHA 服务了,需要把宕机的主库加入到高可用环境(也就是把宕机的主库变成从库)在重新启动 MHA
交互式(手动)故障转移
MHA 可以手动地实现故障转移,而不必去理会 master 的状态,即不监控 master 状态,确认故障发生后可通过 MHA 手动切换
在线切换 Master 到不同的主机
MHA 能够在 0.5- 2 秒内实现切换,0.5- 2 秒的写阻塞通常是可接受的,所以你甚至能在非维护期间就在线切换 master。诸如升级到高版本,升级到更快的服务器之类的工作,将会变得更容易。
MHA 优势
- 自动故障转移快
- 主库崩溃不存在数据一致性问题
- 配置不需要对当前 mysql 环境做重大修改
- 不需要添加额外的服务器(仅一台 manager 就可管理上百个 replication)
- 性能优秀,可工作在半同步复制和异步复制,当监控 mysql 状态时,仅需要每隔 N 秒向 master 发送 ping 包(默认 3 秒),所以对性能无影响。你可以理解为 MHA 的性能和简单的主从复制框架性能一样。
- 只要 replication 支持的存储引擎,MHA 都支持,不会局限于 innodb
MHA 组成
MHA 由 Manager 节点和 Node 节点组成。
MHA Manager 可以单独部署
在一台独立的机器上管理多个 master-slave 集群,也可以部署在一台 slave 节点上
。MHA Node 运行在每台 MySQL 服务器上,MHA Manager 会定时探测集群中的 master 节点,当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master,然后将所有其他的 slave 重新指向新的 master。整个故障转移过程对应用程序完全透明。
MHA 工作原理
- 从宕机崩溃的 master 保存二进制日志事件(binlog events);
- 识别含有最新更新的 slave;
- 应用差异的中继日志(relay log)到其他的 slave;
- 应用从 master 保存的二进制日志事件(binlog events);
- 提升一个 slave 为新的 master;
- 使其他的 slave 连接新的 master 进行复制;
MHA 安装
准备四个节点,其中一个是管理节点,三个是一主两从的环境
MHA 项目地址
https://code.google.com/p/mysql-master-ha/
主从环境我这已近搭建好
环境如下:
主机名 | ip |
mycat01 | 10.0.0.200 |
master01 | 10.0.0.201 |
master02 | 10.0.0.204 |
slave02 | 10.0.0.203 |
注:master01 是主库 master02 是从库,slave02 是从库,一主两从
mha 管理节点需要 mysql 命令环境
在所有节点上安装 node 节点
yum install –y perl-DBD-MySQL
rpm -ivh mha4mysql-node-0.54-0.noarch.rpm在管理节点上安装 manager 节点
yum install -y perl-Config-Tiny
yum install -y perl-Log-Dispatch
yum install -y perl-Parallel-ForkManager
rpm -ivh mha4mysql-manager-0.55-0.el6.noarch.rpm在四个节点的 /etc/hosts 中添加主机内容:
10.0.0.200 mycat01
10.0.0.201 master01
10.0.0.204 master02
10.0.0.202 slave01在管理节点创建配置文件
[server default]
# mysql user and password
user=root
password=123456
ssh_user=root
# working directory on the manager
manager_workdir=/var/log/masterha/app1
# working directory on MySQL servers
remote_workdir=/var/log/masterha/app1
repl_user=repl
repl_password=123456
user=root
ping_interval=1
remote_workdir=/tmp
[server1]
hostname=master01
port=3306
master_binlog_dir=/usr/local/mysql/data
[server2]
hostname=master02
port=3306
master_binlog_dir=/usr/local/mysql/data
#candidate_master=1
#check_repl_delay=0
[server3]
hostname=slave01
port=3306
master_binlog_dir=/usr/local/mysql/data
- 在所有节点的 my.cnf 文件 添加一下内容
relay_log_purge=0
log-slave-updates=true
添加完记得重启所有 mysql 环境
- 所有节点(管理节点和 node 节点)实现无密码登录
MHA manager 通过 SSH 访问所有的 node 节点,各个 node 节点也同样需要通过 SSH 来相互发送不同的 relay log 文件,所以有必要在每一个 node 和 manager 上配置 SSH 无密码登陆。
- 设置目录和软连接
mkdir /var/log/masterha/app1 –p #管理节点 存放 mha 日志
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog #所有节点
ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql #所有节点
- 检测所有节点 SSH 连接是否配置正常
MHAmanager 可通过 masterha_check_ssh 脚本检测 SSH 连接是否配置正常
masterha_check_ssh —conf=/etc/app1.cnf
- 在管理节点检查复制配置
为了让 MHA 正常工作,所有的 master 和 slave 必须在配置文件中正确配置,MHA 可通过 masterha_check_repl 脚本检测复制是否正确配置
masterha_check_repl —conf=/etc/app1.cnf
如果主从复制正常会出现
MySQL Replication Health is OK
- 开启 Manager
当你正确配置了 mysql 复制,正确安装了 manager 和 node 节点,SSH 配置也正确,那么下一步就是开启 manager,可通过 masterha_manager 命令开启
检查 manager 状态
当 MHA manager 启动监控以后,如果没有异常则不会打印任何信息。我们可通过 masterha_check_status 命令检查 manager 的状态,以下是范例测试 master 的自动故障转移
现在 master 运行正常,manager 监控也正常,下一步就是停止 master,测试自动故障
转移,可以简单地停止 master 上的 mysqld 服务
[root@master01 bin]# /etc/init.d/mysql.server stop
Shutting down MySQL………… SUCCESS!
这时候检查 manager 的 log 日志,看看 slave1 是否成功成为新的 master,并且 slave2 从 slave1 中复制。查看 MHA 切换日志
vim /var/log/masterha/app1/mha_manager.log
Master failover to master02(10.0.0204:3306) completed successfully.
会出现迁移成功的字样。
注:有一个主库停止了服务,故障切换完毕,mha 的服务也会停止
ok MHA 搭建完成
MHA 配置文件介绍
[server default]
manager_workdir=/var/log/masterha/app1.log // 设置 manager 的工作目录
manager_log=/var/log/masterha/app1/manager.log // 设置 manager 的日志
master_binlog_dir=/data/mysql // 设置 master 保存 binlog 的位置,以便 MHA 可以找到 master 的日志,我这里的也就是
mysql 的数据目录
master_ip_failover_script= /usr/local/bin/master_ip_failover // 设置自动 failover 时候的切换脚本
master_ip_online_change_script= /usr/local/bin/master_ip_online_change // 设置手动切换时候的切换脚本
password=123456 // 设置 mysql 中 root 用户的密码,这个密码是前文中创建监控用户的那个密码
user=root 设置监控用户 root
ping_interval=1 // 设置监控主库,发送 ping 包的时间间隔,默认是 3 秒,尝试三次没有回应的时候自动进行 failover
remote_workdir=/tmp // 设置远端 mysql 在发生切换时 binlog 的保存位置
repl_password=123456 // 设置复制用户的密码
repl_user=repl // 设置复制环境中的复制用户名
report_script=/usr/local/send_report // 设置发生切换后发送的报警的脚本
secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 # // 一旦 MHA 到 server02 的监控之间出现问题,MHA Manager 将会尝试从 server03 登录到 server02
shutdown_script=”” // 设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂, 这里没有使用)
ssh_user=root // 设置 ssh 的登录用户名
[server1]
hostname=10.0.0.201
port=3306
[server2]
hostname=10.0.0.204
port=3306
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
[server3]
hostname=10.0.0.202
port=3306
设置 relay log 的清除方式(在每个 slave 节点上
):
mysql -e‘set global relay_log_purge=0’
注意:
MHA 在发生切换的过程中,从库的恢复过程中依赖于 relay log 的相关信息,所以这里要将 relay log 的自动清除设置为 OFF,采用手动清除 relay log 的方式。在默认情况下,从服务器上的中继日志会在 SQL 线程执行完毕后被自动删除。但是在 MHA 环境中,这些中继日志在恢复其他从服务器时可能会被用到,因此需要禁用中继日志的自动删除功能
MHA 手动模拟故障
mha 没有开启服务
先关闭两个从库的 slave 进程
mysql> stop slave;在主库上执行插入操作,而从库没办法同步
mysql> insert into temp2 values(5000,’abc’);
Query OK, 1 row affected (0.00 sec)- 主库 MySQL 直接关闭,两个从库开启复制进程,依旧没有最数据
Shutting down MySQL…. SUCCESS!
从库查询刚插入的数据
mysql> select * from temp2 where >
Empty set (0.00 sec)
- 开启 mha 进程,发现完成主从切换
查看日志
Invalidated master IP address on master01.
The latest slave master02(10.0.0.204:3306) has all relay logs for recovery.
Selected master02 as a new master.
master02: OK: Applying all logs succeeded.
master02: OK: Activated master IP address.
slave01: This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
slave01: OK: Applying all logs succeeded. Slave started, replicating from master02.
master02: Resetting slave info succeeded.
Master failover to master02(10.0.0.204:3306) completed successfully.
主库已近切换到 master02 了
5. 查看新的主从是否有 5000 这条记录
+——+——+
| id | name |
+——+——+
| 5000 | abc |
插入成功
可以通过 binlog 分析
[root@master01 app1]# mysqlbinlog -v /var/log/masterha/app1/saved_master_binlog_from_master01_3306_20180909014109.binlog
MHA 手动切换
手动 failover,这种场景意味着在业务上没有启用 MHA 自动切换功能,当主服务器故障时,人工手动调用 MHA 来进行故障切换操作
,具体命令如下:
我还原先前的主从关系
先关闭 mha 进程,确保不会自动执行切换
[root@mycat01 ~]# masterha_stop –conf=/etc/app1.cnf再关闭 maser 主库
[root@master01 ~]# /etc/init.d/mysql.server stop
Shutting down MySQL………… SUCCESS!执行手动切换
开启 mha 进程,可以查看日志确定是否切换成功
去数据库验证 show slave status\G;
MHA 在线切换
还原先前主从环境
为了保证数据完全一致性,在最快的时间内完成切换,MHA 的在线切换必须满足以下条件才会切换成功,否则会切换失败。
1. 所有 slave 的 IO 线程都在运行
2. 所有 slave 的 SQL 线程都在运行
3. 所有的 show slave status 的输出中 Seconds_Behind_Master 参数小于或者等于 running_updates_limit 秒,如果在切换过程中不指定 running_updates_limit, 那么默认情况下 running_updates_limit 为 1 秒。
4. 在 master 端,通过 show processlist 输出,没有一个更新花费的时间大于 running_updates_limit 秒。
在线切换步骤如下:
- 首先,停掉 MHA 监控:
[root@mycat01 ~]# masterha_stop –conf=/etc/app1.cnf - 其次,进行在线切换操作
(模拟在线切换主库操作,原主库 10.0.0.201 变为 slave,
10.0.204 提升为新的主库)
-orig_master_is_new_slave 切换时加上此参数是将原 master 变为 slave 节点,如果不加此参数,原来的 master 将不启动
–running_updates_limit=10000, 故障切换时, 候选 master 如果有延迟的话,mha 切换不能成功,加上此参数表示延迟在此时间范围内都可切换(单位为 s),但是切换的时间长短是由
recover 时 relay 日志的大小决定
- 去数据库验证 show slave status\G;
MHA vip 漂移
记得还原先前主从环境
为什么要做 vip 地址?
简单点就是为了数据库发生故障期间,感觉不到数据库发生了故障,所以才需要 vip 漂移
当然这个你想用 keepalive 做 vip 取决于你
- 在 master 节点上执行 ifconfig eth0:2 10.0.0.210/24
- 在管理监控节点上配置 /usr/local/bin/master_ip_failover
master_ip_failover 内容如下
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 = ‘10.0.0.210/24’;
my $key = ‘2’;
my $ssh_start_vip = “/sbin/ifconfig eth0:$key $vip”;
my $ssh_stop_vip = “/sbin/ifconfig eth0:$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”;
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \” $ssh_start_vip \”`;
}
sub stop_vip() {
return 0 unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \” $ssh_stop_vip \”`;
}
sub usage {
“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”;
在监控节点的 /etc/app1.cnf 中添加此文件
master_ip_failover_script=/usr/local/bin/master_ip_failover测试当把 master 关机之后,VIP 漂移到了新的主节点上
[root@master01 bin]# /etc/init.d/mysql.server stop
Shutting down MySQL………… SUCCESS!
: