Mycat 和 ProxySQL 都是常用的数据库代理工具,主要用于 MySQL 或 MariaDB 数据库的负载均衡、故障转移、读写分离等场景。尽管它们都能为分布式数据库架构提供中间层服务,但它们的设计理念、功能特性、性能优化等方面有所不同。下面是它们的详细优缺点对比:

Mycat vs ProxySQL 优缺点对比

特性/工具MycatProxySQL
架构类型基于 Java 的分布式数据库中间件,支持 MySQL、MariaDB、Oracle 等基于 C 语言的高性能 MySQL 代理层,专为 MySQL 设计
负载均衡支持读写分离、轮询、加权等多种负载均衡策略支持高级的读写分离、SQL 路由、连接池等负载均衡方式
支持的数据库支持 MySQL、MariaDB、Oracle、PostgreSQL(通过插件)主要支持 MySQL、MariaDB,部分支持 PostgreSQL(通过插件)
性能由于是基于 Java 的中间件,性能相对较低性能优越,特别适合高并发场景,因其基于 C 语言开发
高可用性支持集群部署、故障转移、主从复制、双主等高可用方案支持高可用性,具有自动故障转移机制,支持基于心跳的健康检查
配置方式配置较复杂,依赖于 XML 配置文件和管理界面配置灵活,支持通过 SQL 动态管理,无需重启
负载均衡策略支持读写分离、轮询、加权等,且支持 SQL 路由支持多种负载均衡策略,如基于权重的负载均衡、查询类型路由等
连接池管理支持连接池管理,但性能和扩展性相对较弱高效的连接池管理,支持线程池和查询缓存,大幅提升性能
故障转移和重试机制支持主备切换和故障转移,但不如 ProxySQL 灵活支持快速故障转移和连接重试机制,且能自动恢复
SQL 路由支持复杂的 SQL 路由(例如分库分表)支持基于规则的 SQL 路由,尤其适合多种不同的 SQL 路由需求
分布式支持提供分布式数据库集群和分片支持,支持垂直、水平分库分表不直接支持分布式数据库,但可通过多个代理实例间接支持
扩展性可通过插件扩展,但由于是 Java 架构,扩展性受限高度可扩展,且与 MySQL 的集成非常紧密,能够轻松扩展更多功能
支持的协议MySQL 协议,部分支持 PostgreSQL 和其他数据库完全兼容 MySQL 协议,支持 MariaDB 和 Percona Server
监控与管理提供了 Web 界面和命令行管理界面,但使用不如 ProxySQL 灵活提供强大的管理和监控功能,支持 Web 界面、命令行、SQL 命令接口
社区支持有一定的社区支持,主要是中文社区,开发较为活跃社区活跃,支持广泛,尤其是英语社区支持较好
文档与资源中文文档较为完善,英文文档相对较少英文文档非常详细,广泛的用户和开发者支持
容错性支持故障转移和负载均衡,但相较 ProxySQL 配置较为复杂容错性强,支持自动重试和故障转移,简化了配置
资源消耗相对较高,尤其是在大规模分布式环境中,需要较多内存和 CPU 资源较低,资源消耗优化较好,适合高负载、高并发的场景
部署和使用简便性部署相对复杂,配置较为繁琐,适用于更复杂的应用场景部署简单,适用于大多数生产环境,提供多种灵活配置选项

Mycat 优点:

  1. 多数据库支持:Mycat 不仅支持 MySQL、MariaDB,还可以通过插件支持其他数据库(例如 Oracle、PostgreSQL)。
  2. 分布式数据库集群:内置支持分布式数据库架构,支持数据分片、主从复制等。
  3. 灵活的路由功能:提供强大的 SQL 路由功能,支持复杂的分库分表、读写分离等策略。
  4. 高度可定制化:通过插件可以扩展更多功能,如支持不同类型的数据库。

Mycat 缺点:

  1. 性能较差:由于是基于 Java 实现的,因此在高并发环境下性能相对较差。
  2. 配置复杂:配置相对较为复杂,管理和使用较为困难。
  3. 社区支持较弱:主要是中文社区,英文文档和支持较少。

