HAProxy 通过 TCP 模式转发 MySQL 流量是成熟的方案,适合读副本负载均衡或主从高可用场景,但需注意事务一致性和健康检查配置。
先说结论:HAProxy 可以稳定承担 MySQL 的 TCP 负载均衡,适合读写分离架构中的读库 pooling 或主库故障转移,不适合直接对多主写流量做轮询。
- 适合:MySQL 主从架构的读流量分发、单主多从的高可用入口。
- 先准备:备份现有配置、规划健康检查账号、确认 HAProxy 编译参数是否支持 mysql-check、处理端口权限。
- 验收:通过客户端连接测试、观察 HAProxy 状态页后端存活数、检查数据库慢查询日志。
完整配置示例
以下是一个包含 global、defaults 及业务逻辑的最小可用配置结构。注意timeout配置对连接稳定性至关重要,需根据 MySQL 的wait_timeout调整。
globallog /dev/log local0maxconn 4096user haproxygroup haproxydaemondefaultslog globalmode tcpoption tcplogtimeout connect 5stimeout client 30stimeout server 30sretries 3frontend mysql_frontbind *:3306mode tcpdefault_backend mysql_backbackend mysql_backmode tcpbalance roundrobinoption tcp-check# 若编译支持 mysql-check,建议替换上一行并指定用户# option mysql-check user haproxyserver db1 192.168.1.10:3306 check inter 2s fall 3 rise 2server db2 192.168.1.11:3306 check inter 2s fall 3 rise 2
若 HAProxy 编译时启用了 mysql-check 支持,可使用option mysql-check user haproxy以获得更准确的状态判断。
权限与安全配置
1. 健康检查账号权限
在 MySQL 后端创建一个专用于健康检查的账号,遵循最小权限原则。无需授予mysql.user查询权限,仅需连接权限即可:
CREATE USER 'haproxy'@'%' IDENTIFIED BY 'password';
GRANT USAGE ON *.* TO 'haproxy'@'%';
2. 端口绑定权限
Linux 下绑定 1024 以下端口(如 3306)通常需要 root 权限。若以普通用户运行 HAProxy,有两种方案:
- 方案 A(推荐):使用 iptables 转发。HAProxy 监听高位端口(如 13306),通过 iptables 将 3306 流量转发过去。
- 方案 B:赋予 HAProxy 二进制文件能力集。
setcap 'cap_net_bind_service=+ep' /usr/sbin/haproxy。
原理与注意事项
MySQL 协议基于 TCP 长连接,不像 HTTP 那样有明确的请求 - 响应边界。HAProxy 在 TCP 模式下工作在四层,只负责转发数据包,不解析 SQL 语句。这意味着 HAProxy 无法知道当前连接是否正在进行事务,如果在事务中间将连接切换到另一台服务器,会导致数据不一致或报错。
因此,TCP 模式负载均衡的核心在于保持连接的持续性,并通过健康检查确保后端数据库可达。同时,必须配置合理的timeout参数,防止长查询被意外切断。
分步处理
1. 安装与检查
在 Linux 服务器上安装 HAProxy。安装后运行haproxy -v查看版本,并通过haproxy -vv确认编译特性中是否包含USE_MYSQL,这决定了能否使用专用的 MySQL 健康检查。
2. 编写配置文件
编辑/etc/haproxy/haproxy.cfg。确保mode tcp在 frontend 和 backend 中都设置,并补充全局超时参数。
3. 验证配置语法
启动前必须检查配置语法,避免服务中断:
haproxy -c -f /etc/haproxy/haproxy.cfg
4. 重启服务
语法检查通过后,重启 HAProxy 服务。建议先在非高峰期操作,并保留旧版本配置文件以便回滚。
怎么验证是否生效
1. 连通性测试
使用 MySQL 客户端连接 HAProxy 的 VIP 地址:
mysql -h <haproxy_ip> -P 3306 -u root -p
连接成功后,执行SELECT @@hostname;多次,观察返回的主机名是否在后端服务器列表内变化(取决于平衡算法)。
2. 查看 HAProxy 状态页
如果配置了 stats 监听,访问对应 URL 查看后端服务器状态是否为UP。检查sess(会话数)和bin/bout(流量)是否有增长。
3. 数据库侧确认
在后端 MySQL 服务器上执行SHOW PROCESSLIST;,确认连接来源 IP 是 HAProxy 服务器的地址,而不是客户端直连 IP。
常见坑
1. 事务被切断
不要对写流量做多主负载均衡。如果后端是多主架构,HAProxy 无法感知事务状态,轮询可能导致同一事务的不同语句落到不同库上。写流量建议指向单主,或通过中间件处理。
2. 健康检查过于简单
仅使用 TCP 端口检查(check)只能证明端口通,不能证明 MySQL 服务正常。如果可能,尽量使用option mysql-check。
3. 连接超时设置不当
缺少timeout配置或设置过短会导致长查询被强制断开。建议timeout server略大于 MySQL 的wait_timeout,并根据业务慢查询情况调整。
4. 客户端 IP 丢失
TCP 模式下,MySQL 看到的源 IP 是 HAProxy 的 IP。如果数据库有基于 IP 的权限控制,需要放行 HAProxy 服务器 IP,而非客户端 IP。
参考来源
- HAProxy Official Documentation, "Configuration Manual", https://www.haproxy.org/
- HAProxy Technology Blog, "Load balancing MySQL with HAProxy", https://www.haproxy.com/blog/
原文链接:https://www.zjcp.cc/ask/11298.html
