MHA高可用

目录

今日内容概述

1.MHA高可用概述
2.MHA的工作原理
3.MHA的优点总结
4.GTID主从复制
5.GTID主从复制的优缺点
6.GTID主从复制部署
7.MHA部署

今日内容详细

1.MHA高可用概述

# MHA简介
MHA(Master High Availability)是由日本人 yoshinorim(原就职于DeNA现就职于FaceBook)开发的一款成熟的、开源的 MySQL 的高可用程序。它为 MySQL 主从复制架构提供了自动故障切换( automating master failover) 功能。 MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的master 节点,在此期间,MHA 会通过于其它从节点获取额外信息来避免一致性方面的问题,从而在最大程度上保证数据的一致性,以达到真正意义上的高可用,而且整个故障转移过程对应用程序完全透明。最值得称赞的一点是:这一自动故障切换操作,MHA能在10~30秒之内完成。	# 然而对数据库而言还是太久了

此外,MHA 还提供了 master 节点的在线切换功能,即按需切换 master/slave 节点,大概0.5-2秒内即可完成。

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,例如一主二从。因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝的TMHA已经支持一主一从。

2.MHA的工作原理

MHA的组成

MHA由node和manager组成
1.MHA Node(数据节点:
相当于监控客户端,所有机器都需要部署node

2.MHA Manager(管理节点)
Manager相当于服务端,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master(如果原主库恢复,只能当从库)。

通常单独部署在一*立机器上管理多个master/slave集群(组),每个master/slave集群称作一个 application,用来管理统筹整个集群。

Manager应该尽量避免部署在主库上,否则主库一挂则全挂,不仅主库完蛋了,负责自动迁移的Manager也完蛋了,也没人负责自动故障迁移了,导致架构不可用了。

可以考虑部署在某一个slave上,此时这台主机挂掉了,只是挂了一个slave,以及Manager需要注意的一点是:如果Manager部署在slave上,那么该slave就无法被升级为主库;

# 如下图我们可以看出,每个复制组内部和Manager之间都需要ssh实现无密码互联,只有这样,在Master出故障时,Manager才能顺利的连接进去,实现主从切换。

MHA高可用

MHA自动故障切换的步骤

1.Manager会每隔3秒钟探测一次MASTER主库	# 检测主库是否存活

2.如果Manager探测到MASTER主库故障、无法访问,Manager会执行下面操作:
从其他node发起ssh连接,检查主库是否能够SSH上去
从其他node发起mysql连接,检查MASTER库是否能够登陆

3.如果所有的Node节点ssh连接、mysql主库连接均连接失败,则开始故障转移
简单概括下步骤为:
	1.)找到数据最新的从库(通过对比relay-log,查看show slave status即可)
	2.)将最新的从库上的新数据同步到其他从库
	3.)提升一个从库为主库(一般情况提升数据最新的,二般情况提升我们指定的从库为主库)
	4.)通过原来主库的binlog补全新的主库数据
	5.)其他从库以新的主库为主做主从复制

3.MHA的优点总结

1. 自动的故障检测与转移,通常在10-30秒以内
2. MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。
3. 很好地解决了主库崩溃数据的一致性问题。
4. 不需要对当前的mysql环境做重大修改。
5. 不需要在现有的复制框架中添加额外的服务器,仅需要一个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量。
6. 性能优秀,可以工作在半同步和异步复制框架,支持gtid,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。
7. 只要replication支持的存储引擎都支持MHA,不会局限于innodb。
8. 对于一般的keepalived高可用,当vip在一台机器上的时候,另一台机器是闲置的,而MHA中并没有闲置的主机。

4.GTID主从复制

什么是GTID主从复制?

从MySQL 5.6.2 开始新增了一种基于 GTID 的复制方式,用以替代以前传统的复制方式,到MySQL5.6.10后逐渐完善。通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。这种方式强化了数据库的主备一致性,故障恢复以及容错能力.

在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用自MySQL 5.5开始引入的半同步复制,可以大大降低数据丢失的风险。

MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性,或者采用GTID。

要想在分布式集群环境中不丢失事务,就必须为每个事务定制一个全局唯一的ID号,并且该ID是趋势递增的,以此我们便可以方便地顺序读取、不丢事务,其实GTID就是一种很好的分布式ID实践方案,它满足分布ID的两个基本要求:
# 全局唯一性
# 趋势递增
  
GTID (Global Transaction ID全局事务ID)是如何做到全局唯一且趋势递增的呢,它是由UUID+TID两部分组成。
# UUID是数据库实例的标识符
# TID表示事务提交的数量,会随着事务的提交递增

因此它与主库上提交的每个事务相关联,GTID不仅对其发起的服务器是唯一的,而且在给定复制设置中的所有服务器都是唯一的,即所有的事务和所有的GTID都是1对1的映射。

当在主库上提交事务或者被从库应用时,可以定位和追踪每一个事务,对DBA来说意义就很大了,我们可以适当的解放出来,不用手工去可以找偏移量的值了,而是通过CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION=1的即可方便的搭建从库,在故障修复中也可以采用MASTER_AUTO_POSITION= 'X' 的方式。
5.7版本GTID做了增强,不手工开启也自动维护匿名的GTID信息。

