1.MHA简介

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服务器上,因此可以保证所有节点的数据一致性。

2.MHA原理

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

3.MHA工具介绍

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

1.Manager工具:

  • masterha_check_ssh : 检查MHA的SSH配置。
  • masterha_check_repl : 检查MySQL复制。
  • masterha_manager : 启动MHA。
  • masterha_check_status : 检测当前MHA运行状态。
  • masterha_master_monitor : 监测master是否宕机。
  • masterha_conf_host : 添加或删除配置的server信息。
  • masterha_master_switch : 控制故障转移(自动或手动)。
  • masterha_secondary_check:建立TCP连接从远程服务器
  • masterha_stop:停止MHA

2. Node工具

  • save_binary_logs : 保存和复制master的二进制日志。
  • apply_diff_relay_logs : 识别差异的中继日志事件并应用于其它slave。
  • filter_mysqlbinlog : 去除不必要的ROLLBACK事件(防止回滚事件,MHA已不再使用这个工具)。
  • purge_relay_logs : 清除中继日志(不会阻塞SQL线程)。
    注意:Node这些工具通常由MHA Manager的脚本触发,无需人手操作。

MHA优点总结

1)自动故障转移快

2) 主库崩溃不存在数据一致性问题

3)不需要对当前mysql环境做重大修改

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

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

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

4.基于GTID的主从复制

GTID原理介绍
GTID又叫全局事务ID(Global Transaction ID),是一个已提交事务的编号,并且是一个全局唯一的编号。MySQL5.6版本之后在主从复制类型上新增了GTID复制。
GTID是由server_uuid和事务id组成的,即GTID = server_uuid:transaction_id。 server_uuid是在数据库启动过程中自动生成的,每台机器的server-uuid不一样。uuid存放在数据目录的auto.cnf文件下。而transaction_id就是事务提交时由系统顺序分配的一个不会重复的序列号。

GTID存在的价值
(1)GTID使用master_auto_position=1代替了基于binlog和position号的主从复制搭建方式,更便于主从复制的搭建。
(2)GTID可以知道事务在最开始是在哪个实例上提交的。
(3)GTID方便实现主从之间的failover,再也不用不断地去找position和binlog 了。

主从复制中GTID的管理与维护
GTID带来最方便的一点就是主从复制的搭建过程了。它跟异步复制、半同步复制类似,只不过不再利用传统复制模式的binlog文件和position号了,而是在从库“change master to”时使用master_auto_position=1的方式进行搭建,这就让操作变得更加方便和可靠。

先决条件

1.主库和从库开启binlog
2.主库和从库server-id不同
3.创建主从复制用户

主库操作

修改配置文件

  1. #编辑mysql配置文件
  2. [root@mysql-db01 ~]# vim /etc/my.cnf
  3. #在mysqld标签下配置
  4. [mysqld]
  5. server_id =1 #主库server-id为1,从库不等于1
  6. log_bin=mysql-bin #开启binlog日志
  7. #重启mysql
  8. [root@mysql-db01 ~]# /etc/init.d/mysqld restart

创建主从复制用户

  1. #登录数据库
  2. [root@mysql-db01 ~]# mysql -uroot -poldboy123
  3. #创建rep用户(做MHA每个机器都要创建这个用户)
  4. mysql> grant replication slave on *.* to rep@'172.16.1.5%' identified by '123';

从库操作

修改配置文件

  1. #修改mysql-db02配置文件
  2. [root@mysql-db02 ~]# vim /etc/my.cnf
  3. #在mysqld标签下配置
  4. [mysqld]
  5. server_id = 2 #主库server-id为1,从库必须大于1
  6. log_bin=mysql-bin #开启binlog日志
  7. #重启mysql
  8. [root@mysql-db02 ~]# /etc/init.d/mysqld restart
  9. #修改mysql-db03配置文件
  10. [root@mysql-db03 ~]# vim /etc/my.cnf
  11. #在mysqld标签下配置
  12. [mysqld]
  13. server_id = 3 #主库server-id为1,从库必须大于1
  14. log_bin=mysql-bin #开启binlog日志
  15. #重启mysql
  16. [root@mysql-db03 ~]# /etc/init.d/mysqld restart

