简介:面向Linux/CentOS 7环境的Mycat 1.6.7.1发行版压缩包,为需要搭建分布式数据库中间层的架构师、运维人员及后端开发者提供完整运行环境。Mycat基于Java开发,通过分库分表、读写分离与自动路由解决大数据量下的水平扩展和高可用问题。压缩包共含95个文件,大小16.74MB,其中42个jar包提供核心依赖,16个properties与10个xml文件构成配置体系,另有4个sh脚本、so本地库及txt规则说明,覆盖数据源定义、分片策略、全局序列等关键内容。包内核心配置文件可直接用于初始化数据节点与路由规则,配合druid连接池、zookeeper支持及catlet扩展,便于理解Mycat的运作细节并开展实际调优。已有494人学习浏览,适合希望从零部署Mycat集群、系统掌握配置方法的中高级开发者。
1. 为什么还在用 Mycat 1.6.7.1:一个 Linux 发布包解决分库分表与读写分离
Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz 这个名字乍看像乱码,其实信息量很大:Mycat 1.6.7.1、release 版、2019 年 2 月 13 日构建、面向 Linux 的发行包。它的作用是在应用和多个 MySQL 实例之间加一层路由:把一张大表按规则拆到不同库表,同时把读请求分发到从库,让数据库从单机瓶颈变成可横向扩展的集群。适合两类人:一类是被单库容量、连接数打满困扰,又不想立刻引入复杂数据中台的后端或 DBA;另一类是知道 Mycat 但面对一堆版本号不知道选哪个包的初学者。我见过太多团队在 MySQL 实例已经到位、业务 SQL 却无从下手的阶段卡住,而这个 1.x 后期 release 版恰恰是配置最简单、踩坑资料最全的起点。怎么把它跑起来、怎么分片、哪些坑必须避开,下文全部基于这个具体的 Linux 包展开。
2. 从 tar.gz 到可用中间件:Mycat 1.6.7.1 的目录结构与运行前置条件
2.1 解压后的目录到底怎么组织
不管从哪个渠道拿到 1.x 的发行包,解开后基本是同一套骨架。把 tar.gz 丢到 Linux 服务器上解压,你会看到下面这几个目录,每个目录的职责非常清晰。
| 目录 | 职责 |
|---|---|
| bin | 启停脚本 mycat、wrapper 相关配置 |
| conf | 全部配置文件:schema.xml、server.xml、rule.xml、log4j2.xml |
| lib | 运行依赖的 jar 包,Mycat 本身和 MySQL 驱动都在这里 |
| logs | 运行日志:wrapper.log、mycat.log |
| catlet | 存放自定义全局表逻辑的扩展目录,一般用不到 |
conf 目录是核心。schema.xml 定义逻辑库、逻辑表与后端真实库的映射;server.xml 定义账号、端口和全局序列方式;rule.xml 定义表按什么算法分片;log4j2.xml 控制日志级别。Mycat 对应用暴露的是 MySQL 协议端口,所以应用层感觉自己连了一个超大 MySQL,实际上数据分散在多个后端节点。理解这一层,后面所有配置都不会偏。
2.2 核心依赖:为什么这台 Linux 机器必须先有 Java 环境
Mycat 是 Java 写的,没有 JDK 什么都跑不起来。1.6.7.x 分支建议用 JDK 8,太新的 JDK 反而容易遇到模块化限制或 GC 参数不识别的问题。装好之后第一件事不是解压,而是确认 java 命令可用。
# 先确认有没有 JDK,Mycat 1.x 依赖 Java 运行环境 java -version # 如果提示找不到 java,先装 OpenJDK 8 # Debian/Ubuntu 系 sudo apt-get install -y openjdk-8-jdk # CentOS/RHEL 系 # sudo yum install -y java-1.8.0-openjdk检查完 java 版本后再解压,能省掉后面至少三分之一的启动报错。JDK 装好后不用额外配 JAVA_HOME,mycat 启动脚本会自动找,但如果你服务器上有多个 JDK 版本,建议显式 export JAVA_HOME 指向 JDK 8,避免脚本选错。
2.3 版本选型:1.6.7.1 release 版为什么值得选
文件名里的 20190213150257 是打包时间戳,说明这是自动构建产生的 release 产物,依赖完整、目录规范,不是个人手工打包。1.6.7.1 属于 1.x 后期维护分支,配置模型已经非常成熟,社区里能搜到的问题和解决方案也最多。对存量 MySQL 5.6/5.7 环境,这个版本的兼容性表现比较稳。
需要诚实说明的是:Mycat 1.x 已经不再大规模演进,新功能基本停止。如果你是评估全新项目,要同时考虑长期维护成本;但如果你是被单库连接数和容量卡住、想在几周内落地分库分表的团队,1.6.7.1 是投入产出比很高的选择。它不需要引入额外组件,一个压缩包加一台普通虚拟机就能跑起来。
3. Linux 部署实操:解压、环境检查与最小启动命令
3.1 安装前的环境检查清单
在解压之前,我习惯先花三分钟把环境过一遍。很多启动失败不是 Mycat 本身的问题,而是 JDK 版本不对、端口被占、后端的 MySQL 连不上。
- 确认 JDK 8 已安装,java -version 能正常输出
- 确认 8066(数据端口)和 9066(管理端口)没有被占用
- 确认后端 MySQL 实例可以被当前机器访问,防火墙和账号权限都已放通
- 确认磁盘剩余空间足够,解压后大约需要 200MB 左右
- 确认服务器内存不低于 2GB,Mycat 默认堆内存设置一般不会超过 1GB
# 查看端口占用,8066 和 9066 必须空出来 ss -lntp | grep -E '8066|9066' # 测试后端 MySQL 连通性,IP 换成你自己的实例地址 mysql -h 192.168.1.20 -P 3306 -u mycat -p端口检查这条命令是部署时最容易跳过的一步。很多新手启动成功后用客户端连不上,回头才发现是 8066 被其他服务占用了,Mycat 实际没有监听成功。
3.2 解压与最小目录规划
把压缩包放到 /opt 下,用 tar 解压。这里我不建议解压后直接在里面改配置,而是做一个软链,把实际目录名和版本号解耦,后续升级只需要换软链。
cd /opt tar -xzf Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz # 解压出来的目录名以实际结果为准,这里用软链统一指向 ln -s /opt/Mycat-server-1.6.7.1-release-20190213150257-linux /opt/mycat cd /opt/mycat记一个习惯:后面所有操作都基于 /opt/mycat 这个路径,配置文件的绝对路径就是 /opt/mycat/conf。软链的好处是以后换版本时,新包解压完改一下软链就能回滚,不用动配置。这是我在生产环境里常用的后悔药方案。
3.3 启动命令与 wrapper 参数
Mycat 的启停脚本在 bin 目录下,最常用的命令是 start、console、stop、status。头一次启动我强烈建议用 console 模式,因为日志直接打到终端,报错看得最清楚。
# 前台启动,日志直接刷屏,适合第一次验证配置 ./bin/mycat console # 确认没问题后,Ctrl+C 停掉,再以后台方式启动 ./bin/mycat start # 查看运行状态 ./bin/mycat statusmycat 脚本底层会调用 wrapper,所以 JVM 参数在 conf/wrapper.conf 里配置。默认的 -Xmx 通常够用,但如果你机器内存充足,可以适当调大。修改后必须重启 Mycat 才生效。
# conf/wrapper.conf 中调整堆内存,按机器实际内存修改 wrapper.java.additional.1=-Xmx1024M wrapper.java.additional.2=-Xms512M堆内存不是越大越好。Mycat 的堆主要用来缓存路由结果和部分连接状态,数据不经过它落地,所以不需要像 MySQL 那样给十几 GB。设成 1GB 到 2GB 对绝大多数分片场景都足够了,设太大反而会让 GC 停顿变长。
3.4 启动失败时先看这两个日志
启动失败时,先别急着改配置,按顺序看两个日志。wrapper.log 记录 JVM 和 wrapper 本身的启动情况,mycat.log 记录 Mycat 业务层面的报错。它们分工不同,可以帮你快速缩小问题范围。
# 查看 wrapper 日志,关注 JVM 是否成功拉起 tail -n 100 /opt/mycat/logs/wrapper.log # 查看 Mycat 业务日志,关注配置加载和数据源连接报错 tail -n 100 /opt/mycat/logs/mycat.log如果 wrapper.log 里什么都没有,说明脚本还没走到 JVM 启动那一步,大概率是 Java 环境问题。如果 wrapper.log 正常但 mycat.log 报错,再看具体异常类型,比如数据源连不上、配置文件解析失败。这两个日志是排查一切启动问题的入口,把它们的位置记在心里,后面的坑都靠它们定位。
4. 配置分片表:schema.xml、rule.xml 与 server.xml 的落地写法
4.1 schema.xml 定义逻辑库与数据节点映射
schema.xml 是 Mycat 最核心的配置,它决定应用看到的逻辑表长什么样,以及数据实际落在哪些后端库。下面是一个最常见的两节点取模分片示例,订单表按 id 取模拆到两个库。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <!-- 逻辑库 demo,应用连接时指定的库名 --> <schema name="demo" checkSQLschema="false" sqlMaxLimit="100"> <!-- order 表按 id 分片到 dn1、dn2 两个数据节点 --> <table name="order" dataNode="dn1,dn2" rule="mod-id" /> </schema> <!-- 数据节点:每个节点对应一个真实物理库 --> <dataNode name="dn1" dataHost="host1" database="db_orders_0" /> <dataNode name="dn2" dataHost="host1" database="db_orders_1" /> <!-- 数据主机:一组主从 MySQL 的入口配置 --> <dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"> <heartbeat>select user()</heartbeat> <!-- 写库 --> <writeHost host="mysql-01" url="192.168.1.20:3306" user="mycat" password="mycat123"> <!-- 从库,balance="1" 时负责读请求 --> <readHost host="mysql-01-r" url="192.168.1.21:3306" user="mycat" password="mycat123" weight="1" /> </writeHost> </dataHost> </mycat:schema>schema 标签里的 sqlMaxLimit 是防手滑的保险,避免不带 limit 的查询一次拉太多数据。dataNode 里的 database 对应后端 MySQL 的真实库名,这些库必须提前建好,Mycat 不会自动建库。dataHost 里的 balance 和 writeType 决定读写分离策略,balance="1" 表示读请求分到 readHost,writeType="0" 表示只往第一个 writeHost 写入。
后端的 db_orders_0 和 db_orders_1 需要你在 MySQL 里手动创建,并且表结构要一致。Mycat 只做路由,不负责建表,这个步骤漏掉的话,首次写入会直接报错。
4.2 rule.xml 选分片字段与算法
rule.xml 决定数据按什么规则分布。最常用的取模算法是 mod-long,配置简单,数据分布均匀,适合订单、用户这类按 ID 访问频繁的业务。
<tableRule name="mod-id"> <rule> <columns>id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!-- count 必须和 schema.xml 中该表的数据节点数量一致 --> <property name="count">2</property> </function>columns 是分片字段,这个字段必须出现在业务 SQL 的 where 条件里,否则 Mycat 不知道去哪找数据,只能广播到所有节点再合并结果。function 的 count 是取模的模数,必须和 schema.xml 里 dataNode 的数量一致,比如两个节点就填 2。填错不会报错,但数据会按错误规则路由,查出来就是缺数据。
除了 mod-long,Mycat 还内置了范围分片、枚举分片、一致性哈希等算法。取模适合大部分场景,一致性哈希更适合数据量增长不确定的业务。初学者先别贪多,把 mod-long 跑通,理解路由逻辑后再换算法。
4.3 server.xml 的账号、连接数与序列配置
server.xml 管对外暴露的端口和账号。数据端口 8066 给业务系统连,管理端口 9066 给运维执行管理命令用。默认配置里有一个 root 账号,生产环境必须改掉。
<user name="dba"> <property name="password">dba123</property> <!-- 允许访问的逻辑库,逗号分隔 --> <property name="schemas">demo</property> <!-- 是否只读,false 表示可写 --> <property name="readOnly">false</property> </user>server.xml 里还有一个容易被忽略的配置是全局序列。分库分表后自增主键在各节点会重复,所以主键必须由 Mycat 统一生成。1.x 里通过 sequenceHandlerType 指定序列实现方式:0 是本地文件,1 是数据库,2 是本地时间戳,3 是分布式。并发量不大的项目用 2 最省事,并发高的建议用 1 或 3。
序列配置是分片表最容易翻车的点。很多团队上线后才发现主键冲突,就是因为建表时用了 MySQL 自增,而没有配置 Mycat 的全局序列。建议在建表 DDL 里就把主键设计成 bigint,配合序列生成器使用。
4.4 用真实 SQL 验证分片是否生效
配置全部改完后,不要急着接业务,先用几条 SQL 验证路由结果。Mycat 支持在客户端里直接执行 explain 语句,可以看到一条 SQL 被路由到了哪些数据节点。
-- 连接 Mycat 数据端口 mysql -h 127.0.0.1 -P 8066 -u dba -pdba123 demo -- 查看路由计划:id=1 会落到哪个节点 explain select * from `order` where id = 1; -- 插入两条测试数据,id 分别取奇数和偶数 insert into `order` (id, order_no, amount) values (1, 'NO001', 100.00); insert into `order` (id, order_no, amount) values (2, 'NO002', 200.00); -- 分别查两个后端库,确认数据按奇偶分布 select * from db_orders_0.`order`; select * from db_orders_1.`order`;explain 的结果会显示 dataNode 列表。id=1 取模 2 得 1,应该路由到 dn2;id=2 取模 2 得 0,路由到 dn1。如果 explain 显示 ALL 节点,说明 SQL 没带分片字段,走了全路由。这个验证动作虽然简单,但能把配置错误在接业务前暴露出来,避免上线后数据乱掉。
5. Mycat 1.6.7.1 部署避坑:5 个启动与路由问题的排查记录
5.1 坑 1:UnsupportedClassVersionError,JVM 版本不匹配
现象:./bin/mycat start 后进程秒退,wrapper.log 里出现 java.lang.UnsupportedClassVersionError。
原因:Mycat 1.x 编译目标是 JDK 7/8,你用 JDK 11 或更高版本运行时,类文件版本号对不上,JVM 拒绝加载。
解决:卸载高版本 JDK,安装 OpenJDK 8,重新执行 java -version 确认版本,再启动 Mycat。如果你服务器上同时装了多个 JDK,可以在启动前执行 export JAVA_HOME 指向 JDK 8 的路径,避免脚本选错。
5.2 坑 2:9066/8066 端口连接被拒,但 Mycat 进程是活的
现象:./bin/mycat status 显示 RUNNING,但用 mysql 客户端连 8066 报 Connection refused。
原因:最常见的是 Mycat 只监听了 127.0.0.1,或者服务器防火墙挡掉了端口。还有可能是你启动了两次,第二个实例没起来但第一个占着端口。
解决:先用 ss -lntp | grep 8066 看监听地址。如果只监听本地回环,检查 server.xml 里的 bind 配置,改成 0.0.0.0 并重启。同时确认防火墙放行了 8066 和 9066。很多团队在本地虚拟机怎么都连不上,最后发现是云安全组没放行。
5.3 坑 3:不带分片字段的查询触发全路由,性能雪崩
现象:某条查询在分片前只要几十毫秒,分片后变成几百毫秒甚至超时,后端所有 MySQL CPU 同时飙高。
原因:SQL 的 where 条件里没有分片字段,Mycat 无法确定数据在哪个节点,只能把请求广播到所有数据节点,再合并结果。全路由次数一多,整个集群被拖垮。
解决:业务 SQL 必须强制带上分片字段。比如 order 表按 id 分片,查询条件里除了 user_id 还要带 id。如果表确实无法通过分片字段查询,考虑建一张全局表或者用 catlet 做跨节点聚合。用 explain 检查每条核心 SQL 的路由结果,确认没有 ALL 节点出现。
5.4 坑 4:全局序列出现重复主键,写入直接冲突
现象:并发写入时,应用报主键重复错误,但检查每个后端库的自增计数都没有问题。
原因:server.xml 里 sequenceHandlerType 配置不对,或者根本没配置,Mycat 各节点各自为政,生成了相同的主键。
解决:确认 server.xml 里配置了统一的全局序列方式,并在 schema.xml 对应表的 primaryKey 属性中声明主键字段。如果用的是数据库序列模式,还需要在后端 MySQL 里初始化序列表和存储过程。最简单稳妥的做法是先用本地时间戳模式(sequenceHandlerType=2)跑通,并发量上来后再切数据库序列。
5.5 坑 5:dataHost 的 maxCon 太小,压测直接连接失败
现象:压测刚开始几十个并发就报 Can't get connection,后端 MySQL 连接数远没到上限。
原因:Mycat 为每个 dataHost 维护了一组后端连接池,maxCon 设置太小,前端请求一多就把连接池占满了。默认配置在某些低配机器上不一定够用,需要按实际并发调整。
解决:把 dataHost 的 maxCon 从默认值调大,比如 1000,minCon 保持 10 左右即可。同时关注 server.xml 里前端连接的 processor 数量,它影响 Mycat 处理并发请求的线程数。调完重启,再看压测表现。这里的核心思路是:前端连接数和后端连接池是两个维度,要一起匹配。
6. 进阶验证:用 EXPLAIN 确认分片路由,并定位慢 SQL 瓶颈
分片跑通之后,运维视角要立刻切换到两件事:路由对不对、慢 SQL 在哪。Mycat 的 explain 不仅能在开发环境验证配置,上了生产同样可以用来检查异常流量。重点看两种结果:一个是 SQL 路由到了单个节点还是多个节点,另一个是有没有出现全路由。全路由本身不可怕,可怕的是高频查询里混着全路由却没人发现。
定位慢 SQL 时,管理端口 9066 比数据端口更有用。连接后可以执行 show @@slow 查看慢查询列表,也可以看 show @@datasource 确认后端连接池的健康状态。具体命令在不同小版本上略有差异,但 1.6.7.x 基本都支持。关键是把慢 SQL 的路由结果和耗时数据结合起来看:如果某条 SQL 只路由到一个节点却还是很慢,问题大概率在后端 MySQL 的索引或锁;如果路由到多个节点,则要考虑是否能把分片字段补进查询条件。
-- 连接管理端口 mysql -h 127.0.0.1 -P 9066 -u dba -pdba123 -- 查看最近慢 SQL,按耗时排序 show @@slow where rows = 20; -- 查看后端数据源状态,确认连接池没有被占满 show @@datasource;调优时我习惯先看慢 SQL 文本,再决定动哪里。不要在没确认路由结果的情况下盲目加索引,那是最典型的玄学调优:一顿操作猛如虎,回头一看全路由才是根因。正确顺序是先改 SQL 带全分片字段,再确认 explain 结果收窄到单节点,最后才检查后端索引。
Mycat 1.6.7.1 这套方案帮我处理过不少线上连接数打满的紧急情况。现在的习惯是:所有分片表的核心查询全部用 explain 过一遍,把全路由 SQL 记到文档里,每次发版前复查一次。这个习惯救过我很多次,希望也能帮到你。
本文还有配套的精品资源,点击获取