HAProxy 通过 mode tcp 配置四层负载均衡来转发 MySQL 连接,适用于数据库高可用架构,但 HAProxy 本身是负载均衡器而非连接池中间件。配置错误可能导致事务跨节点失败或健康检查不通。
先说结论:HAProxy 适合做 MySQL 的 TCP 流量分发,不能替代 ProxySQL 做连接复用,需配合正确的健康检查。
- 适合:MySQL 主从读写分离、一主多从高可用入口、需要统一入口 IP 的场景。
- 先准备:确认 HAProxy 版本支持
option mysql-check,并在 MySQL 中创建专用于健康检查的账号。 - 验收:通过
show stat查看后端状态为 UP,且客户端连接能正常执行 SQL 查询。
命令速用版
listen mysql_cluster
bind :3306
mode tcp
balance source
option mysql-check user haproxy
server db1 192.168.1.1:3306 check
server db2 192.168.1.2:3306 check为什么会这样
HAProxy 在 TCP 模式下不解析 MySQL 协议内容,只负责转发数据包,因此无法像代理池那样复用后端连接。MySQL 是有状态协议,事务过程中的多次请求必须落在同一台后端服务器上,否则会导致数据不一致。使用 balance source 可以根据客户端 IP 保持会话粘性,减少事务跨节点风险,但最根本的解决方案是在应用层管理连接或使用专门的数据库中间件。
分步处理
第一步:安装与版本确认
在 Linux 服务器上安装 HAProxy,执行 haproxy -v 确认版本。公开资料中没有看到可靠的量化数据表明特定版本对 MySQL 性能有显著差异,但建议使用 2.0 及以上稳定版以支持完整的 health check 功能。
第二步:创建健康检查账号
登录 MySQL 执行 CREATE USER 'haproxy'@'%' IDENTIFIED BY 'password'; 并授予 SELECT 权限。健康检查账号不需要写权限,仅需能登录并返回 OK 信号,避免权限过大带来安全风险。
第三步:编写配置文件
编辑 /etc/haproxy/haproxy.cfg,在 defaults 段设置 mode tcp 和超时时间,在 listen 段绑定 3306 端口。配置中必须包含 option mysql-check user haproxy,否则 HAProxy 无法判断数据库实例是否真正可用。
第四步:启动与重载
执行 haproxy -c -f /etc/haproxy/haproxy.cfg 检查配置语法,确认无误后使用 systemctl restart haproxy 启动服务。如果启动失败,查看 /var/log/haproxy.log 或系统日志定位绑定端口冲突或权限问题。
怎么验证是否生效
检查后端状态
进入 HAProxy 统计页面或命令行,执行 echo "show stat" | socat stdio /var/run/haproxy/admin.sock。确认 mysql_cluster 下各 server 的状态列显示为 UP,如果显示 DOWN 则健康检查失败。
客户端连接测试
使用 MySQL 客户端连接 HAProxy 的 IP 和端口,执行 SELECT 1; 和事务操作。观察多次连接是否稳定,并通过 MySQL 日志确认请求是否按预期分发到后端实例。
常见坑
误用 HTTP 模式
如果在配置中写了 mode http,HAProxy 会尝试解析 HTTP 头,导致 MySQL 二进制协议握手失败,客户端会报连接错误。必须确保 defaults 或 listen 段明确指定 mode tcp。
健康检查权限不足
如果 MySQL 用户没有登录权限或密码错误,HAProxy 会认为后端宕机并剔除节点。确保健康检查用户允许从 HAProxy 服务器 IP 登录,且密码配置一致。
连接数限制
HAProxy 和 MySQL 都有最大连接数限制,高并发下可能触发 Too many connections。需要在 HAProxy 配置中调整 maxconn,并在 MySQL 中调整 max_connections,公开资料中没有看到可靠的量化数据表明具体数值,需根据实际压测调整。
常见问题
HAProxy 和 ProxySQL 做 MySQL 负载均衡有什么区别?
HAProxy 是四层负载均衡,只转发连接,不支持 SQL 解析和连接复用;ProxySQL 是七层数据库代理,支持查询路由和连接池。如果只需要高可用入口选 HAProxy,如果需要读写分离和连接复用选 ProxySQL。
balance 算法选 roundrobin 还是 source?
建议优先选 source,因为 MySQL 事务需要会话保持,roundrobin 可能导致同一事务的多次请求落到不同后端。除非应用层完全无状态且不使用事务,否则 source 更安全。
健康检查频率太高会影响数据库吗?
默认检查频率较低,通常不会影响性能。如果担心压力,可以在 server 行添加 inter 参数调整检查间隔,例如 inter 5000 表示 5 秒检查一次。
参考来源
HAProxy Documentation, Configuration Manual, https://docs.haproxy.org/