开启GID

  1. #编辑mysql配置文件(主库从库都需要修改)
  2. [root@mysql-db01 ~]# vim /etc/my.cnf
  3. #在[mysqld]标签下添加
  4. [mysqld]
  5. gtid_mode=ON
  6. log_slave_updates
  7. enforce_gtid_consistency
  8. #重启数据库
  9. [root@mysql-db01 ~]# /etc/init.d/mysqld restart
  10. [root@mysql-db02 ~]# vim /etc/my.cnf
  11. #在[mysqld]标签下添加
  12. [mysqld]
  13. gtid_mode=ON
  14. log_slave_updates
  15. enforce_gtid_consistency
  16. #重启数据库
  17. [root@mysql-db02 ~]# /etc/init.d/mysqld restart
  18. [root@mysql-db03 ~]# vim /etc/my.cnf
  19. #在[mysqld]标签下添加
  20. [mysqld]
  21. gtid_mode=ON
  22. log_slave_updates
  23. enforce_gtid_consistency
  24. #重启数据库
  25. [root@mysql-db03 ~]# /etc/init.d/mysqld restart
  26. #检查GTID状态
  27. mysql> show global variables like '%gtid%';
  28. +--------------------------+-------+
  29. | Variable_name | Value |
  30. +--------------------------+-------+
  31. | enforce_gtid_consistency | ON | #执行GTID一致
  32. | gtid_executed | |
  33. | gtid_mode | ON | #开启GTID模块
  34. | gtid_owned | |
  35. | gtid_purged | |
  36. +--------------------------+-------+

配置主从复制

  1. #所有从库执行 chang master to语句,配置复制主机信息
  2. mysql> change master to
  3. -> master_host='172.16.1.51',
  4. -> master_user='rep',
  5. -> master_password='123',
  6. -> master_auto_position=1;
  7. #开启slave
  8. mysql> start slave;
  9. #查看slave状态
  10. mysql> show slave status\G

5.部署MHA

部署MHA之前的配置:

  1. 1.只有从库配置:
  2. #从库设置只读
  3. mysql> set global read_only=1;
  4. 2.主库和从库都执行:
  5. #在配置文件中设置,关闭MySQL自动清除relaylog的功能,跳过反向解析
  6. [root@mysql-db01 ~]# vim /etc/my.cnf
  7. [mysqld]
  8. relay_log_purge = 0
  9. skip_name_resolve
  10. #关闭MySQL自动清除relaylog的功能
  11. mysql> set global relay_log_purge = 0;

