mysql高可用架构之MHA部署(二)VIP漂移(保姆级)

本教程接上篇mysql高可用架构之MHA部署(一)(保姆级),手动模拟故障后,再次将故障节点加入主从架构,并且实现主节点IP漂移

1、故障节点加入主从架构

由于MHA运行结束后,mysql主从架构发生了改变,主节点已经由之前的【10.0.0.60】变为【10.0.0.61】,要想再次恢复到一主两从的架构,需要手动将

【10.0.0.60】作为从节点加入到里面,下面开始操作

【10.0.0.60】执行:

  • 停止复制进程并重置
sql 复制代码
mysql> stop slave;
mysql> reset slave all;
  • 从库重新chage master to,主库改成10.0.0.61
sql 复制代码
mysql> CHANGE MASTER TO
  MASTER_HOST='10.0.0.61',
  MASTER_USER='repl',
  MASTER_PASSWORD='2544',
MASTER_AUTO_POSITION=1;
  • 开启线程:
sql 复制代码
mysql> start slave;
  • 查看主从复制状态正常
sql 复制代码
mysql> show slave status\G

可以看到10.0.0.60作为从库,10.0.0.61作为主库

2、修改MHA配置文件,使之适配修改后的主从架构

由于主从架构有变,之前的从变成了主,所以配置文件也需要做修改,使得MHA能再次使用

bash 复制代码
vim /etc/mha/mysql_cluster.cnf

我们会发现这里没有最初的[server1]的配置了,这是由于MHA实现了故障切换,会从配置文件踢掉故障的节点,我们需要修改的是将[server1]加进去,并且指定[server1]作为下一次故障后的主节点

修改后的配置,需要注意的是加入[server1]后,额外添加candidate_master=1指定下次故障后[server1]作为主节点,并注释掉[server2]里面的candidate_master=1

3、检查MHA的可用性、验证集群状态

  1. 检查MHA复制健康状态(确保所有节点正常)
bash 复制代码
masterha_check_repl --conf=/etc/mha/mysql_cluster.cnf

返回值为:MySQL Replication Health is OK.

  1. 检查 SSH 免密登录
bash 复制代码
masterha_check_ssh --conf=/etc/mha/mysql_cluster.cnf

返回值为:All SSH connection tests passed successfully.

  1. 重启MHA Manager服务(使配置生效)
bash 复制代码
nohup masterha_manager   --conf=/etc/mha/mysql_cluster.cnf   --remove_dead_master_conf   --ignore_laster_failover   > /var/log/mha/mysql_cluster/manager.log 2>&1 &
  1. 确认MHA状态
bash 复制代码
masterha_check_status --conf=/etc/mha/mysql_cluster.cnf

#正常输出应为:mysql_cluster (pid: xxxx) is running(0:PING_OK)

这里返回值为:

mysql_cluster (pid:4063) is running(0:PING_OK), master:10.0.0.61

  1. 删除mysql_cluster.failover.complete
bash 复制代码
cd /var/log/mha/mysql_cluster/
rm -rf mysql_cluster.failover.complete

