在大型分布式系统中,MySQL 的高可用架构和读写分离设计是构建稳定、可扩展服务的关键环节。今天我们聚焦一个极具实用价值的架构设计——在 MGR(MySQL Group Replication)集群中,通过代理层 ProxySQL(也被称为 proxy circle)实现读写分离与故障自动转移。

本文将从原理、架构、关键配置、故障处理逻辑、读写分离机制等多个方面全面剖析该方案,力图为读者在实际项目中落地提供完整指导。


一、背景介绍:MGR 高可用集群机制

在介绍 ProxySQL 之前,我们首先回顾一下 MySQL MGR(Group Replication)的基本机制:

  • MGR 是 MySQL 官方推出的一种高可用解决方案。
  • 集群内通过组复制技术,确保主从节点之间的数据强一致性,即不会出现主库有数据而从库没有的情况。
  • 所有节点间通过一致性协议(类似 Raft)进行沟通,动态选主机制确保高可用。
  • 主节点(Primary)可读可写,从节点(Secondary)默认只读,仅承担查询任务。

这种设计天然适合读写分离,但问题在于:客户端并不能自动感知主节点的变化,如果主节点发生故障,MGR 虽然能选出新主节点,但客户端连接仍指向原来的主节点,从而导致连接失败。


二、核心问题:客户端感知与读写路由缺失

典型的 Java 程序通过数据库连接池(如 HikariCP、Druid)连接数据库,通常配置一个主节点 IP 和端口。但在主节点宕机或 MGR 发生主从切换时:

  • 应用层无法感知主节点变化;
  • 连接仍指向旧主库,造成连接失败;
  • 整个服务可能出现严重异常。

因此,必须引入中间层,解耦客户端与数据库之间的直接耦合。


三、ProxySQL:数据库代理的中坚力量

为了解决客户端与 MGR 集群之间的适配问题,引入 ProxySQL 成为一种行业标准做法。ProxySQL 类似于 Web 架构中的 Nginx,它:

  • 充当中间代理;
  • 自动感知后端 MySQL 节点状态;
  • 实现读写请求的路由分发;
  • 支持高性能连接池、查询缓存、SQL 规则重写等多种高级特性。

国外社区多采用 ProxySQL(proxy circle),国内则常见 Sharding-JDBC、MyCAT,但 ProxySQL 更轻量、功能更完整,适合现代云原生场景。


四、ProxySQL + MGR 的部署架构图

+-----------------+
|    Java应用     |
|(HikariCP/Druid) |
+--------+--------+
         |
         v
+-----------------+
|    ProxySQL     |
|(proxy circle)   |
+--------+--------+
         |
  读写路由判断+健康检查
         |
         v
+------------------------------+
|        MGR集群 (3节点)      |
| +----------+  +----------+  |
| |  主节点  |  | 从节点1 |  |
| | 可读可写 |  | 只读    |  |
| +----------+  +----------+  |
|           +----------+     |
|           | 从节点2 |     |
|           | 只读    |     |
|           +----------+     |
+------------------------------+

五、ProxySQL 如何实现读写分离?

ProxySQL 之所以强大,是因为它具备以下三大能力:

1. 健康检查机制(故障自动剔除)

在 MGR 集群中,每个节点上都需创建一个专用用户 monitor@'%',该用户仅用于健康检查:

CREATE USER 'monitor'@'%' IDENTIFIED BY 'yourpassword';
GRANT SELECT ON *.* TO 'monitor'@'%';

ProxySQL 会以该用户身份,定期向每个节点发送如下 SQL:

SELECT 1;
  • 若某节点连续多次无法返回有效结果,则认为该节点宕机;
  • 节点将被动态从负载池中剔除;
  • 保证客户端不会访问到故障节点。

2. 自动识别主从角色

MGR 中主节点随时可能变化,ProxySQL 无法直接知道谁是主谁是从。为此,需要在每个节点上创建一个系统视图:

CREATE OR REPLACE VIEW sys.gr_member_routing_candidate_status AS
SELECT
  member_id,
  member_host,
  member_port,
  member_state,
  IF(VARIABLE_VALUE = 'OFF', 'writer', 'reader') AS role
FROM
  performance_schema.global_status
JOIN
  performance_schema.global_variables
WHERE
  VARIABLE_NAME = 'read_only';

ProxySQL 会定期查询该视图:

SELECT * FROM sys.gr_member_routing_candidate_status;

从而得知当前各节点的角色(主/从),并据此更新路由规则。

3. SQL 语句自动路由

ProxySQL 拥有内置的 SQL 解析引擎,可自动将语句分类:

  • INSERT/UPDATE/DELETE:写操作 → 路由到主节点;
  • SELECT:读操作 → 路由到从节点(可配置是否主节点也参与读)。

这种设计实现了彻底的读写分离,无需客户端代码变动。


六、MGR 与 ProxySQL 结合的优势

能力说明
数据强一致性MGR 使用组复制协议,保证主从数据完全同步
故障自愈主节点故障后自动选主,ProxySQL感知并切换
读写分离提高读性能,缓解主节点压力
高可用架构Java 应用始终只连接 ProxySQL,连接端无感
配置灵活ProxySQL 支持多组集群管理、ACL控制、SQL规则重写

七、关键实践建议

  1. 设置合理的探测周期和失败阈值
    避免网络抖动误判,建议设置探测周期为 2-3 秒,连续失败 3 次再剔除。

  2. ProxySQL 高可用部署
    ProxySQL 自身也应集群部署,避免单点故障,可以借助 Keepalived 或使用容器编排(如 Kubernetes)。

  3. 主节点参与查询的控制
    对于读多写少场景,可让主节点参与读,提升整体吞吐;但写多场景建议主库专注写入。

  4. SQL 黑白名单配置
    防止误将某些特定 SQL 路由到错误节点,如依赖 session 状态的事务性查询。

  5. 持续监控与告警
    结合 Prometheus + Grafana,对 ProxySQL、MGR、主从切换等进行可视化监控。


八、总结

通过为 MGR 集群引入 ProxySQL,实现了以下关键目标:

  • 彻底解耦客户端与数据库集群结构;
  • 实现透明的故障转移与主从识别;
  • 提升读写性能与系统高可用性;
  • 构建易维护、易扩展的分布式数据库访问架构。

对于架构师、中间件研发人员或 DevOps 来说,这套方案具备高度参考价值,也是未来数据库架构发展的重要方向之一。


希望本篇详解对你构建高可用、具备智能路由能力的 MySQL 数据访问层提供帮助。

更多推荐