1. 项目背景与核心价值
在金融、电商等对数据可靠性要求极高的业务场景中,数据库高可用性不是可选项而是必选项。传统主从复制架构下,当主库发生故障时往往需要人工介入切换,这会导致分钟级甚至更长的服务中断。我在某次支付系统故障中亲历过这种痛苦——凌晨3点被报警电话叫醒,手忙脚乱地执行failover操作,整个过程耗时8分钟,直接导致数十万笔交易失败。
MHA(Master High Availability)正是为解决这类痛点而生。这套由日本DeNA公司开源的工具集,能在30秒内完成主从自动切换,配合云原生环境下的容器化部署,可以实现真正意义上的"自愈式"数据库集群。去年我们为某证券交易系统部署的MHA集群,在全年7次硬件故障中均实现了无缝切换,业务端完全无感知。
2. 架构设计与核心组件
2.1 典型部署拓扑
一个完整的云原生MHA集群包含以下核心组件(以5节点为例):
code复制[ Kubernetes Cluster ]
│
├── [ Node1 ]: MySQL Master (可读写)
├── [ Node2 ]: MySQL Slave + MHA Manager (主监控节点)
├── [ Node3 ]: MySQL Slave + MHA Node (备选Master)
├── [ Node4 ]: MySQL Slave + MHA Node
└── [ Node5 ]: MySQL Slave + MHA Node
关键设计要点:
- Manager独立部署:建议部署在从库上而非主库,避免主库故障导致管理功能失效
- 至少3个候选Master:确保即使某个节点不可用,仍有足够候选节点接替主库角色
- VIP漂移机制:通过keepalived实现虚拟IP自动切换,应用层无需修改连接配置
2.2 核心组件交互流程
当主库发生故障时,MHA的工作流程如下:
- 故障检测:Manager通过每3秒一次的心跳检测发现主库异常
- 数据补偿:从各从库获取最新的binlog位置,确保无数据丢失
- 选举新主:根据配置策略(如最新binlog位置)选择最优从库
- 拓扑重构:自动重建复制关系,其他从库指向新主库
- 通知回调:通过自定义脚本触发VIP切换、服务发现更新等操作
关键指标:从故障发生到新主库可写,通常控制在30秒内完成
3. 云原生环境适配实践
3.1 容器化部署要点
在Kubernetes中部署需要特别注意:
yaml复制# mysql-statefulset.yaml 关键配置
securityContext:
privileged: true # 必须开启特权模式才能使用VIP
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind"]
网络配置建议:
- 使用HostNetwork模式:避免容器网络带来的延迟和复杂性
- 持久化存储:建议使用Local PV或高性能云盘,保证IO性能
- 资源限制:MySQL容器至少分配4核CPU+8GB内存
3.2 配置模板精讲
MHA的核心配置文件mha.cnf需要针对云环境优化:
ini复制[server default]
ssh_user=root
repl_user=repl
repl_password=S3cr3tP@ss
master_binlog_dir=/var/lib/mysql
[server1]
hostname=mysql-0.mysql
candidate_master=1 # 明确指定该节点有资格成为主库
[server2]
hostname=mysql-1.mysql
no_master=1 # 该节点仅作为从库
特别注意:
- 每个节点的server_id必须全局唯一
- 建议配置至少两个候选主库(candidate_master=1)
- 云环境下建议禁用SSH StrictHostKeyChecking
4. 生产环境调优指南
4.1 关键参数优化
在my.cnf中必须调整的参数:
ini复制[mysqld]
server-id = ${POD_ORDINAL} # 使用StatefulSet序号
log-bin = mysql-bin
binlog_format = ROW
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
slave_parallel_workers = 16 # 从库并行复制线程数
slave_parallel_type = LOGICAL_CLOCK
4.2 监控指标体系建设
建议采集的核心指标:
| 指标类别 | 具体指标 | 报警阈值 |
|---|---|---|
| 复制延迟 | Seconds_Behind_Master | >30秒 |
| 主库负载 | Threads_running | >CPU核数*2 |
| 网络状况 | Ping延迟 | >100ms |
| 磁盘性能 | IOPS使用率 | >80%持续5分钟 |
推荐使用Prometheus+Grafana监控方案,配置示例:
yaml复制# prometheus-rules.yaml
- alert: MySQLReplicationLag
expr: mysql_slave_status_seconds_behind_master > 30
for: 2m
labels:
severity: critical
annotations:
summary: "MySQL replication lag (instance {{ $labels.instance }})"
5. 故障处理实战记录
5.1 脑裂场景处理
某次网络分区导致出现"双主"情况,处理步骤:
- 立即停止业务写入(重要!)
- 通过GTID比对确定数据更完整的主库
- 在另一主库执行:
sql复制STOP SLAVE; RESET SLAVE ALL; SET GLOBAL read_only=1; - 重建复制关系后,通过pt-table-checksum校验数据一致性
5.2 常见错误速查表
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| Failover后应用连接失败 | VIP未成功漂移 | 检查keepalived日志,手动执行切换 |
| 从库显示Slave_IO_Running=No | 主库binlog被清理 | 重建复制并设置expire_logs_days |
| MHA切换后数据不一致 | 存在级联复制 | 禁用级联复制,确保单层拓扑 |
| Manager频繁切换主库 | 网络抖动导致误判 | 调整ping_interval到更合理值 |
6. 进阶优化技巧
6.1 无损切换方案
通过以下配置实现真正零停机切换:
perl复制# master_ip_failover脚本片段
my $vip = '192.168.1.100';
exec("arping -U -c 5 -I eth0 $vip");
system("iptables -t mangle -A POSTROUTING -p tcp --dport 3306 -j CONNMARK --set-mark 1");
配合应用层连接池的以下配置:
- testOnBorrow=true
- validationQuery="SELECT 1"
- timeBetweenEvictionRunsMillis=30000
6.2 跨可用区部署
在云环境下实现AZ级高可用:
ini复制[server1]
hostname=mysql-az1
multi_tier_slave=1 # 标记为跨AZ从库
[server2]
hostname=mysql-az2
candidate_master=1
check_repl_delay=0 # 允许跨AZ延迟
关键调整:
- 设置repl_connect_retry=60
- 增大slave_net_timeout到3600
- 使用半同步复制增强数据安全
7. 性能压测数据参考
在AWS r5.2xlarge实例上的测试结果:
| 场景 | TPS | 平均延迟 | 切换耗时 |
|---|---|---|---|
| 单主模式 | 12,356 | 8.2ms | N/A |
| MHA集群(正常) | 11,892 | 9.1ms | N/A |
| MHA切换过程中 | 2,145 | 43ms | 28.7s |
| 切换完成后1分钟内 | 9,876 | 11.3ms | N/A |
压测建议:
- 切换期间预期有70%性能下降
- 建议在业务低峰期执行维护性切换
- 提前预热连接池避免冷启动问题
8. 升级与迁移方案
8.1 在线版本升级步骤
- 滚动升级从库节点(注意版本兼容性):
bash复制
kubectl rollout restart statefulset mysql - 确认所有从库同步正常
- 通过MHA手动切换升级主库:
bash复制
masterha_master_switch --conf=/etc/mha.cnf --new_master_host=mysql-new-version
8.2 跨集群迁移技巧
使用Percona XtraBackup实现热迁移:
bash复制# 在源集群执行
xtrabackup --backup --target-dir=/data/backup \
--user=backup --password=Backup@123
# 在目标集群恢复
xtrabackup --prepare --target-dir=/data/backup
xtrabackup --copy-back --target-dir=/data/backup
关键注意事项:
- 确保GTID模式开启
- 迁移后执行CHECKSUM TABLE校验
- 建议在DNS层面做灰度切换
9. 安全加固建议
9.1 最小权限配置
创建专用账户而非使用root:
sql复制-- 复制账户
CREATE USER 'repl'@'%' IDENTIFIED BY 'ComplexP@ssw0rd';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- MHA监控账户
CREATE USER 'mha_monitor'@'10.%.%.%' IDENTIFIED BY 'Monitor@123';
GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT ON *.* TO 'mha_monitor'@'10.%.%.%';
9.2 网络隔离方案
推荐网络架构:
code复制[ 业务应用 ] → [ 数据库LB ] → [ MySQL Pod (仅开放3306) ]
↑
[ MHA Manager ] ←───────┘ (仅允许SSH和自定义端口)
使用NetworkPolicy实现精细控制:
yaml复制apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-allow-mha
spec:
podSelector:
matchLabels:
app: mysql
ingress:
- from:
- podSelector:
matchLabels:
role: mha-manager
ports:
- protocol: TCP
port: 22
- protocol: TCP
port: 9999 # MHA自定义监控端口
10. 成本优化实践
10.1 混合部署策略
针对不同业务重要性采用差异化配置:
| 业务等级 | 节点规格 | 副本数 | 存储类型 |
|---|---|---|---|
| 核心交易 | 16C32G | 3+2 | ESSD PL3 |
| 普通订单 | 8C16G | 2+1 | ESSD PL1 |
| 日志报表 | 4C8G + 只读实例 | 1 | 普通云盘 |
10.2 自动伸缩方案
基于CPU使用率的HPA配置:
yaml复制apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: mysql-readscale
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: mysql-slave
minReplicas: 2
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
配合MySQL Router实现读写分离,可节省30%以上的主库负载。