搭建MySQL的高可用架构(MHA)

mac2025-11-11  9

1.MHA简介

MHA(Master High Availability)是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中, MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。 MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。 MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点/master结点上。 MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master, 然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。 在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。 例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。 使用MySQL 5.5的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。 如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

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

masterha_check_ssh #检查MHA的SSH配置状况 masterha_check_repl #检查MySQL复制状况 masterha_manger #启动MHA masterha_check_status #检测当前MHA运行状态 masterha_master_monitor #检测master是否宕机 masterha_master_switch #控制故障转移(自动或者手动) masterha_conf_host 添加或删除配置的server信息

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

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

实验前提:

注意:主从复制的前提是,数据高度一致性,如果你之前已经做好了一主一从,再继续添从库时,会出现SQL线程连接失败,因为此时主库与新添加的从库数据不一致 ,为了避免此类问题,建议重新打开3个虚拟机做一主二从,保证实验环境的纯净

先做好一主二从的基于GTID的主从复制与半同步复制(基于GTID主从复制在复制过程中更加方便,而半同步复制有效的避免了数据的丢失)

1.配置一主二从

为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL 5.5的半同步复制

安装包:

mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar

点击此处查看MySQL主从复制,半同步复制等具体步骤 (1).基于GTID的主从复制 配置master端:

#1.解压并安装数据库 [root@server1 ~]# ls mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar [root@server1 ~]# tar -xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar [root@server1 ~]# ls

[root@sever1 ~]# yum install -y mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm [root@sever1 ~]# scp mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm root@172.25.66.2: [root@sever1 ~]# scp mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm root@172.25.66.3: 2.更改文件 [root@server1 mysql]# vim /etc/my.cnf ##################### server-id=1 log-bin=mysql-bin gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON

#3.开启数据库 [root@server1 mysql]# systemctl start mysqld #4.查看初始密码 [root@server1 mysql]# cat /var/log/mysqld.log | grep password #5.初始化 [root@sever1 ~]# mysql_secure_installation #6.登陆数据库并用户授权 [root@server1 ~]# mysql -u root -pWestos+001 #用户授权 mysql> grant replication slave on *.* to repl@'172.25.66.%' identified by 'Westos+001'; #刷新授权表 mysql> flush privileges;

配置slave端:(server2) #1.安装数据库

[root@sever2 ~]# ls

[root@sever2 ~]# yum install -y * #2.更改配置文件;仅server-id不同 [root@server2 mysql]# vim /etc/my.cnf ##################### server-id=2 log-bin=mysql-bin gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON

#3.开启数据库 [root@server2 mysql]# systemctl start mysqld #4.查看初始密码 [root@server2 mysql]# cat /var/log/mysqld.log | grep password #5.初始化 [root@sever2 ~]# mysql_secure_installation #6.复制主库 [root@server2~]# mysql -u root -p'Westos+001' #GTID方式复制主库 mysql> change master to master_host='172.25.66.1',master_user='repl',master_password='Westos+001',MASTER_AUTO_POSITION = 1; #开启slave mysql> start slave; #查看slave的状态 mysql> show slave status\G;

配置slave端:(server3) 操作步骤完全同server2结点

#1.安装数据库 [root@sever3 ~]# ls [root@sever3 ~]# yum install -y * #2.更改配置文件;仅server-id不同 [root@server3 mysql]# vim /etc/my.cnf ##################### server-id=3 log-bin=mysql-bin gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON

#3.开启数据库 [root@server3 mysql]# systemctl start mysqld #4.查看初始密码 [root@server3 mysql]# cat /var/log/mysqld.log | grep password 2019-02-26T06:37:39.817817Z 1 [Note] A temporary password is generated for root@localhost: lVyoaMAbj8(! #5.初始化 [root@sever3 ~]# mysql_secure_installation #6.复制主库 [root@server3~]# mysql -u root -p'Westos+001' #GTID方式复制主库 mysql> change master to master_host='172.25.66.1',master_user='repl',master_password='Westos+001',MASTER_AUTO_POSITION = 1; #开启slave mysql> start slave; #查看slave的状态 mysql> show slave status\G;

