MHA高可用

MHA高可用

nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

一.MHA简介


1.作者:松信嘉範


2.软件简介

MHA能够在较短的时间内实现自动故障检测和故障转移,通常在10-30秒以内;在复制框架中,MHA能够很好地解决复制过程中的数据一致性问题,由于不需要在现有的replication中添加额外的服务器,仅需要一个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量;另外,安装简单,无性能损耗,以及不需要修改现有的复制部署也是它的优势之处。

MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。

MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以独立部署在一台独立的机器上管理多个Master-Slave集群,也可以部署在一台Slave上。当Master出现故障时,它可以自动将最新数据的Slave提升为新的Master,然后将所有其他的Slave重新指向新的Master。整个故障转移过程对应用程序是完全透明的。

3.MySQL高可用方案

1)双主 + keepalived

2)MMM

3)MHA

4)MGR(半同步复制)

很多企业用第一种方法 会有什么问题?

双主互为主从,但是数据不一定会统一。可能一个是100,一个是90,当主机宕机 vip漂移到另一台主机时,还有10的数据就没了,所以,第一他会丢数据,第二他只能两台互相切换

二.工作流程原理

MHA高可用_第1张图片

1)把宕机的master二进制日志保存下来。
2)找到binlog位置点最新的slave。
3)在binlog位置点最新的slave上用relay log(差异日志)修复其它slave。
4)将宕机的master上保存下来的二进制日志恢复到含有最新位置点的slave上。
5)将含有最新位置点binlog所在的slave提升为master。
6)将其它slave重新指向新提升的master,并开启主从复制。

#主库宕机处理过程
1. 监控节点 (通过配置文件获取所有节点信息)
   系统,网络,SSH连接性
   主从状态,重点是主库

2. 选主
(1) 如果判断从库(position或者GTID),数据有差异,最接近于Master的slave,成为备选主
(2) 如果判断从库(position或者GTID),数据一致,按照配置文件顺序,选主.
(3) 如果设定有权重(candidate_master=1),按照权重强制指定备选主.
    1. 默认情况下如果一个slave落后master 100M的relay logs的话,即使有权重,也会失效.
    2. 如果check_repl_delay=0的化,即使落后很多日志,也强制选择其为备选主

3. 数据补偿
(1) 当SSH能连接,从库对比主库GTID 或者position号,立即将二进制日志保存至各个从节点并且应用(save_binary_logs )
(2) 当SSH不能连接, 对比从库之间的relaylog的差异(apply_diff_relay_logs) 

4. Failover
将备选主进行身份切换,对外提供服务
其余从库和新主库确认新的主从关系

5. 应用透明(VIP)
6. 故障切换通知(send_reprt)
7. 二次数据补偿(binlog_server)
8. 自愈自治(待开发...)

三.MHA架构图

MHA高可用_第2张图片

不要将manager装在主库上 ,因为manager是通过ssh协议检测的,哪怕我装在主库上,我也要ssh主库然后再检测,那断电了断网了MHA就不会工作了,如果不装在主库上,主库宕机服务没了,MHA是可以继续工作的

manager:服务端 node:客户端

一个MHA可以管理多套MySQL集群(上百套)

四.MHA工具介绍

MHA软件由两部分组成,Manager工具包和Node工具包,具体的说明如下:

1.Manager工具包主要包括以下几个工具:

