MyCat实现分库分表
文章目录
- 前言
- 什么是MyCat
- 为什么需要分库分表
- 场景说明
- MySQL准备
- 创建数据库
- 创建分表
- MyCat安装配置
- 下载安装
- 配置server.xml
- 配置schema.xml
- 配置rule.xml
- 启动MyCat
- 测试验证
- 连接MyCat
- 插入数据
- 查看数据分布
- 查询数据
- 常见分片算法
- 注意事项
- 1. 跨分片查询
- 2. 主键生成
- 总结
前言
随着业务量的增长,单库单表往往会遇到性能瓶颈。当一张表的数据量达到千万级别时,查询效率会明显下降。这时候就需要考虑分库分表了。本文将介绍如何使用MyCat中间件来实现MySQL的分库分表。
什么是MyCat
MyCat是一个开源的数据库中间件,可以看作是一个数据库代理。应用程序连接MyCat就像连接MySQL一样,而MyCat会将SQL请求路由到后端的真实数据库。通过MyCat,我们可以轻松实现读写分离、分库分表等功能。
为什么需要分库分表
单表数据量过大的问题:
查询变慢:索引树层级变深,检索效率降低
写入变慢:页分裂频繁,锁竞争加剧
备份恢复慢:数据量大,备份和恢复时间长
分库分表的好处:
提高查询性能:数据分散,单次查询数据量减少
提高并发能力:请求分散到多个数据库
便于扩展:可以通过增加节点来提升性能
场景说明
假设我们有一个订单表order
,数据量巨大。我们的分库分表策略是:
- 分库:按用户ID哈希分成2个库(db1、db2)
- 分表:每个库中按订单ID模3分成3张表(order_0、order_1、order_2)
最终会有6张物理表分布在2个数据库中。
MySQL准备
创建数据库
在两台MySQL服务器上分别创建数据库:
-- MySQL 1 (192.168.1.101)
CREATE DATABASE db1;-- MySQL 2 (192.168.1.102)
CREATE DATABASE db2;
创建分表
在每个数据库中创建3张订单表:
-- 在db1和db2中都执行
CREATE TABLE order_0 (id BIGINT PRIMARY KEY,user_id BIGINT NOT NULL,product_name VARCHAR(100),amount DECIMAL(10,2),create_time DATETIME,INDEX idx_user_id(user_id)
) ENGINE=InnoDB;CREATE TABLE order_1 LIKE order_0;
CREATE TABLE order_2 LIKE order_0;
MyCat安装配置
下载安装
wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz
tar -zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /usr/local/
配置server.xml
编辑conf/server.xml
,配置MyCat的用户和逻辑库:
<?xml version="1.0" encoding="UTF-8"?>
<mycat:server xmlns:mycat="http://io.mycat/"><!-- 配置用户 --><user name="root" defaultAccount="true"><property name="password">123456</property><property name="schemas">orderdb</property></user><user name="user"><property name="password">user123</property><property name="schemas">orderdb</property><property name="readOnly">true</property></user>
</mycat:server>
配置schema.xml
这是MyCat的核心配置文件,定义了逻辑库、逻辑表和分片规则:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/"><!-- 定义逻辑库 --><schema name="orderdb" checkSQLschema="false" sqlMaxLimit="100"><!-- 定义逻辑表,rule指定分片规则 --><table name="order" dataNode="dn1,dn2" rule="order-hash-rule" /></schema><!-- 定义数据节点 --><dataNode name="dn1" dataHost="host1" database="db1" /><dataNode name="dn2" dataHost="host2" database="db2" /><!-- 定义数据主机 --><dataHost name="host1" maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native"><heartbeat>select user()</heartbeat><writeHost host="hostM1" url="192.168.1.101:3306" user="root" password="123456"></writeHost></dataHost><dataHost name="host2" maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native"><heartbeat>select user()</heartbeat><writeHost host="hostM2" url="192.168.1.102:3306" user="root" password="123456"></writeHost></dataHost></mycat:schema>
配置rule.xml
定义分片规则:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/"><!-- 定义分片规则 --><tableRule name="order-hash-rule"><rule><columns>user_id</columns><algorithm>mod-long</algorithm></rule></tableRule><!-- 定义分片算法 --><function name="mod-long" class="io.mycat.route.function.PartitionByMod"><!-- 数据节点数量 --><property name="count">2</property></function></mycat:rule>
启动MyCat
# 启动
/usr/local/mycat/bin/mycat start# 查看状态
/usr/local/mycat/bin/mycat status# 查看日志
tail -f /usr/local/mycat/logs/wrapper.log
MyCat默认监听:
- 8066端口:数据服务端口,应用连接这个端口
- 9066端口:管理端口,用于管理MyCat
测试验证
连接MyCat
mysql -uroot -p123456 -h127.0.0.1 -P8066 -Dorderdb
插入数据
-- 插入测试数据
INSERT INTO `order`(id, user_id, product_name, amount, create_time)
VALUES (1, 1001, 'iPhone 14', 5999.00, NOW());INSERT INTO `order`(id, user_id, product_name, amount, create_time)
VALUES (2, 1002, 'MacBook Pro', 12999.00, NOW());INSERT INTO `order`(id, user_id, product_name, amount, create_time)
VALUES (3, 1003, 'iPad Air', 4799.00, NOW());
查看数据分布
分别登录到两个MySQL实例查看数据:
-- 在MySQL 1上
USE db1;
SELECT * FROM order_0;
SELECT * FROM order_1;
SELECT * FROM order_2;-- 在MySQL 2上
USE db2;
SELECT * FROM order_0;
SELECT * FROM order_1;
SELECT * FROM order_2;
你会发现数据已经按照user_id的哈希值分散到不同的库和表中了。
查询数据
通过MyCat查询时,就像操作单表一样:
-- 查询指定用户的订单(会路由到特定分片)
SELECT * FROM `order` WHERE user_id = 1001;-- 查询所有订单(会聚合所有分片的结果)
SELECT * FROM `order` ORDER BY create_time DESC LIMIT 10;-- 统计订单总数
SELECT COUNT(*) FROM `order`;
常见分片算法
MyCat支持多种分片算法:
- 取模分片:根据字段值取模
- 范围分片:根据字段值的范围
- 枚举分片:根据枚举值映射
- 时间分片:按日期分片
- 字符串哈希分片:字符串哈希
注意事项
1. 跨分片查询
-- 不带分片键的查询会扫描所有分片,性能差
SELECT * FROM `order` WHERE product_name = 'iPhone';-- 带分片键的查询只会路由到对应分片
SELECT * FROM `order` WHERE user_id = 1001 AND product_name = 'iPhone';
2. 主键生成
分库分表后不能使用MySQL的自增ID,需要使用分布式ID生成方案:
- 雪花算法(Snowflake)
- 数据库序列表
- Redis生成
- MyCat自带的序列号
总结
MyCat是一个功能强大的数据库中间件,可以帮助我们快速实现分库分表。使用MyCat的优势在于:
- 对应用透明:应用程序无需修改代码,只需改一下连接地址
- 配置灵活:支持多种分片策略和路由规则
- 功能丰富:支持读写分离、分库分表、SQL拦截等
在实际使用中,建议先做好容量规划和性能测试,确保分片方案能满足业务需求。