(2).半同步复制 查看链接配置半同步复制

2.配置MHA高可用

注意:

server1和server2和server3结点上都有解析(/etc/hosts)

配置管理机:

为了节省结点,我们将server1设定为既是master又是管理机

1.安装软件

在主库安装MHA Manage:(perl是依赖包)

[root@server1 ~]# ls

[root@server1 ~]# yum install -y * [root@server1 ~]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm server2: [root@server1 ~]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm server3:

在从库安装MHA Node:

[root@server2 ~]# ls mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@server2 ~]# yum install -y * [root@server3 ~]# ls mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@server3 ~]# yum install -y *

2.设定ssh免密

(1)管理机可以免密连接其他结点

[root@server1 ~]# ssh-keygen

[root@server1 ~]# ssh-copy-id server1

[root@server1 ~]# ssh-copy-id server2

[root@server1 ~]# ssh-copy-id server3

测试:

[root@server1 ~]# ssh server1 Last login: Tue Feb 26 12:57:24 2019 from foundation66.localdomain [root@server1 ~]# exit logout Connection to server1 closed. [root@server1 ~]# ssh server2 Last login: Tue Feb 26 13:08:35 2019 from foundation66.localdomain [root@server2 ~]# exit logout Connection to server2 closed. [root@server1 ~]# ssh server3 Last login: Tue Feb 26 14:23:17 2019 from foundation66.localdomain [root@sever3 ~]# exit logout Connection to server3 closed.

(2)主从结点之间相互免密 只需将在管理机端生成的公钥和私钥发送给其他结点即可

[root@server1 ~]# cd .ssh/ [root@server1 .ssh]# ls authorized_keys id_rsa id_rsa.pub known_hosts [root@server1 .ssh]# cd #将.ssh/整个目录发送到其他结点 [root@server1 ~]# scp -r .ssh/ server2: [root@server1 ~]# scp -r .ssh/ server3:

测试:

server结点就不用再测试了,因为它既是master又是管理结点,管理结点刚已经测试过了

server2可以免密连接其他结点:

[root@server2 ~]# cd .ssh/ [root@server2 .ssh]# ls authorized_keys id_rsa id_rsa.pub known_hosts [root@server2 .ssh]# ssh server1 Last login: Tue Feb 26 15:58:03 2019 from server2 [root@server1 ~]# exit logout Connection to server1 closed. [root@server2 .ssh]# ssh server3 Last login: Tue Feb 26 15:58:11 2019 from sever2 [root@sever3 ~]# exit logout Connection to server3 closed.

server3可以免密连接其他结点:

[root@sever3 ~]# cd .ssh/ [root@sever3 .ssh]# ls authorized_keys id_rsa id_rsa.pub known_hosts [root@sever3 .ssh]# ssh server1 Last login: Tue Feb 26 15:58:26 2019 from server2 [root@server1 ~]# exit logout Connection to server1 closed. [root@sever3 .ssh]# ssh server2 Last login: Tue Feb 26 15:58:06 2019 from server2 [root@server2 ~]# exit logout Connection to server2 closed.

3.编写配置文件

[root@server1 ~]# mkdir /etc/masterha [root@server1 ~]# cd /etc/masterha/ [root@server1 masterha]# vim app1.conf ######################## [server default] #默认设置 manager_workdir=/etc/masterha #指定manager工作目录 manager_log=/var/log/masterha.log #指定manager日志存放路径 master_binlog_dir=/etc/masterha #指定mysql的数据目录 user=root #设定管理员用户 password=Westos+001 #设置管理员密码 ping_interval=1 #设置监控频率,默认是3秒,尝试三次没有回应的时候自动进行railover remote_workdir=/tmp #设置远端mysql在发生切换时,binlog(二进制日志)的保存位置 repl_user=repl #设置复制环境中的复制用户名 repl_password=Westos+001 #设置复制用户的密码 ssh_user=root #设置免密用户 [server1] #master hostname=172.25.66.1 port=3306 [server2] #salve hostname=172.25.66.2 port=3306 candidate_master=1 #设置为候选master check_repl_delay=0 #忽略复制延 [server3] #salve hostname=172.25.66.3 port=3306 no_master=1 #不竞选master