GTID主从的原理

1)一个GTID的生命周期

1.事务在主库上执行并提交给事务分配一个gtid(由主库的uuid和该服务器上未使用的最小事务序列号),该GTID被写入到binlog中。
 
2.备库读取relaylog中的gtid,并设置session级别的gtid_next的值,以告诉备库下一个事务必须使用这个值
 
3.备库检查该gtid是否已经被其使用并记录到他自己的binlog中。slave需要担保之前的事务没有使用这个gtid,也要担保此时已分读取gtid,但未提交的事务也不恩呢过使用这个gtid.
 
4.由于gtid_next非空,slave不会去生成一个新的gtid,而是使用从主库获得的gtid。这可以保证在一个复制拓扑中的同一个事务gtid不变。由于GTID在全局的唯一性,通过GTID,我们可以在自动切换时对一些复杂的复制拓扑很方便的提升新主库及新备库,例如通过指向特定的GTID来确定新备库复制坐标

2)图解

MHA高可用

同样的GTID不能被执行两次,如果有同样的GTID,会自动被skip掉

salve1:将自己的UUID1:1发送给master,然后接收到了UUID1:2,UUID1:3 event

salve2:将自己的UUID1:1,UUID1:2发送给master,然后接收到了UUID1:3event

5.GTID主从复制的优缺点

GTID的优点

一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次。

GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置。

减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机。

GTID的缺点

不支持非事务引擎。

不支持create table ... select 语句复制(主库直接报错);(原理: 会生成两个sql, 一个是DDL创建表SQL, 一个是insert into 插入数据的sql; 由于DDL会导致自动提交, 所以这个sql至少需要两个GTID, 但是GTID模式下, 只能给这个sql生成一个GTID)。

不允许一个SQL同时更新一个事务引擎表和非事务引擎表。

在一个复制组中,必须要求统一开启GTID或者是关闭GTID。

开启GTID需要重启 (mysql5.7除外)。

开启GTID后,就不再使用原来的传统复制方式。

对于create temporary table(创建临时表) 和 drop temporary table (删除临时表)语句不支持。

不支持sql_slave_skip_counter(跳过错误)。

6.GTID主从复制部署

环境准备

机器名称 IP地址 角色 备注
manager 172.16.16.50 Manager控制器 用于监控管理
master 172.16.16.52 主数据库服务器 开启binlog、relay-log,关闭relay_log_purge
slave1 172.16.16.53 从1数据库服务器 开启binlog、relay-log,关闭relay_log_purge、设置read_only=1
slave2 172.16.16.54 从2数据库服务器 开启binlog、relay-log,关闭relay_log_purge、设置read_only=1
其中master对外提供写服务,备选master提供读服务,salve页提供相关的读服务,一旦master宕机,将会把备选master提升为新master,slave指向新的master,manager作为管理服务器。

主库配置

1.准备一台纯净的linux主机,二进制安装MySQL5.7,初始化,配置环境变量,配置systemctl管理,配置好配置文件后重启

[root@mysql_master mysql_data]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8mb4
log-error=/var/log/mysqld.log
pid-file=/tmp/mysqld.pid
server-id = 1                                
binlog_format='row'                          
log-bin = /var/lib/mysql/mybinlog
skip-name-resolve
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
relay_log_purge=0
sync_binlog=1            
expire_logs_days = 7                        
max_binlog_size = 100M
binlog_cache_size=4m
max_binlog_cache_size=512m                        
binlog_rows_query_log_events=on          
			
[mysql]
socket=/usr/local/mysql/mysql.sock

[client]
socket=/usr/local/mysql/mysql.sock

systemctl restart mysqld

2.增加主从复制的用户
GRANT REPLICATION SLAVE ON *.* TO 'jerry'@'%' IDENTIFIED BY '123';
flush privileges;

从库配置

1.准备一台纯净的linux主机,二进制安装MySQL5.7,初始化,配置环境变量,配置systemctl管理,配置好配置文件后重启

[root@mysql_salve01 ~]# cat /etc/my.cnf 
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8mb4
log-error=/var/log/mysqld.log
pid-file=/tmp/mysqld.pid

# 中继日志
relay-log=mysql-relay-bin
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%

# 节点ID,确保唯一
server-id=2
binlog_format=row
log-bin=mysql-bin
skip-name-resolve
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
relay_log_purge=0
sync_binlog=1
expire_logs_days=7
#binlog每个日志文件大小
max_binlog_size=100m
#binlog缓存大小
binlog_cache_size=4m 
#最大binlog缓存大小
max_binlog_cache_size=512m
			
[mysql]
socket=/usr/local/mysql/mysql.sock

[client]
socket=/usr/local/mysql/mysql.sock

从库执行
mysql> change master to 
    ->     master_host='172.16.1.53',
    ->     master_user='jerry',
    ->     master_password='123',
    ->     MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G
# 结果如下图