[root@db01 ~/mha4mysql-manager-0.56/bin]# ll
-rwxr-xr-x 1 4984 users 1995 Apr  1  2014 masterha_check_repl
-rwxr-xr-x 1 4984 users 1779 Apr  1  2014 masterha_check_ssh
-rwxr-xr-x 1 4984 users 1865 Apr  1  2014 masterha_check_status
-rwxr-xr-x 1 4984 users 3201 Apr  1  2014 masterha_conf_host
-rwxr-xr-x 1 4984 users 2517 Apr  1  2014 masterha_manager
-rwxr-xr-x 1 4984 users 2165 Apr  1  2014 masterha_master_monitor
-rwxr-xr-x 1 4984 users 2373 Apr  1  2014 masterha_master_switch
-rwxr-xr-x 1 4984 users 5171 Apr  1  2014 masterha_secondary_check
-rwxr-xr-x 1 4984 users 1739 Apr  1  2014 masterha_stop
masterha_check_ssh              #检查MHA的ssh-key
masterha_check_repl             #检查主从复制情况
masterha_manger                 #启动MHA
masterha_check_status           #检测MHA的运行状态
masterha_master_monitor         #检测master是否宕机
masterha_master_switch          #手动故障转移  (主库宕机自动切换 manager要用到的)
masterha_conf_host              #手动添加server信息  (摘除配置文件里面的主机信息 他自己启动用的)
masterha_secondary_check        #建立TCP连接从远程服务器
masterha_stop                   #停止MHA

2.Node工具包主要包括以下几个工具:

[root@db01 ~/mha4mysql-node-0.56/bin]# ll
-rwxr-xr-x 1 4984 users 16367 Apr  1  2014 apply_diff_relay_logs
-rwxr-xr-x 1 4984 users  4807 Apr  1  2014 filter_mysqlbinlog
-rwxr-xr-x 1 4984 users  8261 Apr  1  2014 purge_relay_logs
-rwxr-xr-x 1 4984 users  7525 Apr  1  2014 save_binary_logs
这些工具通常由MHA Manager的脚本触发,无需人为操作
save_binary_logs                #保存宕机的master的binlog事件
apply_diff_relay_logs           #识别relay log的差异
filter_mysqlbinlog              #防止回滚事件 (截取binlog 过滤binlog)
purge_relay_logs                #清除中继日志relay log (关闭自动清除  选择手动清除)

五、MHA优点总结

1)Masterfailover and slave promotion can be done very quickly
自动故障转移快

2)Mastercrash does not result in data inconsistency
主库崩溃不存在数据一致性问题

3)Noneed to modify current MySQL settings (MHA works with regular MySQL)
不需要对当前mysql环境做重大修改

4)Noneed to increase lots of servers
不需要添加额外的服务器(仅一台manager就可管理上百个replication)

5)Noperformance penalty
性能优秀,可工作在半同步复制和异步复制,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。

之前我们用的ping baidu.com的ping 是icmp协议 telnet也是icmp 是tcp/ip的子协议

这里的ping 是select ping 没有协议 所以对性能没有任何影响

6)Works with any storage engine
只要replication支持的存储引擎,MHA都支持,不会局限于innodb

六、基于GTID的MHA-MySQL环境准备

用了GTID的话 就不用了第一件事去保存binlog 他会自动获取

GTID从库开启binlog 所以不需要补全

1.环境准备

主机名 wanIP lanIP 角色
db01 10.0.0.51 172.16.1.51 主库,MHA客户端
db02 10.0.0.52 172.16.1.52 从库,MHA客户端
db03 10.0.0.53 172.16.1.53 从库,MHA客户端
db04 10.0.0.54 172.16.1.54 从库,MHA客户端
MHA-manager 10.0.0.53 172.16.1.53 MHA服务端
1.停库
[root@db01 ~]# /etc/init.d/mysqld stop
2.删除data目录
[root@db01 ~]# rm -fr /application/mysql/data
3.初始化配置文件
[root@db01 support-files]# cp my-default.cnf /etc/my.cnf
cp: overwrite ‘/etc/my.cnf’? y
4.初始化MySQL
[root@db01 support-files]# cd /application/mysql/scripts/
[root@db01 scripts]# ./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data
5.启动数据库
[root@db01 scripts]# /etc/init.d/mysqld start

2.做好四台服务器的GTID主从复制

