(实战)MyCat核心配置详解与分库分表实战指南
1. MyCat分库分表实战背景
最近接手了一个用户量激增的电商项目,数据库查询响应时间从最初的200ms飙升到3秒以上,高峰期经常出现连接池耗尽的情况。经过分析发现,单表数据量已经突破2000万行,索引都快撑不住了。这时候就需要请出我们的分布式数据库中间件MyCat了。
MyCat本质上是一个数据库代理,它最大的价值在于让应用层无感知地实现分库分表。你可以把它想象成一个老练的餐厅领班:当客人(应用程序)点菜时,领班会根据菜品类型(分片规则)把订单分发给不同的厨师(数据库节点),最后再把做好的菜拼成完整的一桌。
在实际项目中,我遇到过最常见的三种分片需求:
- 用户表按user_id范围分片
- 订单表按时间月份分片
- 商品表按品类哈希分片
下面我就用最典型的用户表场景,带大家走通从环境搭建到分片配置的完整流程。这个方案在我们生产环境支撑了日均5000万+的查询请求,响应时间稳定在50ms以内。
2. MyCat核心配置文件详解
2.1 schema.xml - 数据路由的交通图
这个文件定义了逻辑库表与实际物理库表的映射关系,就像快递分拣中心的路由表。最近在配置一个社交平台项目时,我这样设计用户表的分片:
<schema name="social_db" checkSQLschema="true"> <table name="user" dataNode="dn1,dn2,dn3" rule="mod-long" /> <table name="user_relation" dataNode="dn1,dn2,dn3" rule="mod-long" /> </schema> <dataNode name="dn1" dataHost="host1" database="social_01" /> <dataNode name="dn2" dataHost="host2" database="social_02" /> <dataNode name="dn3" dataHost="host3" database="social_03" /> <dataHost name="host1" maxCon="500" dbType="mysql"> <heartbeat>select 1</heartbeat> <writeHost url="192.168.1.101:3306" user="dbadmin" password="加密密码" /> </dataHost>几个容易踩坑的点:
- dataNode的database名称必须在真实MySQL中存在
- writeHost的密码建议使用加密工具生成
- 分片表必须明确指定primaryKey,否则更新操作会全表扫描
2.2 rule.xml - 数据分片的算法库
这里定义了各种分片算法,我常用的是这几种:
- 哈希取模(mod-long):适合均匀分布的场景
- 时间范围(sharding-by-date):适合日志类数据
- 枚举值(sharding-by-intfile):适合固定分类的数据
最近一个物流项目中,我是这样配置订单表的分片规则:
<tableRule name="sharding-by-month"> <rule> <columns>create_time</columns> <algorithm>partbyday</algorithm> </rule> </tableRule> <function name="partbyday" class="io.mycat.route.function.PartitionByDate"> <property name="dateFormat">yyyy-MM-dd</property> <property name="sBeginDate">2023-01-01</property> <property name="sPartionDay">30</property> </function>特别注意:算法中的partitionCount和partitionLength的乘积必须等于分片节点总数,否则会出现数据路由错误。
2.3 server.xml - 系统运行的控制台
这个文件主要配置MyCat服务本身参数,有几个关键配置项需要关注:
<system> <property name="defaultSqlParser">druidparser</property> <property name="processorBufferPool">2048mb</property> <property name="sequnceHandlerType">1</property> </system> <user name="app_user"> <property name="password">加密密码</property> <property name="schemas">social_db</property> <property name="readOnly">false</property> </user>生产环境建议:
- bufferPool大小设置为物理内存的1/4
- 一定要配置防火墙规则,只允许应用服务器访问8066端口
- 不同应用使用不同的数据库账号,方便权限控制
3. 分库分表实战配置
3.1 按用户ID哈希分片
以用户表为例,假设我们需要将5000万用户数据分散到3个库:
- 首先在rule.xml配置分片算法:
<tableRule name="mod-long-user"> <rule> <columns>user_id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <property name="count">3</property> </function>- 然后在schema.xml配置数据节点:
<table name="user" dataNode="dn1,dn2,dn3" rule="mod-long-user" primaryKey="user_id"/>- 验证分片效果:
-- 插入测试数据 INSERT INTO user(user_id, name) VALUES(10001, '张三'); -- 查看执行计划 explain select * from user where user_id=10001;3.2 跨分片查询优化
分库分表后最头疼的就是跨分片查询,我总结了几种解决方案:
- 使用ER表绑定关联关系:
<table name="order" dataNode="dn1,dn2" rule="mod-long"> <childTable name="order_item" joinKey="order_id" parentKey="order_id"/> </table>- 全局表配置(适合字典表):
<table name="region" dataNode="dn1,dn2,dn3" type="global"/>- 使用MyCat的shareJoin特性:
/*!mycat:catlet=io.mycat.catlets.ShareJoin */ select * from user u join order o on u.user_id=o.user_id;4. 生产环境调优经验
4.1 性能优化参数
在server.xml中这些参数需要根据硬件配置调整:
<property name="processors">16</property> <!-- CPU核心数2倍 --> <property name="processorExecutor">32</property> <!-- processors的2倍 --> <property name="defaultMaxLimit">1000</property> <!-- 最大返回行数 -->4.2 常见问题排查
- 连接数不足:
# 查看连接数 show @@connection; # 调整连接池大小 <property name="maxCon">1000</property>- 内存溢出:
# 修改启动参数 vim mycat/conf/wrapper.conf wrapper.java.additional.10=-Xmx4G- 慢查询监控:
-- 开启慢查询日志 <property name="sqlSlowTime">1000</property> -- 查看慢查询 show @@slow;最近在金融项目中遇到一个典型问题:批量插入性能差。最终通过调整batchInsertSize参数解决:
<property name="batchInsertSize">500</property>4.3 高可用方案
推荐的主从切换配置:
<dataHost name="host1" balance="1" switchType="2"> <heartbeat>show slave status</heartbeat> <writeHost host="master" url="192.168.1.101:3306" user="root" password="xxx"> <readHost host="slave" url="192.168.1.102:3306" user="root" password="xxx"/> </writeHost> </dataHost>关键参数说明:
- switchType=1 基于心跳自动切换
- switchType=2 基于MySQL主从状态切换
- balance=1 读写分离模式
在实际部署时,建议配合Keepalived实现VIP漂移,我们线上环境这样配置后,半年内实现了零宕机时间。