MHA高可用

MHA高可用

创建MHA管理用户

在主库创建
mysql> grant all on *.* to 'mhaadmin'@'%' identified by '123';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

# 因为已经成功部署GTID主从复制,所以从库也有这个用户

设置从库可读

# 在从库上进行操作
# 设置只读,不要添加配置文件,因为从库以后可能变成主库
mysql> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show global variables like "%read_only%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | OFF   |
| read_only             | ON    |
| super_read_only       | OFF   |
| transaction_read_only | OFF   |
| tx_read_only          | OFF   |
+-----------------------+-------+
5 rows in set (0.00 sec)

关闭MySQL自动清除relaylog的功能

# 关闭MySQL自动清除中继日志功能
这一步已经在之前的配置文件中配置好了
[mysqld]
#禁用自动删除relay log永久生效
relay_log_purge = 0

7.MHA部署

配置免密登录(所有主机之间互做)

# 创建秘钥对
# 正常创建 ssh-keygen 需要交互,按回车,可以用一下方法跳过交互
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa &> /dev/null

# 发送公钥,包括自己
for i in 50 52 53 54;do ssh-copy-id -i ~/.ssh/id_dsa.pub root@192.168.174.${i};done

安装依赖包(所有机器都执行)

# 安装yum源
wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
 
# 安装MHA依赖的perl包
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager

wget https://qiniu.wsfnk.com/mha4mysql-node-0.58-0.el7.centos.noarch.rpm --no-check-certificate

rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm

然后再去manager主机安装manager包

wget https://qiniu.wsfnk.com/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm --no-check-certificate
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm

配置MHA Manager

# 创建工作目录
mkdir -p /service/mha/
mkdir /service/mha/app1

修改配置

vim /service/mha/app1.cnf

[server default]            
#日志存放路径
manager_log=/service/mha/manager.log
#定义工作目录位置
manager_workdir=/service/mha/app1
#binlog存放目录(如果三台数据库机器部署的路径不一样,可以将配置写到相应的server下面)
#master_binlog_dir=/usr/local/mysql/data
 
#设置ssh的登录用户名
ssh_user=root
#如果端口修改不是22的话,需要加参数,不建议改ssh端口
#否则后续如负责VIP漂移的perl脚本也都得改,很麻烦
ssh_port=22
 
#管理用户
user=mhaadmin
password=123
 
#复制用户
repl_user=jerry
repl_password=123
 
#检测主库心跳的间隔时间
ping_interval=1
 
[server1]
# 指定自己的binlog日志存放目录
master_binlog_dir=/mysql_data
hostname=172.16.1.52
port=3306
 
[server2]
#暂时注释掉,先不使用
#candidate_master=1
#check_repl_delay=0
master_binlog_dir=/mysql_data
hostname=172.16.1.53
port=3306
 
[server3]
master_binlog_dir=/mysql_data
hostname=172.16.1.54
port=3306
 
# 1、设置了以下两个参数,则该从库成为候选主库,优先级最高
# 不管怎样都切到优先级高的主机,一般在主机性能差异的时候用         
candidate_master=1
# 不管优先级高的备选库,数据延时多久都要往那切
check_repl_delay=0
 
# 2、上述两个参数详解如下:
# 设置参数candidate_master=1后,则判断该主机为为候选master,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave。
 
# 默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master
 
# 3、应该为什么节点设置这俩参数,从而把该节点的优先级调高
# (1)、多地多中心,设置本地节点为高权重
# (2)、在有半同步复制的环境中,设置半同步复制节点为高权重
# (3)、你觉着哪个机器适合做主节点,配置较高的 、性能较好的

检测mha配置状态

# 测试免密连接
1.使用mha命令检测ssh免密登录
masterha_check_ssh --conf=/service/mha/app1.cnf
    ALL SSH ... successfilly 表示ok了
 
2.使用mha命令检测主从状态
masterha_check_repl --conf=/service/mha/app1.cnf
    ... Health is OK
 
# 如果出现问题,可能是反向解析问题,配置文件加上
    skip-name-resolve
# 还有可能是主从状态,mha用户密码的情况

启动MHA

nohup masterha_manager --conf=/service/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /service/mha/manager.log 2>&1 &
 
命令参数:
--remove_dead_master_conf       该参数代表当发生主从切换后,宕机库的配置信息将会从配置文件中移除。
--manger_log                    日志存放位置
--ignore_last_failover          在缺省情况下,如果MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover,之所以这样限制是为了避免ping-pong效应。该参数代表忽略上次MHA触发切换产生的文件,默认情况下,MHA发生切换后会在日志目录,也就是上面设置的manager_workdir目录中产生app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为--ignore_last_failover。
 
# MHA的安全机制:
    1.完成一次切换后,会生成一个锁文件在工作目录中
    2.下次切换之前,会检测锁文件是否存在
    3.如果锁文件存在,8个小时之内不允许第二次切换 
上一篇:Transformer架构记录(二)


下一篇:Blog.067 MySQL 数据库 MHA 高可用集群部署及故障切换