# 主库查看gtid参数
mysql> show variables like'%GTID%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| binlog_gtid_simple_recovery     | OFF       |
| enforce_gtid_consistency        | OFF       | #永久支持关闭
| gtid_executed                   |           |
| gtid_mode                       | OFF       | #gtid模块关闭
| gtid_next                       | AUTOMATIC |
| gtid_owned                      |           |
| gtid_purged                     |           |
| simplified_binlog_gtid_recovery | OFF       |
+---------------------------------+-----------+
# 准备配置文件
# 1.主库(db01)配置
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
gtid_mode=on
enforce_gtid_consistency
binlog_format=row
log-bin=mysql-bin
log-slave-updates #之前说从库不会记录binlog 加上这个从库就会记录binlog 
server_id=1


# 2.重启
[root@db01 ~]# /etc/init.d/mysqld restart
SUCCESS! 


# 3.从库(db02)配置
[root@db02 ~]# vim /etc/my.cnf
[mysqld]
gtid_mode=on
enforce_gtid_consistency
binlog_format=row
log-bin=mysql-bin
log-slave-updates
server_id=2


# 4.主库创建主从复制用户
mysql> grant replication slave on *.* to rep@'%' identified by '123';


# 5.从库连接主库
mysql> change master to
-> master_host='10.0.0.51',
-> master_user='rep',
-> master_password='123',
-> master_auto_position=1;

mysql> start slave;

mysql> show slave status\G
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            

# 6.主库查看主从复制状态
mysql> show master status;

3.GTID主从的配置

传统

1.主库要开启binlog,从库不用开启binlog

2.主库要有中从复制用户,从库不需要创建主从复制用户

3.主库server_id=5,从库只要不等于5即可,从库之间可以相同


基于MHA的主从复制

1.主库要开启binlog,从库也要开启binlog

2.主库要创建主从复制用户,从库也必须创建主从复制用户

3.主库server_id=5,从库只要不等于5即可,从库之间必须不相同

从库随时会被提升为新的主库

1.关闭所有数据库自动清除relay log 的功能

  • 主库要关闭
  • 从库也要关闭
  • 临时+永久关闭

2.从库要设置为只读 开启read-only功能

  • 主库不开启
  • 从库要开启
  • 临时开启
#临时关闭自动清除relay log功能(所有库)
set global relay_log_purge = 0;
#永久关闭自动清除relay log功能(所有库)
[root@db01 data]# vim /etc/my.cnf
relay_log_purge = 0

#临时开启只读功能(所有从库)主库执行就瞎了!!!
【不放配置文件 就是怕切换master时从库有永久只读 临时只读在做切换时 MHA会自动帮你取消只读】
set global read_only=1;

mysql> set global read_only=1;
mysql> show variables like '%read_only%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| read_only        | ON    |
+------------------+-------+

只读只针对于普通用户 root用户权限大 还是可以操作的

注意有没有重启mysql 重启后失效 因为你设置的是临时的

# 创建个普通用户试试
grant select,update,insert,delete,create,drop on *.* to dev@'%' identified by '123';

[root@db04 ~]# mysql -udev -p123 -h10.0.0.54

MHA高可用_第3张图片

七、部署MHA并测试

db01:master node 10.0.0.51

db02:slave01 node manager 10.0.0.52

db03:slave02 node 10.0.0.53

db04:slave03 node 10.0.0.54

1.安装部署MHA

# 1.把安装包都拖进去
[root@db01 ~]# ll
-rw-r--r-- 1 root root 36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

[root@db02 ~]# ll
-rw-r--r--  1 root root     87119 Dec 16 08:35 mha4mysql-manager-0.56-0.el6.noarch.rpm
-rw-r--r--  1 root root     36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

[root@db03 ~]# ll
-rw-r--r-- 1 root root 36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

[root@db04 ~]# ll
-rw-r--r-- 1 root root 36326 Dec 16 08:35 mha4mysql-node-0.56-0.el6.noarch.rpm

## 安装包下载地址
https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads


