一个现成的MGR+consul的高可用健康检查脚本
MySQL高可用的方案有很多,MGR算是比较热门的一种了,最近在研究基于MGR的高可用,关于MGR相关的文章,之前的文章中也有些过,这里可以给大家一个方法:
MGR是MySQL原生的高可用方案,不同于master-slave架构,MGR属于同步复制,MGR环境中,必须保证过半的节点收到主节点同步的数据,才能开启下一个事务,我们可以理解它保证的是主从数据的强一致性。
单纯的使用MGR并不能保证业务层面的高可用,因为对于业务来说,连接的始终只有一个IP地址,假设我们有两个服务器,IP地址分别为IP1和IP2,如果业务连接的是IP1,那么,当IP1宕机之后(服务不可用),业务逻辑代码中不会自动切换到IP2,此时虽然数据库层面没有丢失数据,但是业务也会处于不可用的状态,这个过程的示意图如下:
如果想要实现应用层面的高可用,则需要应用层自动的将应用服务器使用的IP切换到IP2上,为了解决这个问题,引入了consul的域名服务,关于consul相关的内容,这里给出传送门,有兴趣可以关注:
引入consul域名之后,我们可以在APP端去使用DNS域名的方式去连接到MySQL服务器上,这样我们只需要在IP1不可用的情况下,将DNS域名的映射关系自动转换到IP2即可,对于应用服务来说,整个过程是透明的。示意图如下:
在这个情况下,我们必须使用健康检查脚本来实时的检测服务器的可用性,说白了,就是检测不同服务器上的数据库实例是否可用。
在MGR单主模式下,我们可以下面的方法来查看MGR的组内成员和主节点信息:
select *from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+---------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+---------------+-------------+--------------+
| group_replication_applier | XXXXXXX-fba1-11e9-8397-00XXXXXX3852 | 192.168.7.XXX | 4307 | ONLINE |
| group_replication_applier | XXXXXXX-fba5-11e9-8396-00XXXXXX84a9 | 192.168.7.XXX | 4307 | ONLINE |
+---------------------------+--------------------------------------+---------------+-------------+--------------+
2 rows in set (0.00 sec)
#主节点信息如下----->
select * from performance_schema.global_status where variable_name='group_replication_primary_member';
+----------------------------------+--------------------------------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | XXXXX-fba1-11e9-8397-0XXXXXXXXa83852 |
+----------------------------------+--------------------------------------+
1 row in set (0.00 sec)
我们可以看到,当前的组内成员信息中包含了该实例的server_uuid和IP地址,而主节点的信息中包含了server_uuid的值,那么我们可以用下面的SQL来查看当前MGR组内的主节点的IP地址:
select member_host as primary_node from performance_schema.replication_group_members where member_id in (select variable_value as member_id from performance_schema.global_status where variable_name='group_replication_primary_member');
+---------------+
| primary_node |
+---------------+
| 192.168.7.XXX |
+---------------+
1 row in set (0.00 sec)
根据这个方法,我们可以在主从节点上都运行这个SQL,然后查看主节点的IP地址,然后再和本机的地址进行比对,如果相同的话,那么说明本机就是主节点,如果不同的话,那么说明本机不是主节点。
基于上面这个思路,最终写成的shell脚本如下:
#!/bin/bash
echo='/bin/echo'
cat='/bin/cat'
function usage() {
${cat} <<EOF
Usage: $0 [options]
-h, --help Show this help message.
-i, --ip_addr Give the ip_addr
-p, --db_port Give the db_port
Example:
sh $0 --ip_addr 192.168.7.XXX --db_port=4307
EOF
}
if [ $# -eq 0 ]; then
${echo} "please input a para"
usage
exit 1;
fi
GETOPT_ARGS=`getopt -o i:p: -al ip_addr:,db_port:, -- "$@"`
eval set -- "$GETOPT_ARGS"
while [ -n "$1" ]
do
case "$1" in
-i|--ip_addr) ip_addr=$2; shift 2;;
-p|--db_port) db_port=$2; shift 2;;
--) break ;;
*) ${echo} "Unknown option '$1'"; exit 1;;
esac
done
primary_ip=`/usr/local/mysql/bin/mysql -udba_admin -p此处输入你的密码 -h127.0.0.1 -P${db_port} -s -Ne "select member_host as primary_node from performance_schema.replication_group_members where member_id in (select variable_value as member_id from performance_schema.global_status where variable_name='group_replication_primary_member');"`
if [ $ip_addr = $primary_ip ];then
echo "this is primary node"
exit 0
else
echo "this is not primary node"
exit 1
fi