ProxySQL 优点:

  1. 高性能:由于是用 C 语言编写,ProxySQL 在高并发环境下的性能非常优秀,适合大规模的数据库代理。
  2. 易于配置和管理:支持动态 SQL 配置,通过 SQL 命令可以实时更改配置,不需要重启。
  3. 支持多种负载均衡策略:提供了多种负载均衡和路由策略,支持更加复杂的路由需求。
  4. 连接池优化:连接池和缓存机制非常高效,有助于减少数据库连接数,提高性能。
  5. 灵活的故障转移机制:支持基于健康检查的自动故障转移和自动恢复。

ProxySQL 缺点:

  1. 仅支持 MySQL 和 MariaDB:ProxySQL 主要支持 MySQL 和 MariaDB,不像 Mycat 那样支持多种数据库。
  2. 功能相对较为单一:虽然功能强大,但在一些复杂的分布式场景中,ProxySQL 的功能相比 Mycat 稍显单一。
  3. 配置较为高级:虽然配置灵活,但对于新手来说,ProxySQL 的配置和使用可能较为复杂。

总结

  • Mycat 更适合需要多种数据库支持、复杂的分布式架构和分库分表需求的场景。它适用于中大型企业的数据库中间件解决方案,尤其是在复杂的 SQL 路由和分布式数据库方面表现较好。
  • ProxySQL 则非常适合高性能、高并发的 MySQL 或 MariaDB 环境,特别是在需要高效连接池、负载均衡和故障转移机制的场景中表现优异。它简单易用,适合对 MySQL 环境有较高要求的企业。

如何使用 ProxySQL 实现负载均衡

要实现 主库既支持读也支持写,而从库只支持读 的配置,需要把写请求固定到主库,并把读请求路由到一个同时包含主库和从库的读主机组。示例中的密码和服务地址均为占位符,生产环境应使用最小权限账号和 Secret。

关键点:

  • 主库:处理读写请求。
  • 从库:只处理读请求(SELECT)。

具体步骤:

  1. 调整 ProxySQL 配置:你需要将主库配置为处理读写请求,从库配置为只处理读请求。
  2. 更新路由规则:配置 SQL 路由规则来确保写请求路由到主库,读请求可以同时路由到主库和从库。

配置方案

1. 配置 MySQL 主从架构

首先,确保你已经有一个 MySQL 主从架构 部署在 Kubernetes 中,主库可以处理读写请求,从库只能处理读请求。

  • mysql-master:主库,支持读写操作。
  • mysql-slave:从库,只支持读操作。

2. 创建 ProxySQL 配置

使用以下的 ProxySQL 配置,可以让 主库支持读写,从库只支持读。

apiVersion: v1
kind: ConfigMap
metadata:
  name: proxysql-config
data:
  proxysql.cnf: |
    # MySQL 读写分离配置
    mysql_servers = (
      # 主库配置,支持读写操作
      { address = "mysql-master-service:3306", port = 3306, hostgroup = 0, max_connections = 100 },
      # 主库同时加入读主机组,使 SELECT 也可以落到主库
      { address = "mysql-master-service:3306", port = 3306, hostgroup = 1, max_connections = 100 },
      # 从库只加入读主机组
      { address = "mysql-slave-service:3306", port = 3306, hostgroup = 1, max_connections = 100 }
    )
 
    # 配置用户,设置默认的主库和从库
    mysql_users = (
      { username = "app_user", password = "<从 Secret 注入的密码>", default_hostgroup = 0, active = 1 }
    )
 
    # SQL 路由规则:
      # SELECT 路由到读主机组(hostgroup = 1),其中包含主库和从库
      mysql_query_rules = (
      { rule_id = 1, active = 1, match_pattern = "^\\s*SELECT", destination_hostgroup = 1, apply = 1 },
      { rule_id = 2, active = 1, match_pattern = "^\\s*(INSERT|UPDATE|DELETE|REPLACE|BEGIN|COMMIT|ROLLBACK)", destination_hostgroup = 0, apply = 1 }
      )

3. 解析配置内容

  • mysql_servers:

    • mysql-master-service:主库服务,配置为 hostgroup = 0,支持读写。
    • mysql-slave-service:从库服务,配置为 hostgroup = 1,只支持读取。
  • mysql_users:示例使用应用账号,默认主机组为 0。不要在 ConfigMap 中保存 root 密码或生产明文凭据;ProxySQL 支持使用 MySQL 认证哈希,具体格式以目标版本文档为准。

  • mysql_query_rules:

    • rule_id = 1:SELECT 查询进入读主机组(hostgroup = 1),由该组中的主库和从库按 ProxySQL 的调度策略分担。
    • rule_id = 2:写操作和事务控制语句进入主库(hostgroup = 0)。复杂 SQL、事务内读写一致性还需要额外的会话规则。

