首页 » MySQL/TiDB/GoldenDB » MySQL高可用方案:Master High Active(MHA) (一)

MySQL高可用方案:Master High Active(MHA) (一)

MySQL High Availability目前常见有以下解决方案:
● MySQL Replication (99.9%)
MHA/Orchestrator by Github and MySQL Replication (99.99%)
● Percona XtraDB Cluster/Galera (99.999%)
● MySQL InnoDB Cluster MGR (99.999%)
● MySQL NDB Cluster (99.999%)

1,背景

随着MySQL的推广使用越来越广泛, MySQL的高可用性变得越来越重要,  本篇主要介绍MySQL基于一个方案MHA,  MHA 是有当时日本DeNA公司youshimaton于2011年首次公开,目前作者在facebook。MHA是一套优秀的作为MySQL高可用性环境下,能做到30秒内自动故障切换和主从提升的高可用软件(同样也支持手动切换)。 以Perl语言编程的方式监控和故障转移管理, 补齐中继日志最大程度保证数据完整. 尽管当前版本还在0.几,但当前这套解决方案仍然广泛采用。

MHA 也是和之前的MMM(http://mysql-mmm.org)类似, 基于MySQL复制的冗余,复制无法保证实时的数据同步和零数据的丢失,MHA是复制管理器,同样也是一套脚本集,MHA不会重建现有的replication link, 只是做master和slave的reconfigure, 是只负责failover,但是也有能力增加自定议脚本是应用程序处理变化,如切换VIP或修改全局文件等。MHA同样在生产环境中还会与半自动同步和KeepAlive、由RenéCannaò创建的ProxySQL 等共用提高可用性,把MySQL组合在一起,可以在不修改应用程序的情况下将流量定向到特定的服务器。 下一个出现的重要解决方案是Shlomi Noach的Orchestrator,它是可用于复制管理需求的可用选项菜单的最新成员。为了使事情更直观,它包括一个图形Web界面。有很多很棒的解决方案可以帮助您在发生故障时保持MySQL环境正常运行。如果您尚未实施GTID并且还不太愿意使用它或伪GTID,请考虑MHA。如果你运行GTID一个系统,你可以考虑Orchestrator的。

MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上,生产环境中多数单独部署。 MHA Node运行在每个MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将判断最新数据的slave提升为新的master,并将所有其他的slave重新指向新的master。

在一个Master node CRASH时,MHA 负责Master-Slave Auto-failover,默认情况下,MySQL复制是异步的。MHA试图从宕机的主服务器上保存二进制日志,通过ssh补齐日志,所以需要root用户,同时负载启停VIP. 如果主服务器崩溃,则它已提交的事务可能尚未传输到任何从服务器。因此,在这种情况下从主服务器到从服务器的故障转移可能导致事务丢失,所以通常还需要使用半同步替代异步,与半同步复制相结合,可以降低由于主硬件故障导致数据丢失的风险。

MHA进行Failover过程:

1)MHA MGR检测到Master异常,进行多项判断校验Master宕掉;
2)根所配置信息,确认出当前架构中所有节点的状态;
3)根据预定义的脚本处理故障的Master,VIP漂移或者停止mysqld服务;
4)所有当前的Slave节点比较位点,选出位点最新的Slave,再与Master比较并获得binlog的差异,copy到管理节点;
5)从候选节点中选择新的Master,新的Master会和位点最新的Slave进行比较并获得relay log的差异;
6)管理节点把binlog的差异copy到新Master,新Master应用binlog差异和relaylog差异,最后获得位点信息,并接受写请求(read_only=0);
7)其他Slave与位点最新的Slave进行比较,并获得relaylog的差异,copy到对应的Slave;
8)管理节点把binlog的差异copy到每个Slave,比较Exec_Master_Log_Pos和Read_Master_Log_Pos,获得差异日志;
9)每个Slave应用所有差异日志,然后reset slave并重新指向新Master;
10)新Master reset slave来清除Slave信息

MHA 的前提条件:
1) MySQL Replication必须已在运行。 MHA管理复制并对其进行监控,但它不是部署工具。
2) 所有主机都应该能够使用公共SSH密钥相互连接。
3) 所有节点都需要能够连接到彼此的MySQL服务器。
4)   所有节点都应具有相同的replication user 和password。
5)   在 multi-master 情况下,只允许一个可写节点。
6)   MySQL版本必须为5.0或更高版本。
7)   Master故障转移的候选者应启用binary log。 replication user 也必须存在。
8)  所有服务器上的二进制日志过滤变量应该相同(replicate-wild%,binlog-do-db …)。
9)  禁用自动relay-log清理并定期从cron任务执行。 您可以使用名为“purge_relay_logs”的MHA包含的脚本。


这里我们在VM环境安装MHA, MHA管理放到第1个slave1主机上。同时会配置半同步。

2, MySQL 编译安装

1, 安装MySQL ON OEL7

[root@master ~]# cat /etc/hosts
127.0.0.1   localhost master
::1         localhost master
192.168.56.200 master
192.168.56.201 slave1
192.168.56.202 slave2
192.168.56.201 mha_mgr

vi /etc/selinux/config
SELINUX=disabled

禁用防火墙,否则后期slave无法连接master
[root@master ~]# systemctl disable firewalld.service
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

--下载 MySQL 5.7.26 安装介质 
# wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.26-el7-x86_64.tar.gz

[root@master ~]# ls
anaconda-ks.cfg  mysql-5.7.26-el7-x86_64.tar.gz
[root@master ~]# tar zxvf mysql-5.7.26-el7-x86_64.tar.gz -C /usr/local/

