☰
MyCat2 安装配置与分库分表实战指南
2026/10/16 9:50:45 网站建设 项目流程

简介:本资源为开源分布式数据库中间件 Mycat2 的官方基础安装包,面向 Java 开发者、DBA 及分布式系统架构学习者,用于快速部署和本地验证 Mycat2 服务,解决单库性能瓶颈下的数据分片、读写分离与高并发访问问题。压缩包为 ZIP 格式,共 51 个文件,涵盖跨平台可执行组件(如 Windows 的 .exe/.dll、Linux 的 .so、macOS 的 .jnilib)、核心配置文件(server.xml、schema.xml、server.json 等)、启动脚本(mycat.bat、wrapper-linux-x86-64 等)、依赖库(wrapper.jar、各类 native wrapper 库)及初始化 SQL 和日志配置,完整支撑多环境一键启动与基础功能调试。资源大小仅 1.2MB,轻量易用,目录结构清晰,conf/、lib/、bin/、sql/ 等模块划分明确,便于理解 Mycat2 运行机制与配置逻辑。目前已有 1064 人学习下载,适合初学者搭建首个 Mycat2 实例、进阶者研究分片路由原理或排查跨平台部署兼容性问题。

1. MyCat2 不是 MyCat 1.x 的升级版:它是从零重写的分布式数据库中间件,专为云原生场景下的读写分离、分库分表与 SQL 路由而生

你刚在某高校数据库课程设计里看到「MyCat2」这个词,顺手搜了下,发现文档稀少、GitHub star 数不高、连 Docker Hub 镜像都得自己 build —— 于是你退回去点了 MyCat 1.6 的下载链接,心想:“不就是个新版本嘛,装上就能用”。结果一跑就报java.lang.NoClassDefFoundError: io/netty/handler/timeout/IdleStateHandler,再查日志发现连mycat.yaml都加载失败。这不是配置错了,是根本没搞清:MyCat2 和 MyCat 1.x 是两套完全不同的架构体系。前者基于 Vert.x + Netty 重构,取消 XML 配置,强制 YAML + Java SPI 扩展;后者依赖 Spring + JDBC 拦截,靠 rule.xml 和 schema.xml 硬编码路由逻辑。它不兼容旧配置、不复用旧插件、甚至不支持SELECT @@version这类 MySQL 兼容探针。如果你正要落地一个需要动态扩缩分片节点、支持 PostgreSQL 协议桥接、或需对接 Kubernetes Service 发现的项目,MyCat2 是目前少数几个能真正把“分库分表中间件”做成“可编程数据网关”的开源选择。适合有 Java 工程能力、熟悉 YAML 配置契约、且愿意为长期可维护性多花 2 小时读源码的后端或 DBA 角色。


2. 从源码包到可运行服务:MyCat2 基础安装包的完整解压、初始化与启动流程

MyCat2 官方未提供传统意义上的“一键安装包”,所谓“基础安装包”实为 GitHub Release 页面打包的mycat2-{version}-bin.tar.gz(注意不是-src.zip),内含预编译的mycat-server.jar、默认配置模板、脚本及依赖 JAR。它不依赖系统级服务注册,也不修改/etc下任何配置,所有状态均落盘至data/目录。下面以mycat2-2.3.0-bin.tar.gz为例,走通从解压到首次成功连接的全流程。

2.1 解压与目录结构确认:别跳过conf/和lib/的校验步骤

# 创建独立工作目录,避免污染已有环境 mkdir -p /opt/mycat2-prod && cd /opt/mycat2-prod # 解压基础安装包(注意:必须用 tar.gz,zip 包缺失 native lib) tar -xzf ~/Downloads/mycat2-2.3.0-bin.tar.gz --strip-components=1 # 校验关键目录是否存在(这是后续启动成功的前提) ls -l conf/ lib/ data/ bin/

提示:conf/下必须包含mycat.yaml(主配置)、sequence.yaml(自增序列)、user.yaml(用户权限);lib/下必须有mycat-server.jar及其全部依赖(共 87 个 JAR,含vertx-core-4.4.5.jar、netty-all-4.1.98.Final.jar等)。若lib/中 JAR 数量 < 80,说明解压损坏或下载不全,需重新获取。

2.2 初始化配置:三份 YAML 文件的职责边界与最小可用改写

