MySQL MHA FailOver后,原Master节点自动以Slave角色加入解群的研究与实现
面临的问题
我们知道开启mha manager监控,当mha 发生自动漂移时,会将老的主库的ip将会从配置文件中移除。那么怎么可以自动将原master 节点自动以slave角色添加到集群中来是运维同学面临的问题。
并且大多数情况下,mha failover 后,mha manager 监控进程也会关闭。所以很有必要再开启一个关于mha manager的保护进程。
背景知识
为简化mha 配置,测试环境由一主一从一监控构成。
注意:主节点、辅助节点 之间 相互ssh 免密码登入。mha manger 到主、副节点之间 需要满足免密码登入(满足单向即可)
在主节点上虚拟出了 可读/写的ip;在从节点上虚拟出只读的ip。程序访问使用虚拟ip。
工具包主要功能
工具包 | 功能描述 |
masterha_check_ssh | 检查mha的ssh配置状况 |
masterha_check_repl | 检查mysql各节点复制状态 |
masterha_manger | 开启 mha manager |
masterha_check_status | 检测当前mha manager运行状态 |
master_ip_failover | 自动切换时管理vip的脚本,主要是vip的漂移。 |
master_ip_online_change | 手动执行mysql master switchover时执行的切换脚本,含有管理vip的脚本 |
masterha_master_switch | 控制故障转移(可手动) |
安装mha manager软件包后,路径/usr/local/bin上会出现以上工具包。
解决方案探究
脚本主要解决的问题
实现功能的文件及描述
主要文件mha_health_check_secondary.sh的处理逻辑
实现代码
文件mha_protect.sh的主要代码
1 ######################################################################## 2 # file name: mha_protect.sh 3 # excute: nohup sh mha_protect.sh & 4 # created time: thu jul 12 est 2018 5 ######################################################################### 6 #!/bin/sh 7 while true; 8 do 9 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l` 10 if [ "$mha_check_result" == "1" ];then 11 echo "$mha_check_result" 12 sh /etc/masterha/mha_health_check_vip.sh > /etc/masterha/mhalog/mha_check_`date "+%y%m%d%h%m%s"`.log 2>&1 13 fi 14 15 sleep 20 16 done
此文件中,调用mha的配置文件的参数为 /etc/masterha/app1.conf。执行mha_health_check_secondary.sh产生的log位于路径 /etc/masterha/mhalog下面,文件以mha_check_时间命名。
文件mha_health_check_secondary.sh 中的主要代码
1 #!/bin/bash 2 3 server1="172.xxx.xxx.xxx" ##此处请输入server1的ip 4 server2="172.xxx.xxx.xxx" ##此处请输入server2的ip 5 vip="172.xxx.xxx.xxx" ##此处请输入已配置的vip 6 mysql_username=用户 ##此处数据用户名 7 mysql_password=密码 ## 此处输入用户名相应的密码 8 9 mha_conf=/etc/masterha/app1.conf 10 # part:: string sql 11 sql_change_master="" 12 mysql_status="" 13 slave_status="" 14 master_status="" 15 16 #if has vip , master server ip 17 ipaddr1=`ssh root@"$server1" ip addr | grep "inet 172" | awk -f '[/]' '{print $1}' | awk '{print $2}' | grep "$vip"` 18 ipaddr2=`ssh root@"$server2" ip addr | grep "inet 172" | awk -f '[/]' '{print $1}' | awk '{print $2}' | grep "$vip"` 19 20 ###此处应该添加一个判断当 ipaddr1 和 ipaddr2 都为 空时,说明,vip设置有问题,退出需要告知管理员,去检查 21 22 if [ "$ipaddr1" = "$vip" ];then 23 masterip=$server1 24 echo masterip 在server1 $server1 上 25 fi 26 if [ "$ipaddr2" = "$vip" ];then 27 masterip=$server2 28 echo masterip 在server2 $server2 上 29 fi 30 31 echo "master ip: $masterip" 32 33 ## start ## 查看app1.conf mha 配置文件server的信息 34 conf_server1=`grep "server1" $mha_conf` 35 conf_server2=`grep "server2" $mha_conf` 36 37 38 echo "conf_server1: $conf_server1 conf_server2 :$conf_server2 " 39 ## end ## 查看app1.conf mha 配置文件server的信息 40 41 # 生成master mysql的[change master]sql命令 42 sql_change_master="change master to master_host='$masterip', master_user='$mysql_username', master_password='$mysql_password',master_port=3306,master_auto_position=1;" 43 44 # -------------------------- 45 # function 46 47 # 对指定主机执行linux命令 48 function do_linux_by_ssh() { 49 # variable 50 func_str_ip="$1" 51 func_str_user="$2" 52 func_str_command="$3" 53 # action 54 ssh $func_str_user@$func_str_ip "$func_str_command" 55 } 56 57 function do_sql() { 58 # variable 59 func_str_ip="$1" 60 func_str_sql="$2" 61 # action 62 mysql -u $mysql_username -h $func_str_ip -p"$mysql_password" -e "$func_str_sql" -p3306 63 } 64 function mysql_stop_up() { 65 # 判断mysql服务状态 66 # variable 67 func_str_ip="$1" 68 mysql_status=`do_linux_by_ssh "$func_str_ip" "root" "service mysqld status" | grep -c 'not running'` 69 if [ "$mysql_status" = 1 ] ;then 70 do_linux_by_ssh "$func_str_ip" "root" "service mysqld start" > /dev/null 71 fi 72 sleep 20 73 mysql_status=`do_linux_by_ssh "$func_str_ip" "root" "service mysqld status" | grep -c 'running'` 74 echo ${mysql_status} 75 } 76 function mysql_slave_up() { 77 # variable 78 func_str_ip="$1" 79 slave_status=`do_sql "$func_str_ip" "show slave status \g;" 2> /dev/null | grep "last_io_errno" | wc -l` 80 if [[ $slave_status == 0 ]] 81 then 82 do_sql "$func_str_ip" "set global read_only=1;set global relay_log_purge=0;" 83 do_sql "$func_str_ip" "$sql_change_master" 84 do_sql "$func_str_ip" "start slave;" 85 fi 86 slave_status=`do_sql "$func_str_ip" "show slave status \g;" 2> /dev/null | grep "last_io_errno: 0" | wc -l` 87 echo ${slave_status} 88 } 89 90 ## mha集群为2个数据节点,所以下面只循环判断server1、server2,同样如果是三个节点,则copy相关代码,修改if添加即可。 91 92 #if server1 down 93 if [ "$conf_server1" != "[server1]" ] ;then 94 #if myql status was dead , auto systemctl start mysqld 95 echo "check server1 mysql status start" 96 mysqlstatus=`mysql_stop_up "$server1"` 97 echo "server1 mysql status : $mysqlstatus" 98 if [ "$mysqlstatus" = 1 ] ; then 99 echo "server1 slave up start" 100 slave_status=`mysql_slave_up "$server1"` 101 echo "server1 slave status :$slave_status server1: $server1" 102 if [ "$slave_status" = 1 ] ; then 103 echo "write server1 app1.conf start" 104 echo -e "\n[server1]\nhostname=$server1\nport=3306" >> /etc/masterha/app1.conf 105 fi 106 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l` 107 if [ "$mha_check_result" = 1 ] ;then 108 nohup masterha_manager --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/masterha/mhalog/manager.log 2>&1 & > /dev/null 109 fi 110 fi 111 fi 112 conf_server1=`grep "server1" /etc/masterha/app1.conf` 113 114 #if server2 down 115 echo "$conf_server2":"$server2" 116 117 if [ "$conf_server2" != "[server2]" ] ;then 118 #if server2 myql status was dead , auto systemctl start mysqld 119 echo "server2 mysql stop status start" 120 mysqlstatus=`mysql_stop_up "$server2"` 121 echo "server2 ysql_stop_up status: $mysqlstatus" 122 if [ "$mysqlstatus" = 1 ] ; then 123 slave_satus=`mysql_slave_up "$server2"` 124 echo "server2 slave_status is : $slave_satus" 125 if [ "$slave_satus" = 1 ] ; then 126 echo "write server2 in app1.conf start" 127 echo -e "\n[server2]\nhostname=$server2\nport=3306" >> /etc/masterha/app1.conf 128 fi 129 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l` 130 echo "$mha_check_result" 131 if [ "$mha_check_result" = 1 ] ;then 132 nohup masterha_manager --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/masterha/mhalog/manager.log 2>&1 & > /dev/null 133 fi 134 fi 135 fi 136 conf_server2=`grep "server2" /etc/masterha/app1.conf` 137 138 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l` 139 if [ "$conf_server1" = "[server1]" ] && [ "$conf_server2" = "[server2]" ];then 140 if [ "$mha_check_result" = "1" ];then 141 nohup masterha_manager --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/masterha/mhalog/manager.log 2>&1 & > /dev/null 142 fi 143 fi
此文件中,调用mha的配置文件的参数为 /etc/masterha/app1.conf。
masterha_manager 监控所产生的log存放在 /etc/masterha/mhalog/manager.log 中。
感谢:以上代码实现主要是由同事fly chen完成。
下一篇: 养肾不只是年轻人的事儿 家里老人更需要