背景与目标
单台 Nginx 或单个数据库出问题,业务就停;误删数据如果只有昨晚的备份,当天的数据就丢了。
目标:接入层没有单点;数据库能恢复到误操作前的任意时刻;出了问题第一时间知道。
架构
接入
- 用户
- VIPVRRP 单播
- Nginx 主 / 备健康检查脚本
- 后端 ×2
数据
- MySQL 主库GTID · binlog
- 从库super_read_only
- 每日备份校验 · 异地副本
监控
- node_exporter
- Prometheus告警规则
- Alertmanager分组 · 抑制 · 静默
关键做法
- 01
Nginx 负载均衡
反向代理两台后端,upstream 轮询并在后端故障时自动切换;能根据 502、Access denied、NOAUTH 等报错定位到进程、监听地址或授权问题。
- 02
Keepalived 双机热备
两台 Nginx 共用一个 VIP,单播心跳,健康检查脚本监测 Nginx 进程;Nginx 停止或主机宕机时,VIP 秒级漂移到备机。
- 03
复现并分析脑裂
阻断两台之间的心跳,两台同时持有 VIP,用 ARP 表观察客户端实际访问的是哪一台,理解免费 ARP 和抢占机制。
- 04
MySQL GTID 主从
基于 GTID 搭建主从复制,从库开启 super_read_only;通过 SHOW REPLICA STATUS 排查 IO / SQL 线程中断。
- 05
误删库时间点恢复
模拟 DROP DATABASE,用"全量备份 + binlog"恢复到删库前一刻,数据不丢;备份定时执行并异地保存。
- 06
监控与告警
Ansible 批量部署 node_exporter,Prometheus 采集所有主机;配置告警分组、抑制和静默,服务停止约 1 分钟内告警,并发送恢复通知。
遇到的问题
用 VIP 访问报 Connection refused,但浏览器能打开
- 原因
- .100 是 VirtualBox 网段自带 DHCP 服务器的地址,IP 冲突
- 解决
- VIP 改为未使用的 .50;用 ip neigh 查 VIP 对应的 MAC 即可确认
删掉防火墙放行规则后,脑裂仍未出现
- 原因
- VRRP 流已被 conntrack 记为 ESTABLISHED,ufw 在用户规则之前就放行了
- 解决
- 用 iptables 在最前面插入 DROP 规则阻断心跳
在备份文件里找不到新语法的复制位点
- 原因
- Ubuntu 22.04 的 mysqldump 仍输出旧语法 CHANGE MASTER TO
- 解决
- 同时匹配新旧两种写法
Alertmanager 容器反复重启
- 原因
- 漏建配置文件,日志报 no such file
- 解决
- 补建配置;排查顺序:先看退出码,再看日志中的 error 行
结果
- 接入层无单点,主机宕机时 VIP 秒级切换
- 误删库可恢复到删除前一刻
- 服务停止约 1 分钟内收到告警,恢复后自动通知
- 主从、备份、告警均经过实际故障演练