环境准备

  1. #每台机器上传MHA的rpm包
  2. [root@mysql-db01 ~]# ll
  3. mha4mysql-manager-0.56-0.el6.noarch.rpm
  4. mha4mysql-node-0.56-0.el6.noarch.rpm
  5. 部署node节点(3台):
  6. #安装依赖包
  7. [root@mysql-db01 ~]# yum install perl-DBD-MySQL -y
  8. #安装node包(3台):
  9. [root@db-01 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
  10. [root@db-02 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
  11. [root@db-03 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
  12. 部署manager节点(1台:10.0.0.53)
  13. #安装manager依赖包
  14. [root@mysql-db03 ~]# yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
  15. #安装manager包
  16. [root@db-03 ~]# yum localinstall -y mha4mysql-manager-0.56-0.el6.noarch.rpm
  17. #添加mha管理账号(所有节点)
  18. mysql> grant all on *.* to mha@'172.16.1.5%' identified by 'mha';
  19. 命令软连接(所有节点)
  20. #如果不创建命令软连接,检测mha复制情况的时候会报错
  21. [root@db-01 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/
  22. [root@db-01 ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/

配置ssh免密登录

  1. #做ssh 免密登录(下面4条命令,所以节点都执行)
  2. #创建秘钥对
  3. [root@db-01 ~]## ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
  4. #发送公钥,包括自己
  5. [root@db-01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.51
  6. [root@db-01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.52
  7. [root@db-01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.53

编辑配置文件

  1. #在安装manager节点的机器上,创建mha配置文件目录
  2. [root@db-03 ~]# mkdir /etc/mha/
  3. #编辑mha配置文件
  4. [root@mysql-db03 ~]# vim /etc/mha/app1.cnf
  5. [server default]
  6. manager_log=/etc/mha/manager.log #manager的日志
  7. manager_workdir=/etc/mha/app1/ #manager的工作目录
  8. master_binlog_dir=/usr/local/mysql/data #master保存binlog的位置,以便MHA可找到master的日志
  9. password=mha #MHA管理账号的密码
  10. ping_interval=2 #监控主库发送ping包的时间间隔,尝试三次没有回应则切换主库
  11. repl_password=123 #主从复制环境中的用户的密码
  12. repl_user=rep #主从复制环境中的用户名
  13. ssh_user=root #ssh的登录用户名
  14. user=mha #MHA管理账号
  15. [server1]
  16. hostname=172.16.1.51
  17. port=3306
  18. [server2]
  19. hostname=172.16.1.52
  20. port=3306
  21. [server3]
  22. hostname=172.16.1.53
  23. port=3306

MHA启动前检测

  1. #测试ssh
  2. [root@db03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
  3. #看到如下字样,则测试成功
  4. Tue Mar 7 01:03:33 2017 - [info] All SSH connection tests passed successfully.
  5. #测试复制
  6. [root@db03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
  7. #看到如下字样,则测试成功
  8. MySQL Replication Health is OK.

启动MHA

  1. #启动MHA
  2. [root@db03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &
  3. #检测MHA启动状态
  4. [root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
  5. app1 (pid:10434) is running(0:PING_OK), master:172.16.1.52
  1. #启动命令分析
  2. nohup
  3. masterha_manager #MHA的启动程序
  4. --conf=/etc/mha/app1.cnf #指定配置文件
  5. --remove_dead_master_conf #移除宕机的server标签从配置文件里
  6. --ignore_last_failover #忽略上一次的切换
  7. < /dev/null > /etc/mha/manager.log 2>&1 &
  8. MHA的工作机制:
  9. 1.完成一次切换后,会生成一个锁文件在工作目录中
  10. 2.下次切换之前,会检测锁文件是否存在
  11. 3.如果锁文件存在,8个小时之内不允许第二次切换

切换主库测试

  1. #STOP主库
  2. [root@db01 ~]# /etc/init.d/mysqld stop
  3. #在STOP主库同时可以看着manager日志
  4. [root@db03 ~]# tail -f /etc/mha/manager.log
  5. #在db03上可以看到主库以切换成db02
  6. mysql> show slave status\G
  7. *************************** 1. row ***************************
  8. Slave_IO_State: Waiting for master to send event
  9. Master_Host: 172.16.1.52
  10. Master_User: rep
  11. Master_Port: 3306
  12. Connect_Retry: 60
  13. Master_Log_File: mysql-bin.000009
  14. Read_Master_Log_Pos: 231
  15. Relay_Log_File: db03-relay-bin.000002
  16. Relay_Log_Pos: 361
  17. Relay_Master_Log_File: mysql-bin.000009
  18. Slave_IO_Running: Yes
  19. Slave_SQL_Running: Yes

MHA环境修复

  1. 1.修复宕机的主库
  2. [root@db01 ~]# /etc/init.d/mysqld start
  3. 2.MHA的日志中,找到change master 语句
  4. [root@db-03 ~]# grep -i 'change master to' /etc/mha/manager.log
  5. Thu Jul 25 04:38:35 2019 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='172.16.1.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='xxx';
  6. 3.在宕机的主库中执行change master语句
  7. mysql> CHANGE MASTER TO MASTER_HOST='172.16.1.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='123';
  8. 4.开启IOSQL线程,将宕机的主库重新加入集群变成从库
  9. mysql> start slave;
  10. 5.manager配置文件中,将server标签重新添加
  11. [root@db03 ~]# vim /etc/mha/app1.cnf
  12. [server1]
  13. hostname=172.16.1.51
  14. port=3306
  15. 6.启动MHA
  16. [root@db03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &
  17. 7.检测MHA启动状态
  18. [root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
  19. app1 (pid:10434) is running(0:PING_OK), master:172.16.1.52

6.配置VIP漂移

修改MHA主配置文件

  1. [root@db03 ~]# vim /etc/mha/app1.cnf
  2. #在[server default]标签下添加
  3. master_ip_failover_script=/etc/mha/master_ip_failover #使用MHA自带脚本

编辑脚本

  1. #根据配置文件中脚本路径编辑
  2. [root@db03 ~]# vim /etc/mha/master_ip_failover
  3. #修改以下几行内容
  4. my $vip = '172.16.1.55/24';
  5. my $key = '1';
  6. my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
  7. my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
  8. #添加执行权限,否则mha无法启动
  9. [root@db03 ~]# chmod +x /etc/mha/master_ip_failover

手动绑定VIP

  1. #绑定vip
  2. [root@db01 ~]# ifconfig eth1:1 172.16.1.55/24

7.配置binlog-server

修改mha配置文件

  1. [root@db03 ~]# vim /etc/mha/app1.cnf
  2. [binlog1]
  3. no_master=1
  4. hostname=10.0.0.53
  5. master_binlog_dir=/data/mysql/binlog/

备份binlog

  1. #创建备份binlog目录
  2. [root@db03 ~]# mkdir -p /data/mysql/binlog/
  3. #进入该目录
  4. [root@db03 ~]# cd /data/mysql/binlog/
  5. #备份binlog
  6. [root@db03 binlog]# mysqlbinlog -R --host=172.16.1.51 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &
  7. #启动mha
  8. [root@mysql-db03 binlog]# 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 &

8.Atlas

Atlas主要功能

1.读写分离

2.从库负载均衡

3.IP过滤

4.自动分表

5.DBA可平滑上下线DB

6.自动摘除宕机的DB

下载安装Atlas

  1. #下载Atlas
  2. [root@db03 ~]#
  3. wget httpss://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
  4. #安装
  5. [root@db03 ~]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
  6. Preparing... ########################################### [100%]
  7. 1:Atlas ########################################### [100%]

编辑配置文件

  1. #进入Atlas工具目录
  2. [root@db03 ~]# cd /usr/local/mysql-proxy/bin/
  3. #生成密码
  4. [root@db03 bin]# ./encrypt 123
  5. #修改Atlas配置文件
  6. [root@db03 ~]# vim /usr/local/mysql-proxy/conf/test.cnf
  7. #Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
  8. proxy-backend-addresses = 172.16.1.51:3306
  9. #Atlas后端连接的MySQL从库的IP和端口
  10. proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306
  11. #用户名与其对应的加密过的MySQL密码
  12. pwds = rep:3yb5jEku5h4=
  13. #SQL日志的开关
  14. sql-log = ON
  15. #Atlas监听的工作接口IP和端口
  16. proxy-address = 0.0.0.0:1234
  17. #默认字符集,设置该项后客户端不再需要执行SET NAMES语句
  18. charset = utf8

启动

  1. [root@db03 ~]# /usr/local/mysql-proxy/bin/mysql-proxyd test start
  2. OK: MySQL-Proxy of test is started

Atlas管理操作

  1. #用atlas管理用户登录
  2. [root@db03 ~]# mysql -uuser -ppwd -h127.0.0.1 -P2345
  3. #查看可用命令帮助
  4. mysql> select * from help;
  5. #查看后端代理的库
  6. mysql> SELECT * FROM backends;
  7. +-------------+----------------+-------+------+
  8. | backend_ndx | address | state | type |
  9. +-------------+----------------+-------+------+
  10. | 1 | 10.0.0.51:3307 | up | rw |
  11. | 2 | 10.0.0.53:3307 | up | ro |
  12. | 3 | 10.0.0.52:3307 | up | ro |
  13. +-------------+----------------+-------+------+
  14. #平滑摘除mysql
  15. mysql> REMOVE BACKEND 2;
  16. Empty set (0.00 sec)
  17. #检查是否摘除成功
  18. mysql> SELECT * FROM backends;
  19. +-------------+----------------+-------+------+
  20. | backend_ndx | address | state | type |
  21. +-------------+----------------+-------+------+
  22. | 1 | 10.0.0.51:3307 | up | rw |
  23. | 2 | 10.0.0.52:3307 | up | ro |
  24. +-------------+----------------+-------+------+
  25. #保存到配置文件中
  26. mysql> SAVE CONFIG;
  27. Empty set (0.06 sec)