4. 更新 ProxySQL 配置

将这个配置更新到 ProxySQL,通常有两种方式:

  1. 通过 ConfigMap 更新:如果使用 Kubernetes ConfigMap 来管理 ProxySQL 配置,你只需更新 ConfigMap 中的 proxysql.cnf 配置并重新加载 ProxySQL。

  2. 手动更新配置:

    • 使用 mysql 客户端连接到 ProxySQL 的 Admin 端口(默认是 6032)并更新配置:
    mysql -h proxysql-service -P 6032 -u admin -p

    然后执行以下 SQL 来更新配置:

     -- 更新 mysql_servers 配置
     INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (0, 'mysql-master-service', 3306);
     INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, 'mysql-master-service', 3306);
     INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, 'mysql-slave-service', 3306);
     
    -- 更新 mysql_users 配置
     INSERT INTO mysql_users (username, password, default_hostgroup) VALUES ('app_user', '<password-or-hash>', 0);
     
    -- 更新 mysql_query_rules 配置
     INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (1, 1, '^\\s*SELECT', 1, 1);
     INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (2, 1, '^\\s*(INSERT|UPDATE|DELETE|REPLACE|BEGIN|COMMIT|ROLLBACK)', 0, 1);
     
    -- 让配置生效
    LOAD MYSQL SERVERS TO RUNTIME;
    LOAD MYSQL USERS TO RUNTIME;
     LOAD MYSQL QUERY RULES TO RUNTIME;
     SAVE MYSQL SERVERS TO DISK;
     SAVE MYSQL USERS TO DISK;
     SAVE MYSQL QUERY RULES TO DISK;

5. 部署 ProxySQL

确保 ProxySQL 部署的 YAML 文件包含正确的 ConfigMap 配置,并且 ProxySQL 使用此配置文件。以下是 ProxySQL 的部署示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: proxysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: proxysql
  template:
    metadata:
      labels:
        app: proxysql
    spec:
      containers:
      - name: proxysql
        image: proxysql/proxysql:2.6.0
        ports:
          - containerPort: 6033 # MySQL 端口
          - containerPort: 6032 # Admin 端口
        volumeMounts:
          - mountPath: /etc/proxysql.cnf
            subPath: proxysql.cnf
            name: proxysql-config
      volumes:
        - name: proxysql-config
          configMap:
            name: proxysql-config
---
apiVersion: v1
kind: Service
metadata:
  name: proxysql
spec:
  ports:
    - port: 3306
      targetPort: 6033
  selector:
    app: proxysql

6. 验证配置

通过以下命令检查 ProxySQL 的配置是否生效:

# 登录到 ProxySQL Admin 端口
mysql -h proxysql-service -P 6032 -u admin -p
 
# 查看服务器配置
SELECT * FROM mysql_servers;
 
# 查看用户配置
SELECT * FROM mysql_users;
 
# 查看查询路由规则
SELECT * FROM mysql_query_rules;
 
# 如果需要重新加载配置
LOAD MYSQL SERVERS TO RUNTIME;
LOAD MYSQL USERS TO RUNTIME;
LOAD MYSQL QUERY RULES TO RUNTIME;

7. 访问 ProxySQL

你可以通过 ProxySQL 服务 访问数据库:

  • 写操作(INSERT、UPDATE、DELETE)会路由到主库。
  • 读操作(SELECT)会路由到主库和从库。
# 通过 ProxySQL 访问 MySQL 服务
mysql -h proxysql-service -P 3306 -u root -p

总结

  • 通过更新 ProxySQL 配置文件,可以将 写请求固定到主库,并让读主机组中的主库和从库共同承担读请求。
  • 配置 mysql_query_rules 时要设置唯一的匹配顺序和 apply=1;事务内读写一致性、复制延迟和故障切换不能仅靠两条正则规则解决。
  • 使用 Kubernetes ConfigMap 来管理 ProxySQL 配置,确保配置与容器的生命周期一致。