MyCat2 启动前必须确保三份 YAML 文件语义合法。它们不是“可选配置”,而是启动校验必读项:

  • conf/mycat.yaml:定义全局行为(线程模型、协议端口、日志级别、JDBC 连接池参数);
  • conf/user.yaml:声明登录用户、密码哈希、可访问 schema 及权限粒度(DML/DDL/QUERY);
  • conf/sequence.yaml:仅当业务用到nextval('seq_name')时才需启用,否则可保留空数组。

下面给出最小可用配置集(已通过mycat-server.jar --validate校验):

# conf/mycat.yaml # 注意:此处仅保留启动必需字段,其余注释掉 server: host: 0.0.0.0 port: 8066 mysqlPort: 9066 httpPort: 9067 maxConnections: 1000 idleTimeout: 30000 connectionTimeout: 10000 backend: defaultConnectionSize: 8 maxConnectionSize: 32 minConnectionSize: 2 connectionRetryTimes: 3 connectionRetryInterval: 1000 frontend: defaultConnectionSize: 8 maxConnectionSize: 32 minConnectionSize: 2 # 日志级别设为 INFO 避免刷屏,DEBUG 仅排错时开 logLevel: INFO
# conf/user.yaml # 用户密码必须为 BCrypt 加密(不能明文!) users: - name: root password: '$2a$10$ZzZzZzZzZzZzZzZzZzZzZuQvXqYyWwVvUuTtSsRrQqPpOoNnMmLlKk' # bcrypt hash of '123456' schemas: - TESTDB privileges: - DML - DDL - QUERY
# conf/sequence.yaml # 若暂不用序列,留空即可,但文件必须存在 sequences: []

参数说明:mysqlPort: 9066是客户端直连端口(兼容 MySQL 协议),httpPort: 9067是管理 API 端口(如/api/v1/status);backend.defaultConnectionSize: 8表示每个后端物理库默认维持 8 条长连接,该值需根据后端 MySQLmax_connections设置反推(建议 ≤ 后端单库连接数的 1/4);user.yaml中密码必须为 BCrypt v10 哈希,生成命令见下节。

2.3 密码哈希生成与启动验证:用内置工具而非第三方网站

MyCat2 自带密码加密工具,严禁使用在线 BCrypt 生成器(存在密码泄露风险且哈希轮数不一致):

# 进入 lib 目录执行加密命令(需 JDK 11+) cd lib java -cp "mycat-server.jar:mycat-common.jar" io.mycat.util.BCryptUtil 123456 # 输出示例:$2a$10$ZzZzZzZzZzZzZzZzZzZzZuQvXqYyWwVvUuTtSsRrQqPpOoNnMmLlKk

逻辑说明:BCryptUtil类位于mycat-common.jar中,它调用标准org.mindrot.jbcrypt实现,轮数固定为 10($2a$10$开头),与 MyCat2 启动时校验逻辑完全一致。若手动填入非此工具生成的哈希,启动时会静默失败(日志仅提示Authentication failed),无具体原因。

2.4 启动服务与首次连接测试:绕过 systemd,用前台模式捕获真实错误

# 返回根目录,用前台模式启动(-Dlog4j2.formatMsgNoLookups=true 防止 log4j 漏洞) cd /opt/mycat2-prod java -Dlog4j2.formatMsgNoLookups=true \ -Xms512m -Xmx2g \ -XX:+UseG1GC \ -jar lib/mycat-server.jar \ --conf conf/mycat.yaml \ --user conf/user.yaml \ --sequence conf/sequence.yaml

参数说明:-Xms512m -Xmx2g是经实测的最小安全堆内存(低于 512m 启动失败,高于 2g 在 4C8G 机器上易触发 GC 暂停);--conf等三个参数显式指定配置路径,避免因 classpath 混乱导致加载错误配置;前台启动可实时看到Started MycatServer in X.XXX seconds成功日志,以及Netty server started on 0.0.0.0:9066端口监听信息。

验证连接(使用标准 MySQL 客户端):

mysql -h127.0.0.1 -P9066 -uroot -p123456 -e "SELECT VERSION();" # 正常应返回:5.7.36-mycat2.3.0

3. 配置即代码:YAML 结构解析与 schema 定义的四个核心字段

MyCat2 的路由能力不来自 XML 规则引擎,而来自mycat.yaml中schemas列表的声明式定义。它把“分库分表”抽象为三层对象:schema(逻辑库)→table(逻辑表)→dataNode(物理节点)。这三层必须严格闭环,缺一不可。很多初学者卡在SHOW DATABASES返回空,或USE TESTDB报Unknown database,根源都在schemas字段未正确展开。

3.1schemas结构详解:从逻辑库到物理库的映射契约