mysql_cluster.failover.complete 作为故障转移完成的标志:供管理员或脚本判断 "上一次故障转移是否成功结束"。当 MHA 完成一次故障转移后,会在 管理节点的工作目录(通常是 --manager_workdir 指定的路径,MHA管理节点mha manger 配置文件里面写了

去该路径下删除即可

4、应用透明


在讨论 "MHA 应用透明(VIP)" 时,首先需要结合 "MHA" 的常见场景定义 ------ 其最广泛的指向是 MySQL High Availability(MySQL 高可用)解决方案,核心用于保障 MySQL 数据库集群的稳定性、故障自动切换与数据一致性,而 "透明(VIP)" 则通常关联 "虚拟 IP(Virtual IP,简称 VIP)"技术,是实现 MHA 高可用 "透明化" 的关键组件。以下从核心概念、实现逻辑、VIP 的核心作用及典型应用场景展开说明,帮你全面理解这一技术组合:

4.1 核心概念:MHA 与 "透明(VIP)" 的关联

MHA(MySQL High Availability)是一套开源的 MySQL 高可用架构方案,由 "MHA Manager(管理节点)" 和 "MHA Node(数据节点,部署在每个 MySQL 服务器上)" 组成,核心能力是:

  • 实时监控 MySQL 主从集群的健康状态(如主库宕机、网络中断);
  • 故障发生时自动完成 "主库切换"(从多个从库中选最优从库升级为主库);
  • 最小化数据丢失(通过 binlog 补传等机制)。
  • "透明(VIP)" 的核心:虚拟 IP(VIP)技术 "透明" 在这里的核心含义是 "对应用层无感知" ------ 即 MySQL 集群发生主从切换后,应用程序无需修改数据库连接地址(IP),仍能正常访问新的主库。而实现这一 "透明性" 的关键就是VIP:
  • VIP 是一个 "逻辑 IP 地址",不绑定到具体的物理服务器网卡,而是动态绑定到当前的 MySQL 主库服务器上。应用程序始终连接 VIP,当主库故障、MHA 切换新主库后,MHA 会自动将 VIP 从旧主库 "漂移" 到新主库,从而实现应用访问的无缝衔接。

5.2 MHA+VIP 实现 "应用透明" 的核心逻辑(步骤)

以典型的 "1 主 2 从" MySQL 集群为例,MHA+VIP 的工作流程如下,全程对应用无感知:

  1. 正常状态:VIP 绑定主库
    初始时,MySQL 主库(如服务器 A)正常运行,MHA Manager 将 VIP(如192.168.1.100)绑定到服务器 A 的网卡上;应用程序的数据库连接地址配置为 VIP(192.168.1.100),所有读写请求通过 VIP 路由到主库 A。
  2. 故障触发:主库宕机,MHA 检测并选新主
    若主库 A 因硬件故障、网络中断等宕机,MHA Node 会向 MHA Manager 上报故障;MHA Manager 通过 "日志完整性、从库延迟、服务器配置" 等指标,从 2 个从库(如服务器 B、C)中选择最优节点(如 B)作为新主库。
  3. VIP 漂移:实现应用透明切换
    MHA Manager 自动执行 "VIP 漂移" 操作:先解除旧主库 A 的 VIP 绑定(若 A 仍存活则强制解绑),再将 VIP 绑定到新主库 B 的网卡;整个漂移过程通常在秒级完成(取决于 MHA 配置的检测间隔),应用程序的数据库连接无需修改,仍通过 VIP(192.168.1.100)访问,此时请求会自动路由到新主库 B,实现 "无感知切换"。
  4. 恢复后:旧主库归位,VIP 保持在新主
    旧主库 A 修复后,MHA 会将其自动配置为新主库 B 的从库(同步新主库数据),VIP 则保持绑定在新主库 B 上,避免再次切换影响应用。

5.3 VIP 在 MHA "应用透明" 中的 3 个核心作用

5.4 典型应用场景(适合用 MHA+VIP 的场景)

  • 对数据库可用性要求高的业务:如电商交易、金融支付、实时订单系统,需避免因 MySQL 故障导致业务中断;
  • 应用层不支持 "多主库地址配置" 的场景:部分老旧应用或第三方系统仅支持单数据库 IP 配置,无法通过应用层实现主从切换,需依赖 VIP 实现透明访问;
  • 中小规模 MySQL 集群:MHA+VIP 架构轻量、开源(无额外 license 成本),适合 10 节点以内的 MySQL 主从集群,运维成本较低。

5.5 注意事项(避免 "透明性" 失效的关键)

  • VIP 漂移的网络权限:MHA Manager 需要拥有 "修改各 MySQL 节点网卡 IP" 的权限(如 root 权限),否则无法执行 VIP 绑定 / 解绑操作;
  • 避免 VIP 冲突:VIP 需与 MySQL 集群在同一网段,且不能与其他服务器的物理 IP 重复,否则会导致网络冲突;
  • 双 VIP 配置(可选):若需区分 "读请求" 和 "写请求",可配置两个 VIP (写 VIP 绑定主库,读 VIP 绑定从库),进一步优化读写分离的透明性;
  • 监控 VIP 状态:需额外监控 VIP 的绑定状态(如通过 Zabbix、Prometheus),避免因 MHA 故障导致 VIP 未漂移,引发 "应用连不上库" 的隐性问题。

如果你的 "MHA" 指向其他领域(如特定行业的系统、软件缩写),可以补充说明具体场景


根据需求,我设计了一个仅在 Manager 节点部署的脚本,它会使用你在主库手工配置的 VIP,实现 MHA 的 VIP 透明切换功能。这个脚本会将预设的 VIP 信息写入配置,并在故障发生时自动将 VIP 从旧主库迁移到新主库。

bash 复制代码
vim /usr/local/bin/master_ip_failover.sh
#!/bin/bash
# 脚本用途:MHA master_ip_failover_script 专用(兼容状态检查和故障切换)
# 支持两种参数模式:
# 1. 状态检查:--command=status --orig_master_ip=xxx --orig_master_port=xxx...
# 2. 故障切换:start/stop 旧主IP 旧主端口 新主IP 新主端口 MHA节点IP

# -------------------------- 配置区(修改为你的环境)--------------------------
VIP="10.0.0.55"               # VIP地址
NETMASK="24"                  # 子网掩码
VIRTUAL_INTERFACE="ens33:1"   # 虚拟接口
SSH_USER="root"               # SSH免密用户
LOG_FILE="/var/log/mha/vip_failover.log"  # 日志路径
# ---------------------------------------------------------------------------------

# 确保日志目录存在
[ -d $(dirname $LOG_FILE) ] || mkdir -p $(dirname $LOG_FILE)

# -------------------------- 工具函数 --------------------------
log() {
    local log_time=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$log_time] $1" >> $LOG_FILE
    echo "[$log_time] $1"
}

