第24章:高可用方案
第24章:高可用方案
高可用是保证业务连续性的关键
24.1 高可用概述
24.1.1 什么是高可用?
定义:
- High Availability(HA)
- 系统能够持续运行,减少停机时间
- 目标:99.9%、99.99%、99.999%可用性
可用性计算:
可用性 = (总时间 - 停机时间) / 总时间 × 100%
99.9% → 年停机时间:8.76小时
99.99% → 年停机时间:52.56分钟
99.999% → 年停机时间:5.26分钟
24.1.2 为什么需要高可用?
问题场景:
- ❌ 主库故障,业务中断
- ❌ 硬件故障,数据丢失
- ❌ 人为误操作,数据损坏
高可用的目标:
- ✅ 故障自动检测
- ✅ 故障自动切换
- ✅ 数据不丢失
- ✅ 业务不中断
24.1.3 高可用方案对比
| 方案 | 自动切换 | 数据一致性 | 复杂度 | 推荐度 |
|---|---|---|---|---|
| 主从复制 | ❌ | 一般 | 低 | ⭐⭐⭐ |
| MHA | ✅ | 好 | 中 | ⭐⭐⭐⭐ |
| MGR | ✅ | 很好 | 高 | ⭐⭐⭐⭐⭐ |
| Orchestrator | ✅ | 好 | 中 | ⭐⭐⭐⭐ |
| Galera Cluster | ✅ | 很好 | 高 | ⭐⭐⭐⭐ |
24.2 MHA(Master High Availability)⭐⭐⭐⭐
24.2.1 MHA概述
什么是MHA?
- Master High Availability Manager
- 日本DeNA公司开发
- 自动主从故障切换工具
MHA架构:
MHA Manager(管理节点)
↓ 监控
主库 → 从库1
→ 从库2
→ 从库3
故障切换流程:
1. 检测主库故障
2. 选择新主库
3. 应用差异日志
4. 切换到新主库
5. 配置其他从库
MHA组件:
- MHA Manager:管理节点,监控和故障切换
- MHA Node:数据节点,在每个MySQL服务器上安装
24.2.2 MHA安装
环境准备:
# 服务器规划
192.168.1.10 master 主库
192.168.1.11 slave1 从库1(候选主库)
192.168.1.12 slave2 从库2
192.168.1.13 manager MHA管理节点
# 配置SSH免密登录(所有节点)
ssh-keygen -t rsa
ssh-copy-id root@192.168.1.10
ssh-copy-id root@192.168.1.11
ssh-copy-id root@192.168.1.12
ssh-copy-id root@192.168.1.13
安装MHA Node(所有MySQL节点):
# 安装依赖
yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager
# 下载MHA Node
wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
# 安装
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
# 验证
ls /usr/bin/
# 应该看到:
# save_binary_logs
# apply_diff_relay_logs
# filter_mysqlbinlog
# purge_relay_logs
安装MHA Manager(管理节点):
# 先安装MHA Node
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
# 下载MHA Manager
wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
# 安装
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
# 验证
ls /usr/bin/
# 应该看到:
# masterha_check_ssh
# masterha_check_repl
# masterha_manager
# masterha_master_switch
# masterha_check_status
# masterha_stop
24.2.3 MHA配置
创建MHA配置文件(/etc/mha/app1.cnf):
[server default]
# MHA Manager工作目录
manager_workdir=/var/log/mha/app1
# MHA Manager日志
manager_log=/var/log/mha/app1/manager.log
# MySQL用户(用于监控和切换)
user=mha
password=mha_password
# 复制用户
repl_user=repl
repl_password=repl_password
# SSH用户
ssh_user=root
# 监控间隔(秒)
ping_interval=3
# 主库故障后,从库等待时间
master_ip_failover_script=/usr/local/bin/master_ip_failover
# VIP切换脚本
# 发送报告
report_script=/usr/local/bin/send_report
# 二次检查
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.1.11 -s 192.168.1.12
# 主库
[server1]
hostname=192.168.1.10
port=3306
# 候选主库优先级(数字越小优先级越高)
candidate_master=1
# 从库1(候选主库)
[server2]
hostname=192.168.1.11
port=3306
candidate_master=1
# 从库2
[server3]
hostname=192.168.1.12
port=3306
# 不作为候选主库
no_master=1
创建MySQL监控用户:
-- 在所有MySQL节点上执行
CREATE USER 'mha'@'%' IDENTIFIED BY 'mha_password';
GRANT ALL PRIVILEGES ON *.* TO 'mha'@'%';
FLUSH PRIVILEGES;
创建VIP切换脚本(/usr/local/bin/master_ip_failover):
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);
my $vip = '192.168.1.100/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
return 0 unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
设置脚本权限:
chmod +x /usr/local/bin/master_ip_failover
24.2.4 MHA使用
检查SSH连接:
masterha_check_ssh --conf=/etc/mha/app1.cnf
# 输出:
# All SSH connection tests passed successfully.
检查复制状态:
masterha_check_repl --conf=/etc/mha/app1.cnf
# 输出:
# MySQL Replication Health is OK.
启动MHA Manager:
# 前台启动(测试用)
masterha_manager --conf=/etc/mha/app1.cnf
# 后台启动
nohup masterha_manager --conf=/etc/mha/app1.cnf > /var/log/mha/app1/manager.log 2>&1 &
# 查看状态
masterha_check_status --conf=/etc/mha/app1.cnf
# 输出:
# app1 (pid:12345) is running(0:PING_OK), master:192.168.1.10
手动故障切换:
# 在线切换(主库正常)
masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive \
--new_master_host=192.168.1.11 --new_master_port=3306 \
--orig_master_is_new_slave --running_updates_limit=10000
# 故障切换(主库故障)
masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=dead \
--dead_master_host=192.168.1.10 --dead_master_port=3306 \
--new_master_host=192.168.1.11 --new_master_port=3306
停止MHA Manager:
masterha_stop --conf=/etc/mha/app1.cnf
24.3 MGR(MySQL Group Replication)⭐⭐⭐⭐⭐
24.3.1 MGR概述
什么是MGR?
- MySQL Group Replication
- MySQL 5.7.17+官方提供
- 基于Paxos协议的多主复制
- 自动故障检测和切换
MGR特点:
- ✅ 自动故障检测
- ✅ 自动故障切换
- ✅ 数据强一致性
- ✅ 支持单主和多主模式
- ✅ 官方支持
MGR架构:
单主模式(推荐):
节点1(主)← 写
节点2(从)← 读
节点3(从)← 读
多主模式:
节点1(主)← 读写
节点2(主)← 读写
节点3(主)← 读写
24.3.2 MGR安装配置
环境准备:
# 服务器规划
192.168.1.10 node1 主节点
192.168.1.11 node2 从节点
192.168.1.12 node3 从节点
# MySQL版本要求:5.7.17+或8.0+
配置节点1(/etc/my.cnf):
[mysqld]
# 基本配置
server_id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
binlog_format = ROW
log_bin = mysql-bin
log_slave_updates = ON
binlog_checksum = NONE
# MGR配置
plugin_load_add = 'group_replication.so'
transaction_write_set_extraction = XXHASH64
# 组复制配置
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "192.168.1.10:33061"
loose-group_replication_group_seeds = "192.168.1.10:33061,192.168.1.11:33061,192.168.1.12:33061"
loose-group_replication_bootstrap_group = OFF
# 单主模式
loose-group_replication_single_primary_mode = ON
loose-group_replication_enforce_update_everywhere_checks = OFF
# 多主模式(可选)
# loose-group_replication_single_primary_mode = OFF
# loose-group_replication_enforce_update_everywhere_checks = ON
# IP白名单
loose-group_replication_ip_whitelist = "192.168.1.0/24"
配置节点2和节点3:
# 只需修改以下参数
server_id = 2 # 节点2
server_id = 3 # 节点3
loose-group_replication_local_address = "192.168.1.11:33061" # 节点2
loose-group_replication_local_address = "192.168.1.12:33061" # 节点3
创建复制用户(所有节点):
-- 创建复制用户
SET SQL_LOG_BIN=0;
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
-- 配置复制通道
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl_password'
FOR CHANNEL 'group_replication_recovery';
启动MGR(节点1):
-- 安装插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
-- 启动组复制(第一个节点需要bootstrap)
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
-- 查看状态
SELECT * FROM performance_schema.replication_group_members;
启动MGR(节点2和节点3):
-- 安装插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
-- 启动组复制
START GROUP_REPLICATION;
-- 查看状态
SELECT * FROM performance_schema.replication_group_members;
24.3.3 MGR监控
查看组成员:
SELECT * FROM performance_schema.replication_group_members;
-- 输出:
-- CHANNEL_NAME MEMBER_ID MEMBER_HOST MEMBER_PORT MEMBER_STATE
-- group_replication_applier aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 192.168.1.10 3306 ONLINE
-- group_replication_applier bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb 192.168.1.11 3306 ONLINE
-- group_replication_applier cccccccc-cccc-cccc-cccc-cccccccccccc 192.168.1.12 3306 ONLINE
查看主节点:
-- 单主模式下查看主节点
SELECT MEMBER_HOST, MEMBER_PORT, MEMBER_STATE, MEMBER_ROLE
FROM performance_schema.replication_group_members;
-- MEMBER_ROLE = PRIMARY:主节点
-- MEMBER_ROLE = SECONDARY:从节点
查看复制状态:
SHOW STATUS LIKE 'group_replication%';
24.3.4 MGR故障切换
自动故障切换:
# 模拟主节点故障
# 在节点1上执行
systemctl stop mysqld
# 在节点2或节点3上查看
SELECT * FROM performance_schema.replication_group_members;
# 结果:
# 节点1状态变为UNREACHABLE或消失
# 自动选举新主节点(节点2或节点3)
手动切换主节点:
-- 在当前主节点上执行
SELECT group_replication_set_as_primary('新主节点的MEMBER_ID');
-- 示例
SELECT group_replication_set_as_primary('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb');
24.4 Orchestrator ⭐⭐⭐⭐
24.4.1 Orchestrator概述
什么是Orchestrator?
- GitHub开源的MySQL高可用和复制拓扑管理工具
- 自动故障检测和切换
- Web界面管理
- 支持复杂的复制拓扑
Orchestrator特点:
- ✅ 自动发现复制拓扑
- ✅ 自动故障检测和恢复
- ✅ Web界面可视化
- ✅ 支持手动和自动切换
- ✅ 支持复杂拓扑
24.4.2 Orchestrator安装
# 下载
wget https://github.com/openark/orchestrator/releases/download/v3.2.6/orchestrator-3.2.6-1.x86_64.rpm
# 安装
rpm -ivh orchestrator-3.2.6-1.x86_64.rpm
# 配置文件
vi /etc/orchestrator.conf.json
# 启动
systemctl start orchestrator
systemctl enable orchestrator
# 访问Web界面
http://192.168.1.13:3000
24.4.3 Orchestrator配置
{
"Debug": false,
"ListenAddress": ":3000",
"MySQLTopologyUser": "orchestrator",
"MySQLTopologyPassword": "orchestrator_password",
"MySQLOrchestratorHost": "127.0.0.1",
"MySQLOrchestratorPort": 3306,
"MySQLOrchestratorDatabase": "orchestrator",
"MySQLOrchestratorUser": "orchestrator",
"MySQLOrchestratorPassword": "orchestrator_password",
"RecoveryPeriodBlockSeconds": 3600,
"RecoveryIgnoreHostnameFilters": [],
"AutoFailoverEnabled": true,
"FailureDetectionPeriodBlockMinutes": 60
}
24.5 高可用方案选择
24.5.1 方案对比
| 特性 | MHA | MGR | Orchestrator |
|---|---|---|---|
| 自动切换 | ✅ | ✅ | ✅ |
| 数据一致性 | 好 | 很好 | 好 |
| 切换速度 | 30-60秒 | 10-30秒 | 30-60秒 |
| 复杂度 | 中 | 高 | 中 |
| 官方支持 | ❌ | ✅ | ❌ |
| 社区活跃度 | 低 | 高 | 中 |
| 适用场景 | 中小型 | 中大型 | 中大型 |
24.5.2 选择建议
小型项目(<10台服务器):
- 推荐:主从复制 + MHA
- 理由:简单、成本低
中型项目(10-50台服务器):
- 推荐:MGR单主模式
- 理由:自动切换、数据一致性好
大型项目(>50台服务器):
- 推荐:MGR + ProxySQL + 分库分表
- 理由:高可用、高性能、可扩展
对数据一致性要求极高:
- 推荐:MGR
- 理由:基于Paxos协议,强一致性
对切换速度要求高:
- 推荐:MGR
- 理由:切换速度快(10-30秒)
24.6 高可用最佳实践
24.6.1 设计原则
1. 至少3个节点
- 避免脑裂
- 提高可用性
2. 跨机房部署
- 避免单点故障
- 提高容灾能力
3. 监控告警
- 实时监控复制状态
- 故障及时告警
4. 定期演练
- 定期进行故障切换演练
- 验证高可用方案
5. 数据备份
- 高可用不等于备份
- 定期备份数据
6. 文档化
- 记录架构设计
- 记录操作流程
24.6.2 常见问题
问题1:脑裂
场景:网络分区导致多个主库
解决方案:
1. 使用奇数个节点(3、5、7)
2. 使用仲裁节点
3. 使用Paxos/Raft协议(MGR)
问题2:数据丢失
场景:主库故障,binlog未同步到从库
解决方案:
1. 使用半同步复制
2. 使用MGR
3. 设置sync_binlog=1
问题3:切换时间长
场景:故障切换需要几分钟
解决方案:
1. 使用MGR(切换快)
2. 优化MHA配置
3. 减少binlog大小
问题4:从库延迟
场景:从库延迟导致切换后数据不一致
解决方案:
1. 监控主从延迟
2. 使用并行复制
3. 优化从库性能
24.7 本章总结
本章学习内容:
- ✅ 高可用概述
- ✅ MHA方案(安装、配置、使用)⭐⭐⭐⭐
- ✅ MGR方案(安装、配置、监控、故障切换)⭐⭐⭐⭐⭐
- ✅ Orchestrator方案
- ✅ 高可用方案选择
- ✅ 高可用最佳实践
重点掌握:
- 高可用目标:故障自动检测和切换
- MHA:自动主从故障切换
- MGR:基于Paxos的多主复制
- 至少3个节点避免脑裂
- 定期演练故障切换
- 高可用不等于备份
方案对比:
- MHA:成熟稳定,适合中小型
- MGR:官方支持,数据一致性好,适合中大型
- Orchestrator:可视化管理,适合复杂拓扑
MGR优势:
- 自动故障检测和切换
- 数据强一致性(Paxos)
- 切换速度快(10-30秒)
- 官方支持
最佳实践:
- 至少3个节点
- 跨机房部署
- 监控告警
- 定期演练
- 数据备份
面试重点:
- 高可用方案有哪些
- MHA和MGR的区别
- 如何避免脑裂
- 如何保证数据不丢失
- 故障切换流程
下一章预告: 分库分表
练习题
- 什么是高可用?99.99%可用性对应多少停机时间?
- MHA的工作原理是什么?
- MGR和MHA有什么区别?
- 什么是脑裂?如何避免?
- MGR的单主模式和多主模式有什么区别?
- 如何配置MGR?
- 如何监控MGR状态?
- 高可用方案如何选择?
- 高可用和备份有什么区别?
- 设计一个高可用方案
继续学习: 第25章:分库分表