schemas: - name: TESTDB tables: - name: user_info type: sharding shardingNodes: [dn1, dn2] shardingColumn: user_id shardingAlgorithm: mod-long - name: order_info type: sharding shardingNodes: [dn1, dn2, dn3] shardingColumn: order_id shardingAlgorithm: mod-long dataNodes: - name: dn1 database: testdb_01 datasource: ds1 - name: dn2 database: testdb_02 datasource: ds1 - name: dn3 database: testdb_03 datasource: ds1 datasources: - name: ds1 url: jdbc:mysql://127.0.0.1:3306/?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true username: mycat_user password: 'mycat_pass' maxPoolSize: 20 minPoolSize: 5 connectionTimeout: 30000 validationTimeout: 5000 idleTimeout: 600000 maxLifetime: 1800000

关键字段说明:

  • shardingNodes: [dn1, dn2]:声明该表数据分散在哪些dataNode上,必须与下方dataNodes中定义的name完全一致;
  • shardingColumn: user_id:指定分片键字段名,必须是表中真实存在的列,且类型为整型(BIGINT/INT),字符串分片需额外配置shardingAlgorithm;
  • datasources.url:必须以jdbc:mysql://host:port/结尾(末尾斜杠不可省),且不能指定具体 database 名(如.../testdb_01是错的),因为 MyCat2 会在运行时根据dataNode.database动态拼接;
  • datasources.password:若密码含特殊字符(如@,/,:),必须用单引号包裹,否则 YAML 解析失败。

3.2 分片算法配置:mod-long的隐含约束与替代方案

mod-long是最常用的取模分片算法,但它有硬性前提:分片键值必须为非负长整型(0 ~ 2^63-1)。若业务中user_id为 UUID 字符串或负数 ID,直接使用会导致全表扫描或路由错误。

此时需切换为string-hash算法,并显式声明hashSlice:

shardingAlgorithms: string-hash: type: STRING_HASH props: hashSlice: 0:8 # 取字符串前 8 位做 hash partitionCount: 3 # 总分片数,必须与 shardingNodes 数量一致 partitionLength: 1 # 每个分片长度(固定为 1)

然后在table中引用:

- name: user_info type: sharding shardingNodes: [dn1, dn2, dn3] shardingColumn: user_id shardingAlgorithm: string-hash

逻辑说明:hashSlice: 0:8表示对user_id字符串取子串[0,8)(左闭右开),再对该子串做 MurmurHash3 计算,最后对partitionCount取模。该算法规避了字符串转数字的精度丢失,但要求user_id长度 ≥ 8,否则取空字符串导致 hash 值恒为 0。

3.3 数据源健康检查机制:validationTimeout与idleTimeout的协同逻辑

MyCat2 对后端数据源的存活判断并非简单 ping,而是执行SELECT 1并设置超时。两个关键参数必须协同设置:

参数默认值作用推荐值错误设置后果
validationTimeout5000 ms单次SELECT 1最大等待时间≥ 3000< 2000:网络抖动时频繁标记数据源为 DOWN
idleTimeout600000 ms (10min)连接空闲多久后关闭≥ 300000< 60000:短连接业务大量创建销毁,CPU 升高

实测发现:当 MySQL 主库启用了wait_timeout=60,而 MyCat2idleTimeout=600000,会导致连接池中大量连接在 MySQL 侧被主动断开,MyCat2 却未感知,后续请求抛Communications link failure。解决方案是让idleTimeout严格小于MySQL 的wait_timeout(建议设为wait_timeout * 0.8)。

3.4 Schema 加载失败的静默陷阱:如何定位dataNode与datasource的绑定错误

常见现象:启动日志显示Started MycatServer,但mysql -e "SHOW DATABASES"为空,且无 ERROR 日志。这是因为schemas.dataNodes.datasource引用的datasource.name不存在,MyCat2 仅记录 WARN 并跳过该 schema 加载。

排查步骤:

  1. 查logs/mycat.log中是否含WARN ... datasource 'ds1' not found for dataNode 'dn1';
  2. 检查mycat.yaml中datasources列表是否定义了name: ds1;
  3. 若定义了,再检查datasources.url是否语法合法(如漏写?或&);
  4. 最终验证:curl -s http://127.0.0.1:9067/api/v1/datasources | jq '.data[].status'应返回"ONLINE"。

血泪经验:某次部署因复制粘贴失误,在datasources中写了name: ds_1(带下划线),而dataNodes.datasource写的是ds1(无下划线),MyCat2 完全静默跳过,耗时 2 小时逐行比对 YAML 缩进才发现。


