资讯动态

MyCat 1.6.7.6_BYMONTH按月分片实战:从配置到性能调优

发布时间:2026/9/7 3:47:06 来源:尧图企业网站定制
简介面向MySQL中间件运维与开发人员的MyCat 1.6.7.6定制资源包针对官方版按月分表配置复杂的问题直接提供subTables的BYMONTH分表支持。配置形式为tableName_$202101-?表示从202101月开始自动按月分表?代表当前月份只需设置起始日期配合动态建表可让子表自动增长适合周期性数据隔离与归档场景。包内共111个文件压缩后24.86MB包含53个jar依赖、18个properties配置、14个txt说明、10个xml映射与schema配置、4个shell脚本及2个SQL建表脚本等结构清晰便于直接部署或参照改造。压缩包保留了MyCat官方版server.xml、schema.xml等核心配置备份以及guava、druid、mongo驱动等运行组件可支持快速搭建按月分表环境。目前已有371人学习下载适用于有一定MyCat基础、希望快速落地按月分表方案的中高级运维或开发工程师。1. 从 ZIP 包说起为什么我还在用 MyCat 1.6.7.6拿到mycat-1.6.7.6_BYMONTH.zip这个包的时候我的第一反应是这年头还在碰 MyCat 的人要么是维护老系统要么是真正被业务逼得没办法了。说实话从 1.6 到 1.7 再到 2.0MyCat 的版本迭代并不算激进但 1.6.7.6 这个维护版本在稳定性上确实可圈可点尤其是配合 BYMONTH 这种按月分片的规则在日志类、订单类、流水类数据的处理上非常顺手。很多人一上来就问为什么不直接用 ShardingSphere或者干脆上 TiDB我的回答通常是看场景。MyCat 作为代理层中间件最大的优势是对业务代码几乎零侵入——你只需要改 JDBC 连接串把原来的 MySQL 地址换成 MyCat 地址剩下的分片逻辑全部由 MyCat 在中间层消化。对于那些已经上线多年、代码里塞满了复杂 SQL 的老项目来说这几乎是唯一能在不重构代码的前提下完成水平扩展的出路。而 BYMONTH 这个后缀说白了就是“按月分片”的定制化打包。它不是我随便起的名字而是针对特定业务场景做过的分片规则定制。比如我们之前处理的短信发送记录表一个月轻松上千万条如果都在一张表里索引再优化也扛不住。按月分表之后每个月一张表查询时 MyCat 自动路由到对应月份的表性能提升立竿见影。这个 ZIP 包里包含的是完整的 MyCat 服务端解压之后配置好分片规则就能跑。它对应的是 MyCat 1.6 系列中比较稳定的一个基线版本修掉了一批 1.6.5、1.6.6 时期遗留的连接池和路由问题。如果你正在维护一个数据量持续增长、又暂时没有重构预算的系统这套方案绝对值得花半小时好好看看。2. BYMONTH 分片规则原理与适用场景2.1 按月分片的“为什么”和“怎么做”按月分片本质上是“分区键 分片算法”的组合。MyCat 的分片规则配置在rule.xml里而 BYMONTH 对应的就是一个自定义的分片算法类。它的核心逻辑是根据日期字段的月份值计算出这条数据应该落在哪张表上。举个例子订单表t_order要按月份分表3 月的写t_order_2024034 月的写t_order_202404。在 MyCat 里你需要做两件事一是定义一个叫sharding-by-month的表规则二是把逻辑表t_order映射到这个规则上。规则的核心就是那个classio.mycat.route.function.PartitionByMonth的类它会解析你传入的日期参数然后通过月份换算得出目标节点的索引。我之前被问得最多的一个问题是这个 PartitionByMonth 具体是怎么算的其实就是把日期字符串转成 Calendar 对象取MONTH字段然后根据你配置的边界月份做差值。比如你配置beginDate2024-01-01那么 2024 年 3 月的数据月份差就是 2数据就落到下标为 2 的分片节点上。这个理解起来不复杂但配置的时候有个关键点容易被忽略分片节点的数量必须能覆盖到你可能出现的最大月份跨度。否则超出的部分直接报错数据写不进去。2.2 什么样的业务适合 BYMONTH 分片不是所有表都适合按月分片。按照我自己的选型经验至少要满足三个条件才算合格数据有明显的时间属性而且业务查询大多带上时间范围条件比如“查最近 30 天”“查某个月的对账单”。如果没有这个前提MyCat 无法根据日期字段精确定位到某个分片只能走全分片广播性能反而更差。数据有冷热分层的特征。比如日志数据写入后头几天访问频繁一个月后基本没人查。这种数据按月分片之后甚至可以直接把上月的历史分片做归档或者降级存储。单表数据量增长快但单条数据本身不大。比如交易流水、操作日志、消息记录。如果单条数据动辄几百 KB那应该在对象存储上想办法而不是纠结数据库分片。反过来如果业务查询的主路径是“按用户 ID 查他的所有订单”那按月分片就明显不合适因为用户不知道他 3 月在哪个表里。这种场景应该按用户 ID 哈希分片而不是按时间。所以选定分片键之前先梳理业务查询的主路径这比什么都重要。2.3 BYMONTH 定制包比通用版本多了什么既然是叫_BYMONTH的定制包那它肯定不只是改了个名字。从我实际拆包对比的情况看这个版本里有几个地方是动过的一是默认的rule.xml里预置了按月分片的完整规则解压即用。通用版 MyCat 的规则里默认带的是mod-long取模和sharding-by-enum枚举按月分片的规则需要自己去写 Java 类或者配置。而这个定制包已经把这些全部配好了连dataNode的示例都给了三个月的量。二是PartitionByMonth这个类做了本地化调整。官方版本对日期格式和边界值的校验比较严格一旦传进来的日期格式不对直接抛异常。定制包这边把容错做了增强格式不对的时候会按当前月份兜底处理避免一个脏数据导致整个写入链路崩溃。这个改法在生产环境里很实用毕竟上游传过来的数据质量永远是个变量。三是连接池的参数做了微调。针对按月分片后经常出现的“月初突然涌入大量写入”的场景把 initialSize、maxActive 等参数调大了一些减少了月初连接数不足导致的超时。这些细节官方版本不是不能改但愿意在打包之前就帮你调好的人确实不多。3. 实操从解压到全链路跑通 BYMONTH 分片3.1 环境准备与配置文件初识先把环境捋一下。MyCat 本身不存储数据它只是中间代理所以你得先准备好后端 MySQL 实例。我这里以三台 MySQL 为例分别对应 3 月、4 月、5 月的数据三台机器的 IP 假设是192.168.1.11、192.168.1.12、192.168.1.13端口都是 3306。解压mycat-1.6.7.6_BYMONTH.zip之后目录结构大致是这样的mycat/ ├── bin/ ├── conf/ │ ├── schema.xml │ ├── rule.xml │ ├── server.xml │ └── ... ├── lib/ ├── logs/ └── version.txtconf目录是核心三个文件各司其职server.xml管 MyCat 自身的账号权限和系统参数schema.xml管逻辑库、逻辑表到物理库、物理表的映射rule.xml管分片规则的定义。我们这次主要动的就是这三个文件。3.2 一步步拆解 schema.xml 配置schema.xml是 MyCat 的“总装图”。打开它之后你首先看到的是schema标签里面定义了逻辑库和逻辑表接着是dataNode定义每个分片节点对应的物理库最后是dataHost定义后端 MySQL 的连接信息。对于按月分片的需求配置大概是这样的schema nametestdb checkSQLschemafalse sqlMaxLimit100 table namet_log primaryKeyid dataNodedn_202403,dn_202404,dn_202405 rulesharding-by-month / /schema dataNode namedn_202403 dataHosthost1 databasedb_202403 / dataNode namedn_202404 dataHosthost2 databasedb_202404 / dataNode namedn_202405 dataHosthost3 databasedb_202405 /注意几个细节dataNode的名字可以随意起但它对应的database必须提前在 MySQL 里建好MyCat 不会自动帮你建库。如果你偷懒没建启动的时候不报错但第一条 SQL 打过来就会报“Table doesnt exist”排查起来一脸懵。另外rule属性对应的sharding-by-month必须在rule.xml里有定义否则加载直接失败。dataHost部分就是标准配置但有一个地方务必单独确认就是balance和writeType的参数。如果你只是做分片不做读写分离balance0、writeType0就够了这意味着所有请求都发给主库。如果配置不当比如把balance设成了 1而你的从库数据同步有延迟那分分钟出现刚写入就查不到的诡异问题。3.3 定制 rule.xml 里的按月分片规则rule.xml里分成两大块tableRule和function。tableRule定义逻辑表用哪个算法、分片键是什么function定义算法的具体实现类和参数。BYMONTH 定制包里的rule.xml已经把按月分片规则写好了核心配置如下tableRule namesharding-by-month rule columnscreate_time/columns algorithmpartbymonth/algorithm /rule /tableRule function namepartbymonth classio.mycat.route.function.PartitionByMonth property namedateFormatyyyy-MM-dd/property property namebeginDate2024-03-01/property property nameendDate2024-05-31/property /function这里columns指定的就是分片键也就是 SQL 里 WHERE 条件的查询字段。beginDate和endDate定义了分片的时间范围MyCat 会在启动时检查传入的日期是否在这个范围内。这里有一个非常容易踩的坑如果endDate没有配置PartitionByMonth会默认按当前系统时间的月份计算分片数。这就会导致一个问题——你配置了 3 个 dataNode但系统当前是 8 月MyCat 自动算出需要 6 个节点结果启动就报错说分片数超过 dataNode 数量。所以生产环境务必显式配置endDate和你的 dataNode 数量严格对应上。3.4 在 server.xml 里设置账号权限server.xml里需要关注的是user标签这里配置的是客户端连接 MyCat 时用的账号。默认配置有一个root和123456但我在生产环境从来不用默认账号因为权限太宽了。建议最小权限配置user nameapp_user defaultAccounttrue property namepasswordApp2024/property property nameschemastestdb/property property namereadOnlyfalse/property /user只给testdb这个逻辑库的权限readOnly设成 false 表示可写。如果你不想让某个账号有写权限单独配置readOnlytrue的账号即可。另外server.xml里的system部分可以调一些全局参数比如maxCon限制最大连接数、processorBufferPoolType控制缓冲区类型。这些都是性能调优的入口后面会提到。3.5 启动 MyCat 与验证分片路由配置弄完之后启动就很简单了。Linux 下直接cd /usr/local/mycat/bin ./mycat start然后看日志确认启动成功tail -f /usr/local/mycat/logs/mycat.log看到Server started successfully就说明起来了。接下来用 MySQL 客户端连接 MyCat 端口默认是 8066mysql -uapp_user -pApp2024 -h127.0.0.1 -P8066 -Dtestdb连上之后先试着插入一条 3 月的数据再插一条 4 月的INSERT INTO t_log (id, content, create_time) VALUES (1, march log, 2024-03-15 10:00:00); INSERT INTO t_log (id, content, create_time) VALUES (2, april log, 2024-04-15 10:00:00);如果分片规则生效这两条数据会分别落到底层不同的物理库上。你可以直接到后端 MySQL 上去查确认-- 在 192.168.1.11 的 db_202403 库里执行 SELECT * FROM t_log; -- 应该只能查到 1 那条这里有几个验证的小技巧在 MyCat 里执行EXPLAIN INSERT INTO ...可以看到这条 SQL 被路由到哪个 dataNode。另外MyCat 的管理端口 9066 也可以用来查看路由状态登录后执行show route能看到最近 SQL 的路由详情这在排查分片问题时特别有用。4. 踩坑实录跨月查询与数据失衡的坑我都替你踩过了4.1 跨月查询为什么这么慢按月分片之后当月数据的查询性能确实好但跨月查询就是另一回事了。比如一条 SQL 是“查 2024 年 3 月到 4 月的所有数据”如果 WHERE 条件里对create_time的函数操作不当MyCat 可能会把所有分片节点都扫一遍然后做结果合并。这比单表全扫还慢因为多了网络开销和数据合并的步骤。问题通常出在条件写法上。比如你写WHERE MONTH(create_time) BETWEEN 3 AND 4表面上很合理但MONTH()这个函数包裹了分片键MyCat 做路由解析时无法从里面提取出精确的范围只能广播到全部分片。解决办法很简单不要对分片键做任何函数运算。把条件写成WHERE create_time 2024-03-01 AND create_time 2024-05-01MyCat 就能识别出这是一个跨两个分片的范围查询它会精确路由到 3 月和 4 月的节点而不会去动 5 月的节点。这一点对任何中间件都一样不光是 MyCat。4.2 月初写入尖峰怎么撑住按月分片之后每月 1 日凌晨会有一个典型的写入尖峰——上个月的归档任务还没跑完这个月的新数据已经涌进来了。我在实际运维中发现这个时间点的连接池打满导致的超时是排在第一位的故障源。MyCat 1.6.7.6 的连接池参数在server.xml里控制。遇到月初尖峰我一般会提前做两个调整一是把maxCon从默认值调大比如调到 2048让 MyCat 能承接更多前端连接二是在后端的dataHost里把maxCon也调大否则 MyCat 到 MySQL 的后端连接数不够前端连接再多也白搭。另外一个容易忽略的点是 MySQL 自身的max_connections。我见过有同事把 MyCat 的maxCon调到 4096但后端 MySQL 的max_connections只有 1000结果流量一上来 MySQL 直接拒绝连接打爆了错误日志。记住一条从 MyCat 到 MySQL 的连接数是乘积关系必须两端同步评估而不是只看一端。4.3 表中的数据怎么按时间节点迁移按月分片跑了大半年数据量会慢慢积累。默认配置下每个分片节点可能会保存多个月的数据这本身没问题。但如果你决定把某个月的数据单独拆出去或者把几个月前的历史分片归档到冷存储就需要做数据迁移。数据迁移我通常分三步走在目标 MySQL 实例上建好对应的库和表结构。注意表结构必须和 MyCat 逻辑表完全一致包括索引、约束否则导数据的时候容易出问题。使用mysqldump按时间条件导出数据比如只导 2024-03-01 到 2024-03-31 的数据mysqldump -uroot -p db_202403 t_log --wherecreate_time 2024-03-01 AND create_time 2024-04-01 t_log_march.sql。把这个 SQL 文件导入到目标库然后更新schema.xml里的 dataNode 映射最后让 MyCat 重新加载配置。这里注意reload config_all是热加载不用重启 MyCat这个操作相当实用。4.4 配置常见异常的速查与避坑指南下面整理几张排查表都是自己踩过或者帮别人排查过的典型问题直接照着对就能解决大部分启动和路由异常的困扰。启动阶段常见问题现象可能原因处理方法启动报Invalid dataNode:dn_xxxschema.xml里 dataNode 数量与rule.xml分片配置不一致核对 dataNode 映射和分片规则范围启动报PartitionByMonth类找不到lib 目录缺少定制 jar解压包不完整重新解压确认lib/MyCat-server-1.6.7.6.jar存在端口 8066 起不来端口被占用netstat -tlnpSQL 执行阶段常见问题现象可能原因处理方法单条插入报错cant find any valid datanode分片键日期超出beginDate/endDate范围检查插入数据时间字段是否在配置范围内跨月查询结果不对分片键上有函数运算路由广播去掉函数改用范围查询写法修改了配置不生效没有做配置热加载执行reload config_all数据全部落在一个节点rule.xml规则没正确关联默认走了全局表确认table标签的rule属性并查看EXPLAIN路由结果一条特别重要的经验改完配置文件后别急着直接重启 MyCat。先在命令行跑一下./mycat console以前台模式启动这样可以直观地看到启动日志里的报错。如果前台启动没有任何异常再按 CtrlC 停掉改用后台方式启动。这个方法帮我省了大量查日志的时间基本能过滤掉七成以上的低级错误。5. 性能调优与周边配置让 MyCat 跑得更顺滑5.1 连接池和线程模型怎么调MyCat 的并发模型基于 NIO 处理器核心参数在server.xml的system里。几个关键参数的参考配置property namemaxCon2048/property property nameprocessorBufferPoolType0/property property nameprocessorBufferChunk2048/property property namefrontSocketSoRcvbuf1048576/property property namefrontSocketSoSndbuf1048576/property property namebackSocketSoRcvbuf4194304/property property namebackSocketSoSndbuf1048576/propertyprocessorBufferPoolType0表示使用内存映射文件缓冲池适合高并发场景frontSocketSoRcvbuf和backSocketSoRcvbuf是前后端 Socket 缓冲区调大一些可以减少网络吞吐瓶颈。但注意缓冲区大小必须和系统实际可用内存匹配内存紧张的小机器不要盲目调大否则直接 OOM。另外MyCat 的多路复用线程池大小可以通过processors参数控制默认一般是本机 CPU 核数。在 CPU 核数大于 16 的机器上我倾向于手动设为 16因为线程数超过这个值后上下文切换的开销反而会吃掉性能收益。5.2 读写分离和 HA 是否必要如果你只是跑分片那么单写节点就够了。但如果不做任何高可用后端 MySQL 挂了整个 MyCat 入口直接断掉业务全废。所以生产环境强烈建议至少做一主一从配置两个dataHost并把writeType设为0、balance设为1或3。balance1的含义是读请求在readhost之间做负载均衡写请求只走writehost。balance3则是读写都均衡到所有节点适合主从同步延迟极小的内网环境。这个选择取决于你业务的读多写少程度和同步延迟容忍度。配置大概长这样dataHost namehost1 maxCon500 minCon20 balance1 writeType0 dbTypemysql dbDriverjdbc switchType1 heartbeatselect user()/heartbeat writeHost hosthost1_master urljdbc:mysql://192.168.1.11:3306 userroot password123456 readHost hosthost1_slave urljdbc:mysql://192.168.1.12:3306 userroot password123456 weight1 / /writeHost /dataHostswitchType1表示主节点宕机时自动切换到备节点这个是实现 HA 的基础。心跳检测默认是select user()轻量且不影响性能。5.3 日志和监控方面的建议MyCat 1.6.7.6 的日志默认在logs/mycat.log跑上一段时间会非常大。建议在conf/log4j2.xml里把日志滚动策略配一下按天切割保留最近 7 天的日志就够了。否则日志文件撑爆磁盘新的日志写不进去排查问题的时候一头雾水。监控方面最简单的方式是定期从管理端口拉取状态数据。管理端口默认是 9066登录后可以执行SHOW DATASOURCE; -- 查看后端数据源状态 SHOW CACHE; -- 查看缓存命中情况 SHOW CONNECTION; -- 查看当前连接数如果要把监控做成自动化可以写一个 Shell 脚本每分钟执行一次SHOW DATASOURCE把结果写到日志文件再用开源的监控告警系统去扫描异常指标。我用这个方法定位过一次后端连接池泄漏的问题帮了大忙。6. 写在最后的实操体会在这个 ZIP 包上折腾了这么久我最大的体会是MyCat 1.6.7.6_BYMONTH 这套东西确实老了但它解决了一个很实际的问题——在不改造业务代码的前提下让 MySQL 撑住千万级甚至亿级的数据量。它的生命力不来自技术先进性而来自无数生产环境的验证和踩坑经验的沉淀。再分享一个小技巧如果你打算长期用按月分片建议在第一次建表的时候就把未来一年的分片节点全部建好包括物理库、表、dataNode 映射。虽然 MyCat 支持在线新增 dataNode但每次动态加节点都存在配置不一致的窗口期一旦写入流量进来就可能触发路由错误。一次性铺好再配合定时任务做数据清理运维省心得多。这个方案到底能用多久、用得多大取决于你的数据增长曲线。但至少在系统重构之前它是一条成本最低、见效最快的过渡路径。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价