MyCat实现分库分表

文章目录

前言

随着业务量的增长,单库单表往往会遇到性能瓶颈。当一张表的数据量达到千万级别时,查询效率会明显下降。这时候就需要考虑分库分表了。本文将介绍如何使用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服务器上分别创建数据库:

sql 复制代码
-- MySQL 1 (192.168.1.101)
CREATE DATABASE db1;

-- MySQL 2 (192.168.1.102)
CREATE DATABASE db2;

创建分表

在每个数据库中创建3张订单表:

sql 复制代码
-- 在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安装配置

下载安装

bash 复制代码
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 复制代码
<?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 复制代码
<?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 复制代码
<?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

bash 复制代码
# 启动
/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

bash 复制代码
mysql -uroot -p123456 -h127.0.0.1 -P8066 -Dorderdb

插入数据

sql 复制代码
-- 插入测试数据
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实例查看数据:

sql 复制代码
-- 在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查询时,就像操作单表一样:

sql 复制代码
-- 查询指定用户的订单(会路由到特定分片)
SELECT * FROM `order` WHERE user_id = 1001;

-- 查询所有订单(会聚合所有分片的结果)
SELECT * FROM `order` ORDER BY create_time DESC LIMIT 10;

-- 统计订单总数
SELECT COUNT(*) FROM `order`;

常见分片算法

MyCat支持多种分片算法:

  1. 取模分片:根据字段值取模
  2. 范围分片:根据字段值的范围
  3. 枚举分片:根据枚举值映射
  4. 时间分片:按日期分片
  5. 字符串哈希分片:字符串哈希

注意事项

1. 跨分片查询

sql 复制代码
-- 不带分片键的查询会扫描所有分片,性能差
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拦截等

在实际使用中,建议先做好容量规划和性能测试,确保分片方案能满足业务需求。

相关推荐
Savvy..2 小时前
Redis 黑马点评-商户查询缓存
数据库·redis·缓存
可DRAK鸦|・ω・`)2 小时前
ArcGIS数据迁移问题汇总(postgresql)
数据库·postgresql
奶糖 肥晨2 小时前
批量重命名技巧:使用PowerShell一键整理图片文件命名规范
android·服务器·数据库
数据与人3 小时前
MySQL 8.0 InnoDB ReplicaSet 完整配置指南与切换
数据库·mysql·adb
JIngJaneIL4 小时前
图书馆自习室|基于SSM的图书馆自习室座位预约小程序设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·图书馆自习室
不要再敲了4 小时前
SSM框架下的redis使用以及token认证
数据库·spring boot·redis·缓存·mybatis
神的孩子都在歌唱4 小时前
PostgreSQL向量检索:pgvector入门指南
数据库·postgresql
编程充电站pro4 小时前
SQL 多表查询实用技巧:ON 和 WHERE 的区别速览
数据库·sql
Swift社区4 小时前
SQL 执行异常排查 java.sql.SQLException:从 SQLException 说起
java·数据库·sql