前言:
此时我们对“supervisor管理mysql”大约比较讲究,兄弟们都需要学习一些“supervisor管理mysql”的相关资讯。那么小编在网络上收集了一些对于“supervisor管理mysql””的相关内容,希望小伙伴们能喜欢,朋友们快快来学习一下吧!关注我「程序猿集锦」,获取更多分享。
VIP漂移的三种方式通过MHA自定义master_ip_failover维护通过keepalive来维护安装keepalive配置keepalive启动keepalive通过keepalive和master_ip_failover结合来使用验证VIP漂移验证VIP是否可用验证VIP是否可以漂移如何恢复失败节点读服务怎么解决思考总结
前置阅读:MySQL高可用架构-MHA(上)
VIP漂移的三种方式
MySQL高可用集群已经搭建好,但是当master1节点宕机之后,从节点提升为主节点后,应用连接到MySQL服务的主节点地址就变成了某一个slave从节点,那如何保证应用可用是一个固定的IP来连接MySQL数据库呢?这就需要使用到VIP虚拟IP地址。
这个VIP地址就是应用中配置的IP地址,它可用在活着的主节点上面绑定,如果主宕机了,这个VIP可用漂移到新的主上。这就是VIP要完成功能。那么如何让这个VIP自动漂移到活着的主节点呢?目前可有三种方式:
通过脚本自己去维护VIP绑定的节点,这要在MHA的扩展脚本中去做,使用perl脚本去做。或者使用keepalive插件自己去维护,这种方式是在MHA做故障迁移的时候,顺便把发生故障的主机上面的keepalive服务给停止掉,这样VIP就可以从故障的节点迁移到指定的节点了。就是上面两种1和2的方式结合的一种方式。在Perl脚本中不去维护VIP的创建绑定等操作,而是交给keepalive服务去做,只要在perl脚本中,决定什么时候在发生主节点MySQL服务不能用的时候,把该主节点上面的keepalive服务给停止,就可以把对应VIP漂移到其他主机上去了。通过MHA自定义master_ip_failover维护
这个脚本就是master_ip_failover自定义脚本。因为我不会写Perl,下面是网上扒来的,供参考。
大体的逻辑就是:我们在脚本中定义一个VIP地址,然后定义一个在远程服务器创建VIP,还有一个取消VIP的方法。然后MAH的manager进程在进行主从切换的时候,会调用这个自定义的master_ip_failover脚本,并给这个脚本传入对应的参数和命令,这个脚本就根据manager进程转入的命令走对应的逻辑,来调用自定义的创建和取消VIP的方法,从而来实现VIP从原主节点到新节点的漂移。
在使用这个脚本之前,需要原先正常的master节点上,先使用下面的命令来创建一个VIP,然后才能将这个VIP漂移到新的主节点上。
root@master1:/var/log/mha/app1# ifconfig eth0:1 172.21.0.10 uproot@master1:/var/log/mha/app1# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.11 netmask 255.255.255.0 broadcast 172.21.0.255 ether 02:42:ac:15:00:0b txqueuelen 0 (Ethernet) RX packets 1251 bytes 162986 (159.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 3342 bytes 342702 (334.6 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.10 netmask 255.255.0.0 broadcast 172.21.255.255 ether 02:42:ac:15:00:0b txqueuelen 0 (Ethernet)lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 154 bytes 21841 (21.3 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 154 bytes 21841 (21.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
master_ip_failover的示例脚本如下:
root@manager:/var/log/mha/app1# cat /etc/mha/app1/master_ip_failover#!/usr/bin/env perluse strict;use warnings FATAL => 'all';use Getopt::Long;use MHA::DBHelper;my ( $command, $ssh_user, $orig_master_host, $orig_master_ip, $orig_master_port, $new_master_host, $new_master_ip, $new_master_port, $new_master_user, $new_master_password);# MySQL cluster VIP for write requestmy $vip = '172.21.0.10';my $key = '1';my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";GetOptions( 'command=s' => \$command, 'ssh_user=s' => \$ssh_user, 'orig_master_host=s' => \$orig_master_host, 'orig_master_ip=s' => \$orig_master_ip, 'orig_master_port=i' => \$orig_master_port, 'new_master_host=s' => \$new_master_host, 'new_master_ip=s' => \$new_master_ip, 'new_master_port=i' => \$new_master_port, 'new_master_user=s' => \$new_master_user, 'new_master_password=s' => \$new_master_password,);exit &main();sub main { if ( $command eq "stop" || $command eq "stopssh" ) { # $orig_master_host, $orig_master_ip, $orig_master_port are passed. # If you manage master ip address at global catalog database, # invalidate orig_master_ip here. my $exit_code = 1; eval { print "Disabling the VIP on old master: $orig_master_host \n"; &stop_vip(); # updating global catalog, etc $exit_code = 0; }; if ($@) { warn "Got Error: $@\n"; exit $exit_code; } exit $exit_code; } elsif ( $command eq "start" ) { # all arguments are passed. # If you manage master ip address at global catalog database, # activate new_master_ip here. # You can also grant write access (create user, set read_only=0, etc) here. my $exit_code = 10; eval { my $new_master_handler = new MHA::DBHelper(); # args: hostname, port, user, password, raise_error_or_not $new_master_handler->connect( $new_master_ip, $new_master_port, $new_master_user, $new_master_password, 1 ); ## Set read_only=0 on the new master $new_master_handler->disable_log_bin_local(); print "Set read_only=0 on the new master.\n"; $new_master_handler->disable_read_only(); ## Creating an app user on the new master #print "Creating app user on the new master..\n"; #FIXME_xxx_create_user( $new_master_handler->{dbh} ); $new_master_handler->enable_log_bin_local(); $new_master_handler->disconnect(); ## Update master ip on the catalog database, etc #FIXME_xxx; print "Enabling the VIP - $vip on the new master - $new_master_host \n"; &start_vip(); $exit_code = 0; }; if ($@) { warn $@; # If you want to continue failover, exit 10. exit $exit_code; } exit $exit_code; } elsif ( $command eq "status" ) { print "Checking the Status of the script.. OK \n"; # do nothing exit 0; } else { &usage(); exit 1; }}# A simple system call that enable the VIP on the new mastersub start_vip() { `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;}# A simple system call that disable the VIP on the old_mastersub stop_vip() { return 0 unless ($ssh_user); `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;}sub usage { print"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";}root@manager:/var/log/mha/app1#通过keepalive来维护
我们接下来安装keepalive插接,目的是为了在MySQL数据集群中配置一个虚拟的VIP,然后让这个VIP可以根据主节点的状态来自动的在可用的主节点进行漂移。此时我们不需要自己在master节点上创建VIP,当我们在master节点和备选master节点上,配置好keepalive的配置文件/etc/keepalived/keepalived.conf之后,启动keepalive服务后会自动在对应的节点创建VIP地址。
安装keepalive
我们在master1节点和slave1节点上面都安装keepalive插件,master1作为默认的主节点,slave1作为备用主节点(如果是有多个备选主节点,那么所有的备选主节点都要安装并启动keepalive服务),使用apt-get命令来安装keepalive软件,如果是centos使用yum来安装。
root@master1:/# apt-get install keepalived -yroot@slave1:/# apt-get install keepalived -y
keepalive安装完成之后,会在/etc/init.d目录里下面生成一个启动脚本文件keepalived,如下所示,我们只是master1节点上示例展示。查看这个脚本文件,可用看到它的配置文件是在/etc/keepalived/keepalived.conf这里。所以,后续配置keepalive的时候,我们需要在这个配置文件中进行配置。
# 查看启动和停止keepalive服务的脚本文件root@master1:/etc/keepalived# ls -lstr /etc/init.d/keepalived4 -rwxr-xr-x 1 root root 2121 Aug 15 2015 /etc/init.d/keepalived# 查看keepalive的默认配置文件配置路径是什么root@master1:/etc/keepalived# cat /etc/init.d/keepalived | grep CONFIGCONFIG=/etc/keepalived/keepalived.conftest -f $CONFIG || exit 0root@master1:/etc/keepalived#配置keepalive
在master1节点和slave1节点上面分别创建配置文件/etc/keepalived/keepalived.conf,然后分别编辑配置他们。
在maste1上的keepalived.conf`配置文件如下:
root@master1:/etc/keepalived# cat /etc/keepalived/keepalived.conf! Configuration File for keepalivedglobal_defs { router_id 172.21.0.11}vrrp_script chk_mysql_status { script "/etc/keepalived/check_mysql_port.sh 3306" interval 2 weight -20}vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 251 priority 100 advert_int 1 mcast_src_ip 172.21.0.11 nopreempt authentication { auth_type PASS auth_pass 11111111 } track_script { chk_mysql_status } virtual_ipaddress { 172.21.0.10 }}root@master1:/etc/keepalived#在slave1上的keepalived.conf`配置文件如下:
root@slave1:/etc/keepalived# cat keepalived.conf! Configuration File for keepalivedglobal_defs { router_id 172.21.0.12}vrrp_script chk_mysql_status { script "/etc/keepalived/check_mysql_port.sh 3306" interval 2 weight -20}vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 251 priority 90 advert_int 1 mcast_src_ip 172.21.0.12 nopreempt authentication { auth_type PASS auth_pass 11111111 } track_script { chk_mysql_status } virtual_ipaddress { 172.21.0.10 }}root@slave1:/etc/keepalived#
现在,针对上面的配置文件的参数,使用master1节点上面的配置文件,做如下简单介绍说明,以便于立即keepalive的配置文件怎么配置。
root@master1:/etc/keepalived# cat /etc/keepalived/keepalived.conf! Configuration File for keepalivedglobal_defs { router_id 172.21.0.11 # keepalive所在主机的IP地址,一个名字而已,这里用IP地址代替了。}vrrp_script chk_mysql_status { # 检查主机3306端口的shell脚本,发生VIP漂移的触发原因就是某一个主机的某个端口不可用。这个脚本需要自定义去写一下,比较简单,后面会给出示例。 script "/etc/keepalived/check_mysql_port.sh 3306" interval 2 # 端口检查的频次,每2秒中一次 weight -20}vrrp_instance VI_1 { state BACKUP # 当前keepalive节点的角色 interface eth0 # 当前主机的物理网卡名称 virtual_router_id 251 priority 100 advert_int 1 mcast_src_ip 172.21.0.11 # 当前主机的物理IP地址 nopreempt # keepalive多个节点互相通信的认证方式,用于标识哪些keepalive节点是同一个keepalive集群。 authentication { auth_type PASS auth_pass 11111111 } track_script { chk_mysql_status # 检查服务端口的脚本,VIP发生漂移的时候就是从这里触发的。 } virtual_ipaddress { 172.21.0.10 # 这就是我们设置的VIP的地址 }}root@master1:/etc/keepalived#
注意:上面两台服务器的keepalived都设置为了BACKUP模式,目的是为了尽量减少VIP漂移的次数。具体原因如下:
在keepalived中2种模式,分别是master->backup模式和backup->backup模式。这两种模式有很大区别。
在master->backup模式下,一旦主库宕机,虚拟ip会自动漂移到从库,当主库修复后,keepalived启动后,还会把虚拟ip抢占过来,即使设置了非抢占模式(nopreempt)抢占ip的动作也会发生。在backup->backup模式下,当主库宕机后虚拟ip会自动漂移到从库上,当原主库恢复和keepalived服务启动后,并不会抢占新主的虚拟ip,即使是优先级高于从库的优先级别,也不会发生抢占。
所以,为了减少ip漂移次数,通常是把修复好的主库当做新的备库。同时把keepalive中的角色都设置为backup角色。
在配置好keepalive的配置文件后,配置文件中有引用到一个监控某个服务是否可以的脚本,这里我们要监控的是MySQL数据库服务是否可用,所以我们监控的是MySQL的3306端口是否在提供监听服务。如果是要监听其他服务的端口,只要作出对应的端口作出修改即可。下面给出监听MySQL服务的shell脚本,这个脚本在每一个keepalive节点上都是一样的,在我们的master1和slave1上使用相同的脚本文件。
root@master1:/etc/keepalived# cat chk_mysql_status.sh#!/bin/bashCHK_PORT=$1if [ -n "$CHK_PORT" ]; then PORT_PROCESS=`ss -lnt | grep $CHK_PORT | wc -l` if [ $PORT_PROCESS -eq 0 ]; then echo "请注意:端口号$CHK_PORT现在已经不可用,下面将退出keepalive的服务,VIP即将发生漂移。" >> ./chk_mysql_status.log # 发现当前主机的MySQL端口不能访问后,把当前主机的keepalive服务也停止,让这个主机上的VIP漂移到备选主节点上 /etc/init.d/keepalived stop exit 1 fielse echo "待监控的服务端口号不能为空!" >> ./chk_mysql_status.logfiroot@master1:/etc/keepalived# pwd/etc/keepalivedroot@master1:/etc/keepalived#
需要注意的是脚本的放置目录,我们是放在和keepalive配置文件相同的目录/etc/keepalive目录下面了。
启动keepalive
在master1节点上启动keepalive服务,如下所示:
root@master1:/etc/keepalived# /etc/init.d/keepalived start[ ok ] Starting keepalived: keepalived.# 查看启动keepalive后,VIP已经创建成功root@master1:/etc/keepalived# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000 link/ipip 0.0.0.0 brd 0.0.0.03: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000 link/tunnel6 :: brd ::59: eth0@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:15:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.21.0.11/24 brd 172.21.0.255 scope global eth0 valid_lft forever preferred_lft forever inet 172.21.0.10/32 scope global eth0 # 这里就是我们配置的VIP,默认是master1上面,当master1节点的3306端口挂掉,或漂移到slave1上。 valid_lft forever preferred_lft foreverroot@master1:/etc/keepalived#
在slave1节点上,也启动keepalive服务,如下所示:
root@slave1:/etc/keepalived# /etc/init.d/keepalived start[ ok ] Starting keepalived: keepalived.root@slave1:/etc/keepalived## 此时slave1上面是没有我们配置的VIP的,因为master1目前还是可用状态。root@slave1:/etc/keepalived# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000 link/ipip 0.0.0.0 brd 0.0.0.03: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000 link/tunnel6 :: brd ::61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:15:00:0c brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.21.0.12/24 brd 172.21.0.255 scope global eth0 valid_lft forever preferred_lft foreverroot@slave1:/etc/keepalived#通过keepalive和master_ip_failover结合来使用
这种方式就结合前面使用MHA的master_ip_failover脚本和keepalive两种方式的变形。实现的方式就是:VIP的创建我们交给keepalive来做,但是这个VIP要向完成漂移的动作,发生故障的服务器上面的keepalive进程必须终止后,VIP才会发生漂移,那么如何让这个发生故障的服务器上面的keepalive终止进程呢?就在我们的master_ip_failover脚本中去终止对应的服务器上面的keepalive进程服务,这样这个服务器上面的VIP就会发生漂移了。
脚本的实现方式和第一种master_ip_failover的脚本类似,只是此时我们不需要只是用keepalive的时候自定义的那个chk_mysql_status.sh脚本来终止keepalive进程了。在master_ip_failover脚本中去终止对应的keepalive服务进程。脚本如下:
root@manager:/var/log/mha/app1# cat /etc/mha/app1/master_ip_failover#!/usr/bin/env perl## Note: This is a sample script and is not complete. Modify the script based on your environment.use strict;use warnings FATAL => 'all';use Getopt::Long;use MHA::DBHelper;my ( $command, $ssh_user, $orig_master_host, $orig_master_ip, $orig_master_port, $new_master_host, $new_master_ip, $new_master_port, $new_master_user, $new_master_password);# MySQL集群中的VIP地址my $vip = '172.21.0.10';# 开启和关闭VIP的命令,下面是通过停止对应的服务器上面的keepalive的命令,来完成VIP的漂移的。my $ssh_start_vip = "/etc/init.d/keepalived start";my $ssh_stop_vip = "/etc/init.d/keepalived stop";# 也可以使用下面的方式,自己通过ifconfig命令在对应的服务器上面增加和删除VIP,这样在master节点和备选master节点就不用安装keepalive服务了。#my $key = '1';#my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip up";#my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";GetOptions( 'command=s' => \$command, 'ssh_user=s' => \$ssh_user, 'orig_master_host=s' => \$orig_master_host, 'orig_master_ip=s' => \$orig_master_ip, 'orig_master_port=i' => \$orig_master_port, 'new_master_host=s' => \$new_master_host, 'new_master_ip=s' => \$new_master_ip, 'new_master_port=i' => \$new_master_port, 'new_master_user=s' => \$new_master_user, 'new_master_password=s' => \$new_master_password,);exit &main();sub main { if ( $command eq "stop" || $command eq "stopssh" ) { # $orig_master_host, $orig_master_ip, $orig_master_port are passed. # If you manage master ip address at global catalog database, # invalidate orig_master_ip here. my $exit_code = 1; eval { print "Disabling the VIP on old master: $orig_master_host \n"; &stop_vip(); # 调用停止VIP的方法 # updating global catalog, etc $exit_code = 0; }; if ($@) { warn "Got Error: $@\n"; exit $exit_code; } exit $exit_code; } elsif ( $command eq "start" ) { # all arguments are passed. # If you manage master ip address at global catalog database, # activate new_master_ip here. # You can also grant write access (create user, set read_only=0, etc) here. my $exit_code = 10; eval { my $new_master_handler = new MHA::DBHelper(); # args: hostname, port, user, password, raise_error_or_not $new_master_handler->connect( $new_master_ip, $new_master_port, $new_master_user, $new_master_password, 1 ); ## Set read_only=0 on the new master $new_master_handler->disable_log_bin_local(); print "Set read_only=0 on the new master.\n"; $new_master_handler->disable_read_only(); ## Creating an app user on the new master #print "Creating app user on the new master..\n"; #FIXME_xxx_create_user( $new_master_handler->{dbh} ); # 如果应用使用的MySQL用户并没有在salve节点创建,可以在切换的时候,在这里定义并创建。但是一般情况下,整个集群中的所有用户都是相同的,权限也是相通的,所以一般情况用不上这个操作。 $new_master_handler->enable_log_bin_local(); $new_master_handler->disconnect(); ## Update master ip on the catalog database, etc #FIXME_xxx; print "Enabling the VIP - $vip on the new master - $new_master_host \n"; &start_vip(); # 调用开启VIP的方法 $exit_code = 0; }; if ($@) { warn $@; # If you want to continue failover, exit 10. exit $exit_code; } exit $exit_code; } elsif ( $command eq "status" ) { print "Checking the Status of the script.. OK \n"; # do nothing exit 0; } else { &usage(); exit 1; }}# 在远程服务器开启VIP的方法sub start_vip() { `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;}# 在远程服务器停止VIP的方法sub stop_vip() { return 0 unless ($ssh_user); `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;}sub usage { print"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";}root@manager:/var/log/mha/app1#验证VIP漂移
在验证VIP是否可以正常漂移的实验中,针对上面提出来的3种实现方式,我们选择第一种方式来验证一下。其他两种方式,我也一并做过,但是这里不再一一贴出实验过程。
第一种方式:通过master_ip_failover脚本来维护VIP的漂移。在master1节点上创建一个VIP,如下所示,用于对外提供写的服务。然后我们看下在master1节点宕机的时候,这个上面的VIP是否可以自动漂移到salve1备用主主节点上。
# 在master1节点上创建VIP地址root@master1:/var/log/mha/app1# ifconfig eth0:1 172.21.0.10 up# VIP地址已经在master1节点上创建完成root@master1:/var/log/mha/app1# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.11 netmask 255.255.255.0 broadcast 172.21.0.255 ether 02:42:ac:15:00:0b txqueuelen 0 (Ethernet) RX packets 1251 bytes 162986 (159.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 3342 bytes 342702 (334.6 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.10 netmask 255.255.0.0 broadcast 172.21.255.255 ether 02:42:ac:15:00:0b txqueuelen 0 (Ethernet)lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 154 bytes 21841 (21.3 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 154 bytes 21841 (21.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0# 此时的salve1节点上是没有VIP地址的root@slave1:/# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.12 netmask 255.255.255.0 broadcast 172.21.0.255 ether 02:42:ac:15:00:0c txqueuelen 0 (Ethernet) RX packets 9 bytes 726 (726.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0root@slave1:/#
对于master_ip_failover脚本,参考上面提到VIP漂移第一种实现方式的贴出来的脚本内容,这不再重复贴出。
验证VIP是否可用
现在的VIP已经在master1上面创建成功了,下面我们来尝试使用这个VIP是否可以正常方式到MySQL服务。我们在安装MHA服务的manager节点上,尝试通过VIP来访问MySQL数据库服务,看是否可以成功。通过如下结果可以看出通过VIP是可以正常方式MySQL服务的。
root@manager:/etc/mha# mysql -uroot -proot -h172.21.0.10mysql: [Warning] Using a password on the command line interface can be insecure.Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 48Server version: 5.7.31-log MySQL Community Server (GPL)Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> select @@hostname;+---------------+| @@hostname |+---------------+| master1.mysql |+---------------+1 row in set (0.00 sec)mysql>
通过上面的实验可以看出,在manager节点172.21.0.100上是可以通过172.21.0.10这个VIP来访问MySQL数据库的。
验证VIP是否可以漂移
manager节点的操作
首先,我们在manager节点上面,启动MHA的manager服务。启动方式如下所示,我们选择后台启动。
# 以后进程的方式启动MHA的manager服务root@manager:/var/log/mha/app1# nohup masterha_manager --conf=/etc/mha/app1.cnf &[1] 1230root@manager:/var/log/mha/app1# nohup: ignoring input and appending output to 'nohup.out'
查看manager服务启动后,日志目录下面的文件有哪些。日志文件的目录在/etc/mha/app1.cnf配置文件中定义。
# 启动后,发现会在/var/log/mha/app1目录下面生如下3个文件,一个是nohup的日志输出,一个是manager服务的日志输出文件,一个是MySQL数据库集群中master节点监控状态标识文件。root@manager:/var/log/mha/app1# ls -lstrtotal 164 -rw------- 1 root root 299 Mar 7 09:56 nohup.out8 -rw-r--r-- 1 root root 5784 Mar 7 09:56 app1.log4 -rw-r--r-- 1 root root 33 Mar 7 09:56 app1.master_status.health
用如下的命令动态监控manager服务的日志输出是什么,以方便我们在测试主从切换的时候,动态查看manager服务的日志内容。
# 用tail -f的命令动态的观察manager服务日志的输出内容,发现目前已经启动manager服务,它在等待MySQL服务不可用的时候,才会有动作以及日志的输出。root@manager:/var/log/mha/app1# tail -f app1.logSun Mar 7 09:56:55 2021 - [info] Checking master_ip_failover_script status:Sun Mar 7 09:56:55 2021 - [info] /etc/mha/app1/master_ip_failover --command=status --ssh_user=root --orig_master_host=172.21.0.11 --orig_master_ip=172.21.0.11 --orig_master_port=3306Checking the Status of the script.. OKSun Mar 7 09:56:55 2021 - [info] OK.Sun Mar 7 09:56:55 2021 - [warning] shutdown_script is not defined.Sun Mar 7 09:56:55 2021 - [info] Set master ping interval 1 seconds.Sun Mar 7 09:56:55 2021 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.Sun Mar 7 09:56:55 2021 - [info] Starting ping health check on 172.21.0.11(172.21.0.11:3306)..Sun Mar 7 09:56:55 2021 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
master1主节点的操作
下面我们可以尝试把master1节点MySQL服务停止掉,看下VIP是否会自动漂移到slave1上。在master1节点上执行如下操作来停止MySQL数据库服务。由于我们的MySQL服务是用docker容器启动的,当我们停止容器中的MySQL之后,这个容器也就退出了。
root@master1:~# /etc/init.d/mysql stop...........% ➜ ~
查看manager节点的日志
当发生主从切换之后,manager节点上面的manager服务会停止,如下可以查看manager服务以及停止,需要在我们恢复好MySQL数据失败的节点之后,再次以后台进程的方式启动起来。
# 检查manager节点上的manager服务的状态,发现在完成主从切换之后,它已经停止了root@manager:/var/log/mha/app1# masterha_check_status --conf=/etc/mha/app1.cnfapp1 is stopped(2:NOT_RUNNING).root@manager:/var/log/mha/app1#
同时,我们可以查看在manager节点manager服务的日志目录下面,有如下文件生成,需要注意的是,其中的app1.failover.complete标识文件,需要删除之后,才可以再次启动manager服务。否则我们的manager服务是不能启动成功的。
root@manager:/var/log/mha/app1# ls -lstrtotal 28 4 -rw------- 1 root root 773 Mar 7 10:06 nohup.out # nohup的输出日志文件24 -rw-r--r-- 1 root root 22206 Mar 7 10:06 app1.log # 主从切换过程的日志文件 0 -rw-r--r-- 1 root root 0 Mar 7 10:06 app1.failover.complete # 主从切换完成的标识文件,再次启动manager服务之前,需要将这个文件删除之后,才可以再次启动manager服务。root@manager:/var/log/mha/app1# pwd/var/log/mha/app1root@manager:/var/log/mha/app1#
在manager节点上,查看manager节点的主从切换的日志输出如下,由于日志内容太长,这里我们只列出最后几行的日志内容。
root@manager:/var/log/mha/app1# tail -f app1.log# ...省略...Master 172.21.0.11(172.21.0.11:3306) is down!Check MHA Manager logs at manager.mysql:/var/log/mha/app1/app1.log for details.Started automated(non-interactive) failover.Invalidated master IP address on 172.21.0.11(172.21.0.11:3306)The latest slave 172.21.0.12(172.21.0.12:3306) has all relay logs for recovery.Selected 172.21.0.12(172.21.0.12:3306) as a new master.172.21.0.12(172.21.0.12:3306): OK: Applying all logs succeeded.172.21.0.12(172.21.0.12:3306): OK: Activated master IP address.172.21.0.22(172.21.0.22:3306): This host has the latest relay log events.Generating relay diff files from the latest slave succeeded.172.21.0.22(172.21.0.22:3306): OK: Applying all logs succeeded. Slave started, replicating from 172.21.0.12(172.21.0.12:3306)172.21.0.12(172.21.0.12:3306): Resetting slave info succeeded.Master failover to 172.21.0.12(172.21.0.12:3306) completed successfully.
slave1节点的操作
查看备选主节点slave1上面的是否有VIP的地址,通过如下命令可以查看VIP已经漂移到了slave1节点上了。这个漂移的动作就是我们在master_ip_failover脚本中,通过ifconfig命令来实现的,这个脚本会在MHA的manager服务在完整主从切换之后自动调用的。至于这个脚本的具体位置和路径,则是定义在/etc/mha/app1.cnf配置文件中。
root@slave1:/# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.12 netmask 255.255.255.0 broadcast 172.21.0.255 ether 02:42:ac:15:00:0c txqueuelen 0 (Ethernet) RX packets 433 bytes 61965 (60.5 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 395 bytes 96296 (94.0 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.21.0.10 netmask 255.255.0.0 broadcast 172.21.255.255 ether 02:42:ac:15:00:0c txqueuelen 0 (Ethernet)lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 59 bytes 8093 (7.9 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 59 bytes 8093 (7.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0root@slave1:/#
以上,我们就验证了通过master_ip_failover在定义的脚本来完成VIP在发生主从切换的时候漂移的过程。至于另外两种VIP漂移的方式,实验过程大同小异。大家可以自行式样。
如何恢复失败节点
在manger节点上的操作
在manager节点中的app1.log中,包含具体恢复失败节点的命令提示。其实现的原理则是把失败的主节点,以一个从节点的角色再次加入到集群当中去。
当前启动好失败的主节点之后,如何把这个恢复的节点加入到集群当中去,可以参考app1.log日志文件中的输出内容。
root@manager:/var/log/mha/app1# cat app1.log | grep "CHANGE"Sun Mar 7 10:06:25 2021 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='172.21.0.12', MASTER_PORT=3306, MASTER_LOG_FILE='slave1-mysql-bin.000007', MASTER_LOG_POS=154, MASTER_USER='repl', MASTER_PASSWORD='xxx';Sun Mar 7 10:06:27 2021 - [info] Executed CHANGE MASTER.root@manager:/var/log/mha/app1#
在失败节点上的操作
根据上面在app1.log日志文件中输出的内容,改为如下内容,在失败的节点上,执行改变主从复制链路的命令之后,就可以把刚恢复的节点以从节点的角色加入到MHA考可用集群当中。
/* 在失败节点执行如下命令,设置新的复制链路 */mysql> CHANGE MASTER TO MASTER_HOST='172.21.0.12', MASTER_PORT=3306, MASTER_LOG_FILE='slave1-mysql-bin.000007', MASTER_LOG_POS=154, MASTER_USER='repl', MASTER_PASSWORD='repl';Query OK, 0 rows affected, 2 warnings (0.03 sec)/* 启动复制链路 */mysql> start slave;Query OK, 0 rows affected (0.03 sec)/* 查看主从复制后的链路,发现链路已经切换为slave1作为主节点了 */mysql> show slave status\G*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.21.0.12 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: slave1-mysql-bin.000007 Read_Master_Log_Pos: 154 Relay_Log_File: master1-relay-bin.000002 Relay_Log_Pos: 327 Relay_Master_Log_File: slave1-mysql-bin.000007 Slave_IO_Running: Yes Slave_SQL_Running: Yes /* ...省略输出内容... */ Master_Server_Id: 12 Master_UUID: 3ae2324e-7bef-11eb-bc99-0242ac15000c Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 864001 row in set (0.00 sec)mysql>
在manager节点上操作
前面的步骤我们已经恢复了主从复制的链路,接下来就是要再次启动我们的MHA在manager节点上的manager服务。
在启动之前,需要把manager节点上的主从切换完成的标识文件删除掉,如下所示:
root@manager:/var/log/mha/app1# rm /var/log/mha/app1/app1.failover.completeroot@manager:/var/log/mha/app1#
然后再次启动MAH监控服务,
# 后台启动MHA的manager服务root@manager:/var/log/mha/app1# nohup masterha_manager --conf=/etc/mha/app1.cnf &[1] 1877root@manager:/var/log/mha/app1# nohup: ignoring input and appending output to 'nohup.out'# 查看MHA的manager服务启动的结果root@manager:/var/log/mha/app1# masterha_check_status --conf=/etc/mha/app1.cnfapp1 (pid:1877) is running(0:PING_OK), master:172.21.0.12root@manager:/var/log/mha/app1#读服务怎么解决
对于一个高可用的MHA集群,对外提供写的服务,可以通过VIP来解决应用层连接的问题。那么对于读的服务,多个slave节点如何对应用层提供服务?
其实,对于这样的高可用的集群,它是一个读写分离的高可用集群。主节点提供写的服务,从节点提供读的服务。在应用层连接数据库的时候,就需要配置两个IP地址,一个用于写,一个用于读。这样对应用层是有侵入性的,因为应用层要自己确定每一个SQL请求到底是该发送到写的IP地址,还是发送到读的IP地址上。
为了解决这种对应用层侵入的问题,有现有的数据库中间件来解决这样问题。MyCat就是这样一个可以使用读写分离的数据库中间件。我们把上面我们提到的VIP地址,和多个slave节点IP地址,分别配置在MyCat中,MyCat会根据接收到的SQL语句自动识别出这是一个写请求还是一个读请求,进而把对应的SQL发送给VIP还是salve的IP。至于到底发送到哪个salve节点上,MyCat里有各种可以选择的配置方式,轮休分发的策略是常用的配置方式。MyCat对外提供一个IP地址,供应用层来连接MyCat。这样就解决了MHA高可用集群的读写分离。
如果考虑到MyCat的高可用,可以在MySQL的MHA集群上层部署两台MyCat,做高可用的MyCat,然后通过keepalive在两个MyCat上启动一个VIP,让应用通过这个VIP来连接MyCat。最后的网络拓扑图,如下所示:
思考
MHA中的manager节点,本身就是一个单节点,该如何避免这个呢?
目前的MHA还不支持两个MHA的manager共同管理一个MySQL集群。从技术上讲,你可以部署两个manager去监控同一个MySQL集群。但是,当发生故障转移的时候两个MHA的manager节点都在对MySQL集群进行故障转移,如果他们选择的从节点不是同一个从节点将会发生什么情况?整个MySQL集群就有可能产生两个master节点,发生脑裂的现象。所以我们目前还没有一个很好的办法对MHA的manager节点做高可用。
比较推荐的一种做法是通过监控脚本去对MHA的manager服务是否正在运用进行监控,如果没有运行就把这个服务再次尝试启动。可以把这样的脚本配置在Linux服务器的crontab中。
另外一种做法就是使用类似于的supervisor这样的后端守护进程去监控manager节点的manager服务是否正常运行,如果发现没有在运行,supervisor会尝试把manager进程给启动起来。此时,我们不用担心在MySQL集群发生故障转移主从切换之后MHA的manager节点在自动停止运行之后,再次被supervisor这样的守护进程给再次拉取起来。因为此时的manager进程是启动不了的,因为manager进程在启动的时候,会检查是否有上一次MySQL宕机的时候生成的标识文件,如果没有这样的文件才会启动成功,有这样的文件,是不会启动成功的。
MySQL中集群虽然高可用了,那VIP漂移的问题怎么解决的呢?
我们可以使用两种方式来解决这个VIP漂移的问题。
可以使用基于MHA的Perl脚本去做VIP的绑定和漂移工作。可以借助keepalive这样的组件来完成VIP的绑定和漂移的工作,这里需要注意一点,keepalive管理的VIP发生漂移的触发动作是当前绑定VIP的主机上面的keepalive进程关闭退出之后,当前主机绑定的VIP才会发生漂移的动作。所以当我们的master节点如果没有发生宕机,只是MySQL进程出现问题不能访问的时候,我们是需要把当前的主机上面运行的keepalive进程给终止掉,才会发生VIP的漂移。所以,此时我们需要在MHA的master_ip_failover脚本整增加杀死已经死掉的主节点的keepalive进程,或在keepalive的配置文件中配置一个监控MySQL服务的脚本,根据监控的结果来决定是否要杀死当前主节点的keepalive进程。
MHA中如何保证候选的master是从数据最接近宕机的master中选择出来的呢?可以设置几个candidate_master节点?
可以设置多个候选主节点,但是感觉意义不大。我们设置多个候选节点的目的是担心只要一个候选节点,万一这个候选节点挂掉了,就不能完成主从切换了。因为候选的主节点以及处于宕机的状态,所以这个节点不能用于提供主节点的服务。
但是实验证明,即便使我们设置两个以上的候选节点,如果其中任意一个候选节点出现宕机的情况,此时MHA是不能完成主从切换的。会出现如下的错误信息,在MHA尝试自动完成主从切换的时候。言外之意,如果MySQL集群中,已经存在一个候选节点宕机的情况,是不能自动完成主从切换的,需要保证集群中所有节点都是可用状态。
Sun Mar 7 19:46:16 2021 - [info] Replicating from 172.21.0.11(172.21.0.11:3306)Sun Mar 7 19:46:16 2021 - [info] Primary candidate for the new Master (candidate_master is set)Sun Mar 7 19:46:16 2021 - [error][/usr/share/perl5/MHA/ServerManager.pm, ln492] Server 172.21.0.33(172.21.0.33:3306) is dead, but must be alive! Check server settings.Sun Mar 7 19:46:16 2021 - [error][/usr/share/perl5/MHA/ManagerUtil.pm, ln178] Got ERROR: at /usr/share/perl5/MHA/MasterFailover.pm line 269.
如果备选主节点先于主节点宕机了,MHA会发现这个现象吗?主从切换还能完成吗?
MHA不会发现候选节点宕机或者任何一个从节点宕机的情况。如果发生这种现象,将不能完成主从自动切换。
总结
关于MAH的高可用集群搭建、主从切换的实验就到这里了,如果你有什么疑问可以评论区留言,我们一起讨论。后续给大家分享MGR高可用集群的搭建和实验。
标签: #supervisor管理mysql #mhamysql #oracle插接式数据库 #mysql decimal62是什么意思