# groupadd mysql
# useradd -r -g mysql -s /bin/false mysql
# tar zxvf mysql-5.7.14-linux-glibc2.5-x86_64.tar.gz -C /usr/local/
# cd /usr/local/
# ln -s /usr/local/mysql-5.7.14-linux-glibc2.5-x86_64 mysql
# cd mysql
# mkdir data
# chmod 750 data
# chown -R mysql .
# chgrp -R mysql .
# bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
# [Note] A temporary password is generated for root@localhost: A1Qw;meU*Nd1

# bin/mysql_ssl_rsa_setup
# chown -R root .
# chown -R mysql data
# cp support-files/mysql.server /etc/init.d/mysql

# cp support-files/mysql.server /etc/init.d/mysql
# chkconfig --add mysql

-- 配置环境变量
# vi .bash_profile
# PATH=$PATH:$HOME/bin:/usr/local/mysql/bin/
#export PATH

# vi /etc/my.conf

[mysqld]
character_set_server=utf8
port=3306
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
user=mysql

#replication options
server-id=200
log-bin=mysql-bin
log-bin-index=mysql-bin.index
binlog_format=mixed
skip-name-resolve
expire_logs_days=14
skip-slave-start
relay-log-purge=0
relay-log=mysql-relay-bin
relay-log-index=mysql-relay-bin.index

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

[mysqld_safe]
log-error=/usr/local/mysql/data/mysqld.log
pid-file=/usr/local/mysql/data/master.pid

-- change mysql root password to anbob;
# mysqladmin -u root -h127.0.0.1 -p password "anbob"

-- 启动MySQL
# /etc/init.d/mysql start
OR
[root@master ~]# service mysql start
Starting MySQL. SUCCESS!

3, 配置主从同步和半自动同步

配置SSH 互信

–on master 192.168.56.22

ssh-keygen -t rsa
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.56.201
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.56.202

其它从库一样copy到其它node。

配置主从同步

[root@master ~]# mysql -u root -p
Enter password:

mysql> grant replication slave on *.* to 'rpl'@'192.168.56.%' identified by 'mysql';
Query OK, 0 rows affected, 1 warning (0.08 sec)

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

mysql> SHOW VARIABLES LIKE 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
1 row in set (0.00 sec)
--or
mysql> SELECT @@log_bin;

mysql> SHOW BINARY LOGS
    -> ;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       154 |
| mysql-bin.000002 |       154 |
| mysql-bin.000003 |       177 |
| mysql-bin.000004 |       154 |
+------------------+-----------+
4 rows in set (0.00 sec)

-- 从Master导出数据库
mysqldump -uroot -p --master-data=2 --single-transaction --default-character-set=utf8 -R --triggers -A >all.sql

-- 检查日志位置
[root@master ~]# head -n 30 all.sql|grep -i "CHANGE MASTER TO"
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=154;
[root@master ~]# scp all.sql root@192.168.56.201:/root
[root@master ~]# scp all.sql root@192.168.56.202:/root
[root@master ~]# scp /etc/my.cnf root@192.168.56.201:/etc
[root@master ~]# scp /etc/my.cnf root@192.168.56.202:/etc

Note: 并修改SLAVE的server-id 分别为201和202. 启动slave上的MySQL 数据库服务,

如果是slave 主机是clone的master主机,同样还要修改$data_dir/auto.cnf  文件中的UUID, 删除掉可以自动生成

[root@master data]# cd /usr/local/mysql/data
[root@master data]# mv auto.cnf auto.cnf.bak

在所有SLAVE数据库上创建备库

[root@slave2 ~]# mysql -uroot -p change master to master_host='192.168.56.200',master_user='rpl',master_password='mysql',master_port=3306,master_log_file='mysql-bin.000004',master_log_pos=154;

所有节点安装半同步插件

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; 
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_master_enabled=on ;  

启动主从同步

mysql> start slave;
mysql> set global read_only=1;

检查

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000016 |     1589 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql>  show slave hosts;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID                           |
+-----------+------+------+-----------+--------------------------------------+
|       202 |      | 3306 |       200 | 81a7ae3c-a22c-11e9-bbbf-080027032e78 |
|       201 |      | 3306 |       200 | 3ccfe5d1-a22c-11e9-a10b-08002738fa8b |
+-----------+------+------+-----------+--------------------------------------+
2 rows in set (0.00 sec)

mysql> show status like 'Rpl_semi_sync_master%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 2     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+

mysql> Show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.56.200
                  Master_User: rpl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000015
          Read_Master_Log_Pos: 315
               Relay_Log_File: mysql-relay-bin.000021
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000015
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:

Note: 如果Rpl_semi_sync_master_clients 值为0,表示半自动slave没发现,需要重启同步和半自动:
需要重启从库的复制(在从库上先stop slave然后再start slave)
然后重启主库的半同步复制(先set global rpl_semi_sync_master_enabled=off; 再set global rpl_semi_sync_master_enabled=on;)
从库一样要set global rpl_semi_sync_master_enabled=on;
有事务同步Rpl_semi_sync_master_yes_tx值会增长。

4, 配置MHA

安装依赖的环境,这里使用离线系统盘做yum源.

# mount /dev/cdrom /mnt
mount: /dev/sr0 is write-protected, mounting read-only

# vi /etc/yum.repos.d/public-yum-ol7.repo
[oel7]
name = Enterprise Linux 7.3 DVD
baseurl=file:///mnt/
gpgcheck=0
enabled=1

# yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN

安装MHA NODE

# ls
all.sql  anaconda-ks.cfg  mha4mysql-node-master.zip  mysql-5.7.26-el7-x86_64.tar.gz
# unzip mha4mysql-node-master.zip
# cd mha4mysql-node-master
# perl Makefile.PL
# make && make install
打赏

对不起,这篇文章暂时关闭评论。