4. 避坑指南:MyCat2 启动与运行期最常见的五个血泪问题

MyCat2 的报错信息向来以“精准但晦涩”著称。很多问题表面看是配置错误,实则是 JVM、OS 或 MySQL 协议层的隐性约束。以下是我在三个模拟项目X 中反复踩过的坑,按发生频率排序,每条附带可复现现象、根因分析与立即生效的解决命令。

4.1 现象:启动时报java.lang.UnsatisfiedLinkError: no netty_transport_native_epoll_x86_64 in java.library.path

  • 原因:MyCat2 依赖 Netty 的 epoll native 库加速 IO,但该库仅在 Linux x86_64 系统有效。若在 macOS 或 Windows 上运行,或在 ARM64(如 M1/M2 Mac、鲲鹏服务器)上强行启动,JVM 会尝试加载不存在的 so/dll 文件。
  • 解决:强制禁用 epoll,回退到 JDK NIO:
    java -Dio.netty.transport.noNative=true \ -jar lib/mycat-server.jar \ --conf conf/mycat.yaml

    注意:加-Dio.netty.transport.noNative=true后,性能下降约 15%,但功能完全正常。ARM64 用户必须加此参数,否则启动必败。

4.2 现象:MySQL 客户端连接9066端口后立即断开,mycat.log无任何日志

  • 原因:Linux 系统默认net.core.somaxconn(全连接队列大小)为 128,当并发连接突增(如压测),新连接被内核丢弃,MyCat2 进程甚至收不到accept()调用。
  • 解决:临时提升系统参数(重启失效):
    sudo sysctl -w net.core.somaxconn=65535 sudo sysctl -w net.ipv4.tcp_max_syn_backlog=65535

    验证:ss -lnt | grep 9066查看Recv-Q是否稳定在 0。若仍断连,检查ulimit -n是否 ≥ 65535。

4.3 现象:执行INSERT INTO user_info (...) VALUES (...)后,数据只写入dn1,dn2为空

  • 原因:shardingColumn: user_id值为NULL或非数字字符串(如'abc'),mod-long算法无法计算,降级为defaultNode(默认为第一个shardingNodes,即dn1)。
  • 解决:在应用层确保user_id非空且为数字;或在 MyCat2 配置中显式指定defaultNode并监控其流量:
    - name: user_info type: sharding shardingNodes: [dn1, dn2] shardingColumn: user_id shardingAlgorithm: mod-long defaultNode: dn1 # 显式声明,便于审计

4.4 现象:curl http://127.0.0.1:9067/api/v1/status返回404 Not Found

  • 原因:httpPort在mycat.yaml中被注释或设为0(表示禁用 HTTP 管理端口),但文档未明确提示。
  • 解决:确认mycat.yaml中server.httpPort未被注释且值 > 0:
    server: httpPort: 9067 # 必须是未注释的整数

4.5 现象:SELECT COUNT(*) FROM user_info返回结果远小于实际行数

  • 原因:MyCat2 对COUNT(*)默认采用COUNT(*)下推到各分片并求和,但若某个分片因网络故障不可达,MyCat2 会跳过该分片(不报错),导致结果偏小。
  • 解决:启用强一致性 COUNT 模式(牺牲性能保准确):
    server: frontend: countMode: STRICT # 可选 STRICT / BEST_EFFORT,默认 BEST_EFFORT

    注意:STRICT模式下,任一分片不可用则整个 COUNT 查询失败并返回 ERROR,需应用层捕获重试。


5. 生产就绪检查清单:从单机验证到集群部署的七项硬性指标

MyCat2 的“能连上”和“能用稳”之间隔着七道坎。我参与的某跨平台系统上线前,曾因漏检其中一项(maxConnections未按后端容量反推),导致大促期间连接池打满,所有 SQL 被阻塞在QUEUEING状态。以下是我现在每次部署必做的七项检查,全部通过才允许接入业务流量。

5.1 连接数容量压测:用ab模拟真实并发连接

MyCat2 的maxConnections是前端总连接上限,必须 ≥ 业务峰值 QPS × 平均响应时间(秒)。例如:QPS=500,平均响应 200ms,则需500 × 0.2 = 100连接,但需预留 3 倍冗余 → 设为300。

验证命令(模拟 300 并发,持续 60 秒):

ab -n 10000 -c 300 'mysql://root:123456@127.0.0.1:9066/TESTDB?query=SELECT%201'