# 2.安装node (先装node  因为没有node  manager起不来) 
[root@db01 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db02 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db03 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db04 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm


# 3.安装manager
[root@db02 ~]# yum localinstall -y mha4mysql-manager-0.56-0.el6.noarch.rpm 


# 4.创建MHA管理用户(所有库都要创建)
主库创建一个就行了 你做了主从复制 从库就会有这个用户
db01:
mysql> grant all on *.* to mha@'%' identified by 'mha';
db02:
mysql> select user,host from mysql.user;
+------+-----------+
| user | host      |
+------+-----------+
| mha  | %         |
| rep  | %         |
| root | 127.0.0.1 |
| root | ::1       |
|      | db02      |
| root | db02      |
|      | localhost |
| root | localhost |
+------+-----------+


# 5.做命令的软链接
[root@db01 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db01 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

[root@db02 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db02 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

[root@db03 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db03 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql

[root@db04 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@db04 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql


# 6.创建密钥对
[root@db01 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.51
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.52
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.53
[root@db01 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.54

----

[root@db02 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.51
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.52
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.53
[root@db02 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.54

----

[root@db03 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.51
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.52
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.53
[root@db03 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.54

----

[root@db04 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.51
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.52
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.53
[root@db04 ~]# ssh-copy-id -i ~/.ssh/id_dsa.pub 10.0.0.54


# 7.写MHA配置文件
[root@db02 ~]# mkdir /etc/mha
[root@db02 ~]# vim /etc/mha/app1.cnf
[server default]
manager_log=/etc/mha/app1/manager.log
manager_workdir=/etc/mha/app1
master_binlog_dir=/application/mysql/data
user=mha
password=mha
ping_interval=2
repl_password=123
repl_user=rep
ssh_user=root
ssh_port=22

[server1]
hostname=10.0.0.51
port=3306

[server2]
#candidate_master=1
#check_repl_delay=0
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306

[server4]
hostname=10.0.0.54
port=3306

## 启动前测试
[root@db02 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
Mon Dec 16 12:12:11 2019 - [info] All SSH connection tests passed successfully.

[root@db02 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.


# 8.启动MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

--remove_dead_master_conf:加上这个参数 你主库挂了 他会把你配置文件里主库啥的摘掉
--ignore_last_failover:忽略上一次切换 不生成锁文件
【MHA工作机制】
做完一次切换后 在工作目录下(etc/mha/app1) 会生成一个锁文件(app1.failover.complete) 
8小时之内不做第二次切换


# 9.检测MHA启动状态
[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:121442) is running(0:PING_OK), master:10.0.0.51


# 10.停止MHA
[root@db02 ~]# masterha_stop --conf=/etc/mha/app1.cnf

2.报错解释

MHA高可用_第4张图片

报错原因:将IP解析成主机名了

解决方法:

#在配置文件中,添加一个跳过反向解析的参数
skip_name_resolve

报错原因:找不到这个10网段

解决方法:

change master to  和  /etc/mha/app1.cnf
建立主从关系的主机网段要和配置文件里的一致   不能一个是10网段 一个是172网段

3.配置文件详解

[server default]
#设置manager的工作目录
manager_workdir=/etc/mha/app1

#设置manager的日志
manager_log=/etc/mha/app1/manager.log

#设置master 保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录
master_binlog_dir=/application/mysql/data

#设置自动failover时候的切换脚本
master_ip_failover_script= /usr/local/bin/master_ip_failover

#设置手动切换时候的切换脚本
master_ip_online_change_script= /usr/local/bin/master_ip_online_change

#设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码
password=mha

#设置监控用户root
user=root

#设置监控主库,发送ping包的时间间隔,尝试三次没有回应的时候自动进行failover
ping_interval=1

#设置远端mysql在发生切换时binlog的保存位置
remote_workdir=/tmp

#设置复制用户的密码
repl_password=123

#设置复制环境中的复制用户名 
repl_user=rep

#设置发生切换后发送的报警的脚本
report_script=/usr/local/send_report

#一旦MHA到server02的监控之间出现问题,MHA Manager将会尝试从server03登录到server02
secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=192.168.0.50 --master_port=3306

#设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)
shutdown_script=""

#设置ssh的登录用户名
ssh_user=root 

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306
#设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave。
candidate_master=1

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

4.切换master 并恢复

`切换master测试
# 1.查看三个从库的主从状态
db02:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 191
               Relay_Log_File: db02-relay-bin.000006
                Relay_Log_Pos: 401
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

db03:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 191
               Relay_Log_File: db03-relay-bin.000005
                Relay_Log_Pos: 401
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes                   

db04:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 191
               Relay_Log_File: db04-relay-bin.000005
                Relay_Log_Pos: 401
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

# 2.把db01关掉 再查看三个从库主从状态
[root@db01 ~]# /etc/init.d/mysqld stop

db02:
mysql> show slave status\G
Empty set (0.00 sec)

db03:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.52
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 191
               Relay_Log_File: db03-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

db04:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.52
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 191
               Relay_Log_File: db04-relay-bin.000002
                Relay_Log_Pos: 361
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            

`MHA-master恢复
# 1.修复主库
[root@db01 ~]# /etc/init.d/mysqld start
Starting MySQL......... SUCCESS! 

# 2.manager日志找到这个 并在之前主库上执行
[root@db02 ~]# grep -i 'change master to' /etc/mha/app1/manager.log 
Mon Dec 16 15:35:53 2019 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='xxx';

db01:
mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='123';
mysql> start slave;

# 3.修改配置文件(当你做完切换时 配置文件自动发生该改变 和之前的不一样了)
[root@db02 ~]# vim /etc/mha/app1.cnf  (db01没了 加上)
[server1]
hostname=10.0.0.51
port=3306

# 4.启动并检查MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:10048) is running(0:PING_OK), master:10.0.0.52

5.恢复集群脚本

[root@db04 ~]# vim huifu.sh (每台服务器上都放一个脚本)
#!/bin/bash

#old_master=`ssh 10.0.0.52 "sed -nr 's#^Master (.*)\(.*!$#\2#gp' /etc/mha/app1/manager.log"`

change=`ssh 10.0.0.52 "grep -i 'change master to' /etc/mha/app1/manager.log"|awk -F: '{print $NF}'|sed 's#xxx#123#g'`

/etc/init.d/mysqld start

mysql -e "$change start slave;"

ssh 10.0.0.52 '\cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf'
    
[root@db02 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failo/app1/manager.log 2>&1 &

[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:21314) is running(0:PING_OK), master:10.0.0.51   
    
#重新恢复集群之后 就要重新开MHA

报错解释

db01指向52

db02,db03,db04指向51

发生脑裂

51:

MHA高可用_第5张图片

52,53,54:

MHA高可用_第6张图片

解决方法:

51:
mysql> stop slave;
mysql> reset slave all;

八、MHA优先级参数

在没有配置权重或者没有数据量的情况下,规定:

切换master测试 -----> 配置文件server标签越小优先级越高 [server1]-[server2]/[server_a]-[server_b]

数字优先级最高 然后走字母

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

#放一起用
candidate_master=1
check_repl_delay=0
一般不用 这个参数

九、高可用GTID主从和高可用传统主从的区别

1.配置传统主从复制

# 1.修改配置文件(主从都修改 注意server_id不同) 就是把gtid那几个注释掉
[mysqld]
skip_name_resolve
log-bin=mysql-bin
binlog_format=row
server_id=1
relay_log_purge = 0

# 2.重启
[root@db01 ~]# /etc/init.d/mysqld restart (全部重启)
Starting MySQL......... SUCCESS! 

# 3.清除之前做的主从 查看主从状态  都是1 120起
mysql> stop slave;
mysql> reset master;(没数据测试的时候用 其他时候千万不行) reset slave all;
mysql> show master status;

# 4.从库连接主库 并检查 (所有从库)
mysql> change master to
    -> master_host='10.0.0.51',
    -> master_user='rep',
    -> master_password='123',
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=120;

mysql> start slave;

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 317
               Relay_Log_File: db02-relay-bin.000002
                Relay_Log_Pos: 480
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes


# 5.主从ok之后 找到manager启动前检测
[root@db02 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf  
MySQL Replication Health is OK.

# 6.启动MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &

# 7.检测MHA启动状态
[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:121442) is running(0:PING_OK), master:10.0.0.51

MHA高可用_第7张图片

报错原因:之前重启了mysql 导致临时只读失效

解决方法:

#在所有从库上执行临时只读
set global read_only=1;

2.查看日志,很有用

#GTID
[root@db02 ~]# tail -f /etc/mha/app1/manager.log 
GTID failover mode = 1
...
#master_ip_failover_script没有设置    
master_ip_failover_script is not set. Skipping invalidating dead master IP address.
...
#候选的主库在配置文件中:
Candidate masters from the configuration file:
...

----- Failover Report -----
app1: MySQL Master failover 10.0.0.51(10.0.0.51:3306) to 10.0.0.52(10.0.0.52:3306) succeeded
Master 10.0.0.51(10.0.0.51:3306) is down!
Check MHA Manager logs at db02:/etc/mha/app1/manager.log for details.
Started automated(non-interactive) failover.
Selected 10.0.0.52(10.0.0.52:3306) as a new master.
10.0.0.52(10.0.0.52:3306): OK: Applying all logs succeeded.
10.0.0.53(10.0.0.53:3306): OK: Slave started, replicating from 10.0.0.52(10.0.0.52:3306)
10.0.0.54(10.0.0.54:3306): OK: Slave started, replicating from 10.0.0.52(10.0.0.52:3306)
10.0.0.52(10.0.0.52:3306): Resetting slave info succeeded.
Master failover to 10.0.0.52(10.0.0.52:3306) completed successfully.
#传统
[root@db02 ~]# tail -f /etc/mha/app1/manager.log 
第一步就是保存binlog
save_binary_logs (var/tmp) 在坏掉的主机上  
...
GTID failover mode = 0
...
master_ip_failover_script is not set. Skipping invalidating dead master IP address.
...
Candidate masters from the configuration file:
...
finding the latest slave that has all relay 
...
scp宕机主库的binlog ---> manager的工作目录下 ---> 新主库的/usr/tmp下
...

十、配置VIP漂移

1.为什么要vip漂移?

原理如同负载均衡vip漂移 保证数据不丢失

2.VIP漂移的两种方式:

1)通过keepalived的方式,管理虚拟IP的漂移 【局限性:丢数据 只能两台切换】
2)通过MHA自带脚本方式,管理虚拟IP的漂移

3.keepalived漂移方案

例如:如何一定漂db02

1.给db02添加两个参数
candidate_master=1
check_repl_delay=0


2.让db02从库做半同步 数据就比其他从库多 选择该从库为备master 
【但是做半同步会影响主库性能,并且超时恢复成异步】
可以选择硬件好的服务器做主库和半同步 主要是磁盘(内存CPU:1核2G,2核4G,4核8G)
半同步服务器不提供服务,只做主库的热备 切换master 原主库做现主库的热备,不提供服务
都花钱


3.延迟从库 延迟其他的两个从库db03,db04  这样db02的数据就比其他两个更新的快 
【#错!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!】
【因为MHA对比的是relay-log 延迟从库relay-log里面也有拿过来的数据 只不过sql线程拖延执行】

这些是一套不成熟的方案

4.MHA自带脚本方案

1.配置文件

脚本语法错误,脚本格式错误,脚本权限错误 这三个会导致MHA起不来

# 1.修改配置文件
[root@db02 ~]# vim /etc/mha/app1.cnf
[server default]
master_ip_failover_script=/etc/mha/app1/master_ip_failover

# 2.找到之前解压的工具tar包
[root@db01 ~]# ll
-rw-r--r--   1 root root        345 Dec 17 10:19 huifu.sh
drwxr-xr-x  10 4984 users       196 Apr  1  2014 mha4mysql-manager-0.56
drwxr-xr-x   8 4984 users       168 Apr  1  2014 mha4mysql-node-0.56

# 3.进入master工具目录找到这个脚本
[root@db01 ~/mha4mysql-manager-0.56/samples/scripts]# ll
-rwxr-xr-x 1 4984 users  3648 Apr  1  2014 master_ip_failover
-rwxr-xr-x 1 4984 users  9870 Apr  1  2014 master_ip_online_change
-rwxr-xr-x 1 4984 users 11867 Apr  1  2014 power_manager
-rwxr-xr-x 1 4984 users  1360 Apr  1  2014 send_report

# 4.把这个脚本修改好放在manager的工作目录下
[root@db02 /etc/mha/app1]# vim master_ip_failover
my (
...
my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down"; 
...
GetOptions(

# 5.添加执行权限,否则mha无法启动
[root@db02 ~]# chmod +x /etc/mha/app1/master_ip_failover
    
# 6.手动绑定vip
[root@db02 ~]# ifconfig eth0:0 10.0.0.55/24

# 7.查看vip
[root@db02 /etc/mha/app1]# ip a |grep eth0
2: eth0:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 10.0.0.52/24 brd 10.0.0.255 scope global eth0
    inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0

# 8.如果不想配了 
[root@db02 ~]# ifconfig eth0:0 down

2.注意事项!

my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down"; 

#这一串添加的配置 key=0/key=1都可以                 改成0是因为我eth0是外网ip
#但是注意下面的两行 eth0:key 这里要注意

#当你命令行手动绑ip的时候需要写清楚:
key=0
[root@db02 ~]# ifconfig eth0:0 10.0.0.55/24
[root@db02 ~]# ifconfig eth0:0 down

key=1
[root@db02 ~]# ifconfig eth0:1 10.0.0.55/24
[root@db02 ~]# ifconfig eth0:1 down

#如果写错了 就会发生脑裂 如下图:两个服务器上都有10.0.0.55

MHA高可用_第8张图片

MHA高可用_第9张图片

3.MHA做漂移原理

[root@db02 /etc/mha/app1]# ssh 10.0.0.51 "ifconfig eth0:0 10.0.0.55/24"

[root@db01 ~]# ip a |grep eth0
2: eth0:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
    inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0

4.测试ip漂移

# 1.主库上手动绑一次 之后不需要再绑
[root@db01 ~]# ifconfig eth0:0 10.0.0.55/24

# 2.先停止MHA 然后启动MHA
[root@db02 ~]# masterha_stop --conf=/etc/mha/app1.cnf
[root@db02 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/manager.log 2>&1 &
[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:21314) is running(0:PING_OK), master:10.0.0.51

# 3.如果起不来 (脚本格式的问题)
[root@db02 ~]# dos2unix /etc/mha/app1/master_ip_failover

# 4.停掉主库 主库是51
[root@db01 ~]# /etc/init.d/mysqld stop
Shutting down MySQL...... SUCCESS!

# 5.在从库上查看slave信息
db03:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.52
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 120
               Relay_Log_File: db03-relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
db04:
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.52
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 120
               Relay_Log_File: db04-relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
                   
# 6.#在db01上查看vip信息
[root@mysql-db01 ~]# ip a |grep eth0
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0

# 7.在db02上查看vip信息
[root@mysql-db02 ~]# ip a |grep eth0
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 10.0.0.52/24 brd 10.0.0.255 scope global eth0
    inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0

# 8.测试完恢复集群
[root@db01 ~]# sh a.sh
                   
# 9.恢复之后要重新启动MHA
[root@db02 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failo/app1/manager.log 2>&1 &

[root@db02 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:21314) is running(0:PING_OK), master:10.0.0.51   

**5.MHA VIP管理实现自动化恢复集群 **

# 1.每台机器上放恢复脚本
cat huifu.sh 
#!/bin/bash
 
#old_master=`ssh 10.0.0.52 "sed -nr 's#^Master (.*)\(.*!$#\2#gp' /etc/mha/app1/manager.log"` change=`ssh 10.0.0.52 "grep -i 'change master to' /etc/mha/app1/manager.log"|awk -F: '{print $NF}'|sed 's#xxx#123#g'`
 
/etc/init.d/mysqld start
 
mysql -uroot -p123 -e "$change start slave;"
 
ssh 10.0.0.52 '\cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf'
 
# 2.脚本加上调用恢复脚本 
[root@db02 ~]# vim /etc/mha/app1/master_ip_failover 
sub start_vip() {    
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;    `ssh $ssh_user\@$orig_master_host \" /bin/sh /root/huifu.sh \"`; }
    
# 3.脚本需要改善
手动执行 一下cp
[root@db02 ~]# \cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf

十一、配置binlog-server

binlog-server配置:
必须要有5.6以上的版本,支持gtid并开启

如果断电,断网,怎么办?

# 1.添加一个binlog server 
[root@db02 ~]# vim /etc/mha/app1.cnf 
[binlog1]   (可以有多台 也可以是非集群中的任意一台 随便拎出来一个)
no_master=1 (永远不提升成主库)
hostname=10.0.0.53 
master_binlog_dir=/data/mysql/binlog/
 
# 2.创建实时备份binlog的目录 
[root@db03 ~]#  mkdir /data/mysql/binlog/ -p
 
# 3.逻辑备份工具 
1.mysqldump 
2.into out file 
3.binlog 
4.replication 
--------------
5.mysqlbinlog
 
# 4.实时拉取binlog 
[root@db03 ~]# cd /data/mysql/binlog/
[root@db03 /data/mysql/binlog]# mysqlbinlog  -R --host=10.0.0.52 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &
(拉取日志的起点,需要按照目前从库的已经获取到的二进制日志点为起点)

[root@db03 /data/mysql/binlog]# ll
-rw-rw---- 1 root root 120 Dec 18 11:23 mysql-bin.000001
-rw-rw---- 1 root root 143 Dec 18 11:23 mysql-bin.000002
-rw-rw---- 1 root root 357 Dec 18 11:23 mysql-bin.000003
-rw-rw---- 1 root root 143 Dec 18 11:23 mysql-bin.000004
-rw-rw---- 1 root root 143 Dec 18 11:23 mysql-bin.000005
-rw-rw---- 1 root root 120 Dec 18 11:23 mysql-bin.000006

# 5.db02主库操作
mysql> flush logs;

# 6.查看有没有拉取
[root@db03 /data/mysql/binlog]# ll
-rw-rw---- 1 root root 120 Dec 18 11:23 mysql-bin.000001
-rw-rw---- 1 root root 143 Dec 18 11:23 mysql-bin.000002
-rw-rw---- 1 root root 357 Dec 18 11:23 mysql-bin.000003
-rw-rw---- 1 root root 143 Dec 18 11:23 mysql-bin.000004
-rw-rw---- 1 root root 143 Dec 18 11:23 mysql-bin.000005
-rw-rw---- 1 root root 167 Dec 18 11:25 mysql-bin.000006
-rw-rw---- 1 root root 120 Dec 18 11:25 mysql-bin.000007

# 7.重启MHA
[root@db02 ~]# masterha_stop --conf=/etc/mha/app1.cnf
[root@db02 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

注意:之前配置过GTID 那么binlog里就不仅有传统binlog还有GTIDbinlog

要把GTID_mode打开 不然拉取得时候会报错

你可能感兴趣的:(HA,大厂任性挑,数据库,MHA,高可用)