# SSH执行命令
ssh_exec() {
    local host="$1"
    local cmd="$2"
    ssh -o BatchMode=yes -o ConnectTimeout=5 "$SSH_USER@$host" "$cmd" > /dev/null 2>&1
    return $?
}

# -------------------------- VIP操作函数 --------------------------
# 添加VIP
vip_add() {
    local host="$1"
    local vip_full="$VIP/$NETMASK"
    log "在 $host 添加VIP:$vip_full(接口:$VIRTUAL_INTERFACE)"
    ssh_exec "$host" "ifconfig $VIRTUAL_INTERFACE $vip_full up"
    sleep 3
    ssh_exec "$host" "ifconfig $VIRTUAL_INTERFACE 2>/dev/null | grep -q '$VIP'"
    if [ $? -eq 0 ]; then
        log "$host VIP添加成功"
        return 0
    else
        log "$host VIP添加失败"
        return 1
    fi
}

# 移除VIP
vip_remove() {
    local host="$1"
    log "从 $host 移除VIP:$VIP(接口:$VIRTUAL_INTERFACE)"
    ssh_exec "$host" "ifconfig $VIRTUAL_INTERFACE down"
    sleep 2
    ssh_exec "$host" "ifconfig $VIRTUAL_INTERFACE 2>/dev/null | grep -q '$VIP'"
    if [ $? -ne 0 ]; then
        log "$host VIP移除成功"
        return 0
    else
        log "$host VIP移除失败(可能已宕机)"
        return 0
    fi
}

# 检查VIP状态(供status命令使用)
vip_check_status() {
    local host="$1"
    ssh_exec "$host" "ifconfig $VIRTUAL_INTERFACE 2>/dev/null | grep -q '$VIP'"
    if [ $? -eq 0 ]; then
        log "VIP在 $host 上存在"
        return 0
    else
        log "VIP在 $host 上不存在"
        return 1
    fi
}

# -------------------------- 参数解析与处理 --------------------------
# 解析键值对参数(状态检查时使用)

# 解析键值对参数(状态检查时使用)