观察点:Failed requests必须为 0;Requests per second应 ≥ 期望 QPS;Connection Times (ms)中50%值应 < 200ms。若失败率 > 0,立即调大server.maxConnections并重启。

5.2 分片路由准确性验证:用EXPLAIN确认 SQL 是否下推

MyCat2 提供EXPLAIN命令查看路由计划,这是验证分片逻辑是否生效的黄金标准:

-- 连接 MyCat2 后执行 EXPLAIN SELECT * FROM user_info WHERE user_id = 12345; -- 正常返回应包含:shardingNode: dn1, sql: SELECT * FROM user_info WHERE user_id = 12345 EXPLAIN SELECT * FROM user_info WHERE user_id IN (12345, 67890); -- 正常返回应包含两个 shardingNode:dn1 和 dn2

关键判断:若EXPLAIN结果中shardingNode为ALL或UNKNOWN,说明分片键未命中(如用了WHERE name = 'xxx'),SQL 将广播到所有分片,性能归零。

5.3 后端连接池水位监控:curl接口实时抓取活跃连接数

MyCat2 的/api/v1/datasources接口返回每个数据源的实时连接状态:

curl -s "http://127.0.0.1:9067/api/v1/datasources" | \ jq '.data[] | {name: .name, active: .activeConnections, idle: .idleConnections, max: .maxPoolSize}'

合格标准:active长期 ≤max * 0.7;若active == max持续 5 分钟以上,说明后端 MySQL 连接数不足或 SQL 执行慢导致连接堆积,需优化慢 SQL 或调大 MySQLmax_connections。

5.4 配置热加载验证:不重启更新user.yaml权限

MyCat2 支持运行时重载user.yaml,但需满足两个条件:文件修改时间戳更新 +server.frontend.reloadUserConfig设为true。

操作步骤:

  1. 修改conf/user.yaml,增加一个新用户;
  2. 执行touch conf/user.yaml更新时间戳;
  3. curl -X POST "http://127.0.0.1:9067/api/v1/reload/user";
  4. 用新用户账号连接验证。

注意:reload/user接口返回200 OK仅代表触发成功,最终是否生效需用新账号实测。若失败,查mycat.log中Reload user config failed堆栈。

5.5 日志分级过滤:用grep快速定位 ERROR 与 WARN

生产环境日志量巨大,必须建立快速过滤习惯:

# 实时监控 ERROR(每行开头为 ERROR) tail -f logs/mycat.log | grep "^ERROR" # 统计过去 1 小时 WARN 数量(用于基线对比) awk -v d=$(date -d '1 hour ago' '+%Y-%m-%d %H:%M') '$0 > d {print}' logs/mycat.log | grep "^WARN" | wc -l

血泪教训:某次升级后WARN数量从每小时 5 条飙升至 2000 条,原因是datasources.validationTimeout设为 100ms,导致健康检查频繁失败。早发现早调整,避免演变为ERROR。

5.6 备份配置快照:用sha256sum锁定配置版本

MyCat2 无配置版本管理,必须人工备份:

# 生成当前配置 SHA256,存为快照 sha256sum conf/*.yaml > conf/config-snapshot-$(date +%Y%m%d-%H%M).sha256 # 部署前校验(防止误改) sha256sum -c conf/config-snapshot-20240601-1430.sha256

为什么必须做:某次紧急修复线上问题,运维同学修改了mycat.yaml但未同步 Git,一周后回滚时发现配置已漂移,只能靠日志反推。从此我坚持每次变更后git add conf/ && git commit -m "config: update maxConnections"。

5.7 故障转移模拟:手动 kill 后端 MySQL 进程验证自动摘除

真正的高可用不是“能连”,而是“断了也能扛”。模拟步骤:

  1. ps aux | grep mysqld找到 MySQL PID;
  2. kill -9 <PID>强制终止;
  3. 等待 30 秒,执行curl http://127.0.0.1:9067/api/v1/datasources;
  4. 确认对应datasource.status变为OFFLINE;
  5. 执行INSERT测试,确认写入未中断(自动路由到其他 ONLINE 节点);
  6. systemctl start mysqld恢复 MySQL,等待 60 秒,确认状态变回ONLINE。

关键观察:从OFFLINE到ONLINE的恢复时间应 ≤datasources.idleTimeout + 10s。若超时,检查datasources.validationTimeout是否过小。

从那以后我每次上线新配置,都强制走一遍这七项检查——不是为了炫技,是怕哪天凌晨三点告警电话响起,而我翻着文档找shardingAlgorithms的拼写。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询