3.测试 1.检测ssh免密

[root@server1 masterha]# masterha_check_ssh --conf=/etc/masterha/app1.conf

排错:若出现如下报错,一定是主从结点的免密没有做好 2.检测复制过程

报错:不允许root用户远程登陆

[root@server1 masterha]# masterha_check_repl --conf=/etc/masterha/app1.conf

解决方案:在master端,给root用户添加权限即可

[root@server1 masterha]# mysql -u root -p'Westos+001' #给root用户授权 mysql> grant all on *.* to root@'%' identified by 'Westos+001'; [root@server1 masterha]# masterha_check_repl --conf=/etc/masterha/app1.conf

根据提示,设定slave端只读:

[root@server2 ~]# mysql -u root -p'Westos+001' mysql> set global read_only=1; [root@server3 ~]# mysql -u root -p'Westos+001' mysql> set global read_only=1

3.检测故障切换

1.手动切换

(1).故障切换

模拟主库master宕机:

#关闭数据库 [root@server1 ~]# systemctl stop mysqld

手动切换:

#由于server1(主库)已经宕机,此时将手动master切换到server2结点上 [root@server1 ~]# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.conf --dead_master_host=172.25.66.1 --dead_master_ip=172.25.66.1 --dead_master_prot=3306 --new_master_host=172.25.66.2 --new_master_port=3306

测试:发现当server1(主库)宕机后,server2结点接管master,server3结点依旧是slave

[root@server2 ~]# mysql -u root -p'Westos+001' #查看slave信息为空,因为此时server2已经切换为master mysql> show slave status\G; mysql> show master status;

[root@sever3 ~]# mysql -u root -p'Westos+001' mysql> show slave status\G;

开启server1的数据库,手动将其添加到slave中

[root@server1 ~]# systemctl start mysqld [root@server1 ~]# mysql -u root -p'Westos+001' #MASTER_HOST为master主库的ip mysql> CHANGE MASTER TO MASTER_HOST='172.25.66.2', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='Westos+001'; #开启slave mysql> start slave; mysql> show slave status\G;

(2)热切换

热切换:在主库没有宕机的情况下,手动切换 master #删除app1.failover.complete文件

[root@server1 ~]# cd /etc/masterha/ [root@server1 masterha]# ls app1.conf app1.failover.complete [root@server1 masterha]# cat app1.failover.complete [root@server1 masterha]# rm -rf app1.failover.complete [root@server1 masterha]# ls app1.conf

在主库活跃的情况下,手动将master切回到server1结点上

[root@server1 masterha]# masterha_master_switch --master_state=alive --conf=/etc/masterha/app1.conf --new_master_host=172.25.66.1 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

测试:

发现的确实现了在主库活跃的情况下,将master回切到server1结点上

[root@server1 ~]# mysql -u root -p'Westos+001' mysql> show master status;

[root@sever2 ~]# mysql -u root -p'Westos+001' mysql> show slave status\G;

[root@sever3 ~]# mysql -u root -p'Westos+001' mysql> show master status;

2.自动切换

设定自动切换:

[root@server1 ~]# cd /etc/masterha/ #自动切换 [root@server1 masterha]# nohup masterha_manager --conf=/etc/masterha/app1.conf &> /dev/null & [1] 6286 [root@server1 masterha]# ps a

测试:

当主库宕机后,master自动切换到server2结点上

[root@server1 masterha]# systemctl stop mysqld [1]+ Done nohup masterha_manager --conf=/etc/masterha/app1.conf &>/dev/null [root@server2 ~]# mysql -u root -p'Westos+001' mysql> show master status;

[root@sever3 ~]# mysql -u root -p'Westos+001' mysql> show slave status\G

[root@server1 masterha]# pwd /etc/masterha [root@server1 masterha]# ls app1.conf app1.failover.complete [root@server1 masterha]# rm -rf app1.failover.complete

开启server1的数据库,手动添加到slave中(此过程没办法自动完成)