# 解析键值对参数(MHA触发的status/stopssh/start/stop命令均在此处理)
parse_key_value_params() {
    local command=""
    local orig_master_ip=""  # 旧主库IP(stop命令用)
    local new_master_ip=""   # 新主库IP(start命令用)
    local orig_master_port=""
    local new_master_port=""

    # 1. 提取所有键值对参数(包括start/stop命令需要的新/旧主库IP)
    for param in "$@"; do
        case "$param" in
            --command=*)        command="${param#*=}" ;;
            --orig_master_ip=*) orig_master_ip="${param#*=}" ;;  # 旧主库IP(stop命令用)
            --new_master_ip=*)  new_master_ip="${param#*=}" ;;   # 新主库IP(start命令用)
            --orig_master_port=*) orig_master_port="${param#*=}" ;;
            --new_master_port=*) new_master_port="${param#*=}" ;;
        esac
    done

    # 2. 处理MHA触发的4种核心命令
    case "$command" in
        # 命令1:status(检查主库VIP状态)
        status)
            log "收到status命令,检查主库 $orig_master_ip 的VIP状态"
            [ -z "$orig_master_ip" ] && { log "错误:缺少orig_master_ip参数"; return 1; }
            vip_check_status "$orig_master_ip"
            return $?
            ;;
        
        # 命令2:stopssh(释放旧主库SSH连接,无需实际操作)
        stopssh)
            log "收到stopssh命令,释放旧主库 $orig_master_ip 的SSH连接(无需操作)"
            return 0
            ;;
        
        # 命令3:stop(从旧主库删除VIP)
        stop)
            log "收到stop命令,从旧主库 $orig_master_ip 移除VIP"
            [ -z "$orig_master_ip" ] && { log "错误:缺少orig_master_ip参数"; return 1; }
            vip_remove "$orig_master_ip"  # 复用已有的VIP删除函数
            return $?
            ;;
        
        # 命令4:start(在新主库添加VIP)
        start)
            log "收到start命令,在新主库 $new_master_ip 添加VIP"
            [ -z "$new_master_ip" ] && { log "错误:缺少new_master_ip参数"; return 1; }
            vip_add "$new_master_ip"  # 复用已有的VIP添加函数
            return $?
            ;;
        
        # 不支持的命令
        *)
            log "不支持的命令:$command"
            return 1
            ;;
    esac
}



# 处理位置参数(故障切换时使用)
handle_position_params() {
    local operation="$1"
    local old_master_ip="$2"
    local old_master_port="$3"
    local new_master_ip="$4"
    local new_master_port="$5"
    # local mha_ip="$6"  # 第6个参数暂不使用

    case "$operation" in
        start)
            log "收到start命令,在新主库 $new_master_ip 添加VIP"
            [ -z "$new_master_ip" ] && { log "错误:新主库IP为空"; return 1; }
            vip_add "$new_master_ip"
            ;;
        stop)
            log "收到stop命令,从旧主库 $old_master_ip 移除VIP"
            [ -z "$old_master_ip" ] && { log "错误:旧主库IP为空"; return 1; }
            vip_remove "$old_master_ip"
            ;;
        release)
            log "收到release命令,无需操作"
            return 0
            ;;
        *)
            log "不支持的操作:$operation"
            return 1
            ;;
    esac
}

# -------------------------- 脚本入口 --------------------------
log "===== 脚本启动,参数总数:$# ====="
log "参数列表:$*"

# 区分参数模式:键值对参数(含--command)还是位置参数
if [[ "$*" == *--command=* ]]; then
    # 处理状态检查的键值对参数
    parse_key_value_params "$@"
else
    # 处理故障切换的位置参数(兼容5或6个参数)
    if [ $# -eq 5 ] || [ $# -eq 6 ]; then
        handle_position_params "$1" "$2" "$3" "$4" "$5" "$6"
    else
        log "错误:位置参数数量不正确(实际$#个,需5或6个)"
        exit 1
    fi
fi

log "===== 脚本执行结束 ====="
exit 0

脚本使用说明

这个脚本完全符合需求:

1、仅在 MHA Manager 节点部署

2、使用你预先在主库手工配置的 VIP(通过ifconfig ens33:1 10.0.0.55/24)

3、实现 VIP 透明切换功能,应用无需感知数据库主从切换

配置步骤

首先在主库手工配置 VIP(这是你的要求):

#在MySQL主库服务器上执行

bash 复制代码
ifconfig ens33:1 10.0.0.55/24 up
[root@mysql_0 ~]# ifconfig ens33:1  10.0.0.55/24
[root@mysql_0 ~]# ifconfig ens33:1 10.0.0.55/24 up

这里会出现子ip

bash 复制代码
vim  /usr/local/bin/master_ip_failover.sh

在 Manager 节点配置脚本:

复制上述脚本到 MHA Manager 节点(如/usr/local/bin/目录,修改脚本顶部的配置区域,确保与你的环境一致:

bash 复制代码
VIP="10.0.0.55"               # 与你手工配置的VIP一致
NETMASK="24"                  # 子网掩码
INTERFACE="ens33"             # 主库物理网卡
VIRTUAL_INTERFACE="ens33:1"   # 虚拟接口,与手工配置一致
SSH_USER="root"               # 具有免密登录权限的用户
MHA_CONF="/etc/mha/mysql_cluster.cnf"  # MHA配置文件路径

赋予执行权限:

bash 复制代码
chmod +x   /usr/local/bin/master_ip_failover.sh

要让 MHA 在检测到主库故障并完成切换后自动调用此脚本迁移 VIP,需要修改 MHA 配置文件:

bash 复制代码
[server default]
#其他配置...
master_ip_failover_script=/usr/local/bin/master_ip_failover.sh

例如:

这样,当 MHA 执行故障切换时,会自动调用脚本将 VIP 从旧主库迁移到新主库,实现对应用的透明性。

脚本核心功能

使用这个脚本后,应用程序只需连接 VIP(10.0.0.55),无论 MHA 何时进行主从切换,应用都无需修改配置,实现了真正的透明访问。

6、修改完配置文件,需要重新运行MHA程序

  • 1、MHA 启动
bash 复制代码
nohup masterha_manager   --conf=/etc/mha/mysql_cluster.cnf   --remove_dead_master_conf   --ignore_laster_failover   > /var/log/mha/mysql_cluster/manager.log 2>&1 &
  • 2、MHA 停止
bash 复制代码
masterha_stop  --conf=/etc/mha/mysql_cluster.cnf
  • 3、检查 MHA 状态
bash 复制代码
masterha_check_status --conf=/etc/mha/mysql_cluster.cnf
  • 4、检查 SSH 免密登录
bash 复制代码
masterha_check_ssh --conf=/etc/mha/mysql_cluster.cnf
  • 5、检查主从复制
bash 复制代码
masterha_check_repl --conf=/etc/mha/mysql_cluster.cnf

这里就可以看到主从架构、以及VIP在哪台服务器

7、停掉主库mysql(模拟mysql故障)、在主库服务器执行

bash 复制代码
systemctl stop mysqld
  • 1、删除报错文件(如果有)
bash 复制代码
rm -f /var/log/mha/mysql_cluster/mysql_cluster.failover.error
  • 2、观测VIP脚本日志
bash 复制代码
 tail -f /var/log/mha/vip_failover.log

可以看到VIP由原主库【10.0.0.61】变到新主库【10.0.0.60】上了

在【10.0.0.60】查看VIP信息,确实有了

  • 3、查看MHA日志
bash 复制代码
vim /var/log/mha/mysql_cluster/manager.log

可以看到当旧主库【10.0.0.61】宕掉之后,新的主库【10.0.0.60】顶替了。

VIP漂移也实现了。主库切为【10.0.0.60】了

至此,我们实现了MHA高可用,并且实现了应用透明(VIP),浮动IP漂移

,后面在第三篇我也会进行MHA邮箱告警的配置。

相关推荐
-Xie-3 小时前
Mysql杂志(三十一)——Join连接算法与子查询、排序优化
数据库·mysql
wh_xia_jun3 小时前
物联网二级平台设计与实现:从Home Assistant到JetLinks的设备协同架构实践
物联网·架构
上海云盾-高防顾问3 小时前
智能化 DDOS 防护平台架构与演进方向
架构·ddos
程序新视界3 小时前
在连表查询场景下,MySQL隐式转换存在的坑
数据库·mysql·dba
冰糖猕猴桃4 小时前
【AI】深入 LangChain 生态:核心包架构解析
人工智能·ai·架构·langchain
咋吃都不胖lyh4 小时前
MySQL 与Power BI 的作用,以及在数据分析中扮演的角色
mysql·数据分析·powerbi
深海呐4 小时前
Android 编译速度优化:JVM堆内存扩充
android·jvm·jvm内存扩充·android 加快编译速度
心随雨下5 小时前
Flutter中新手需要掌握的几种Widget
android·flutter·ios
叶辞树5 小时前
查看安卓设备的音视频解码器信息
android