[root@server1 ~]# systemctl start mysqld [root@server1 ~]# mysql -u root -p'Westos+001' mysql> CHANGE MASTER TO MASTER_HOST='172.25.66.2', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='Westos+001'; #开启slave mysql> start slave; mysql> show slave status\G;

4.脚本实现vip的漂移

1.下载脚本

[kiosk@foundation66 Desktop]$ scp master_ip_failover master_ip_online_change root@172.25.66.1:/usr/local/bin/ [root@server1 ~]# cd /usr/local/bin/ [root@server1 bin]# ls master_ip_failover master_ip_online_change

2.更改脚本

#此脚本用于实现手动切换vip [root@server1 bin]# vim master_ip_online_change ################### my $vip = '172.25.66.100/24'; #设定vip my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0"; #添加vip my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0"; #删除vip

#此脚本用于实现自动切换vip [root@server1 bin]# vim master_ip_failover ################### my $vip = '172.25.66.100/24'; #设定vip my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0"; #添加vip my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0"; #删除vip my $exit_code = 0;

3.给脚本一个可执行权限

[root@server1 bin]# ll total 8 -rw-r--r-- 1 root root 2179 Feb 26 21:14 master_ip_failover -rw-r--r-- 1 root root 3796 Feb 26 21:13 master_ip_online_change [root@server1 bin]# chmod +x * [root@server1 bin]# ll total 8 -rwxr-xr-x 1 root root 2179 Feb 26 21:14 master_ip_failover -rwxr-xr-x 1 root root 3796 Feb 26 21:13 master_ip_online_change

4.更改配置文件

[root@server1 bin]# cd /etc/masterha/ [root@server1 masterha]# ls app1.conf [root@server1 masterha]# vim app1.conf ######################## master_ip_failover_script=/usr/local/bin/master_ip_failover #设置自动failover时候的切换脚本 master_ip_online_change_script=/usr/local/bin/master_ip_online_change #设置手动切换时候的切换脚本

5.给master端添加vip

[root@server2 ~]# ip addr

#添加vip [root@server2 ~]# ip addr add 172.25.66.100/24 dev eth0 [root@server2 ~]# ip addr

6.测试

(1)手动热切换

手动切换:

#将master手动切换到server1上(热切换) [root@server1 masterha]# masterha_master_switch --master_state=alive --conf=/etc/masterha/app1.conf --new_master_host=172.25.66.1 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

检测:

发现vip漂移到server1结点上,因为此时server1切换为了master

[root@server1 masterha]# ip addr

[root@server2 ~]# ip addr [root@server1 ~]# mysql -u root -p'Westos+001' mysql> show master status;

[root@server2 ~]# mysql -u root -p'Westos+001' mysql> show slave status\G;

[root@server3 ~]# mysql -u root -p'Westos+001' mysql> show slave status\G;

(2)自动切换

设定自动切换

[root@server1 ~]# nohup masterha_manager --conf=/etc/masterha/app1.conf &> /dev/null & [1] 2220

检测:

发现当主库(server1)宕机后,server2自动接管master,此时vip漂移到server2结点上。也即是说,vip会随着master的切换而漂移,谁接管master,vip便会漂向谁

[root@server1 ~]# systemctl stop mysqld [1]+ Done nohup masterha_manager --conf=/etc/masterha/app1.conf &>/dev/null [root@server2 ~]# ip addr

[root@server1 ~]# ip addr

[root@server2 ~]# mysql -u root -p'Westos+001' mysql> show master status;

[root@server3 ~]# mysql -u root -p'Westos+001' mysql> show slave status\G;

开启server1的数据库,手动将其添加到slave中

[root@server1 ~]# systemctl start mysqld [root@server1 ~]# mysql -u root -p'Westos+001' mysql> CHANGE MASTER TO MASTER_HOST='172.25.66.2', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='Westos+001'; mysql> start slave; mysql> show slave status\G;

排错:

当开启slave时,报错

#启动slave时,使用repository中信息初始化relay log结构失败了 mysql> start slave; ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository 解决方案:先重置slave,再重新启动机即可 mysql> reset slave; Query OK, 0 rows affected (0.25 sec) mysql> start slave; Query OK, 0 rows affected (0.14 sec)

最新回复(0)