【详解】Mycat读写分离+垂直切分+水平切分+er分片+全局表
Mycat读写分离+垂直切分+水平切分+ER分片+全局表
引言
随着互联网应用的快速发展,数据量的爆炸性增长给数据库带来了前所未有的压力。传统的单体数据库已经难以满足高并发、大数据量的处理需求。Mycat作为一款开源的分布式数据库中间件,通过读写分离、垂直切分、水平切分、ER分片和全局表等技术,有效解决了这些问题。本文将详细介绍这些技术在Mycat中的实现和配置方法。
1. 读写分离
1.1 概述
读写分离是提高数据库性能的一种常见手段,通过将读操作和写操作分配到不同的数据库实例上,可以显著提升系统的吞吐量。Mycat支持基于规则的读写分离,可以根据业务需求灵活配置。
1.2 配置示例
在server.xml
中配置读写分离:
<user name="test">
<property name="password">test</property>
<property name="schemas">TESTDB</property>
<property name="defaultHost">write</property>
</user>
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="t_order" dataNode="dn1,dn2" rule="auto-sharding-long"/>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="testdb1" />
<dataNode name="dn2" dataHost="localhost2" database="testdb2" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="localhost:3306" user="root" password="root">
<readHost host="hostS1" url="localhost:3307" user="root" password="root"/>
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="localhost:3308" user="root" password="root">
<readHost host="hostS2" url="localhost:3309" user="root" password="root"/>
</writeHost>
</dataHost>
1.3 关键参数解释
-
balance
: 负载均衡策略,0表示不开启,1表示轮询。 -
writeType
: 写操作的路由策略,0表示所有写操作都路由到主库。 -
switchType
: 切换策略,1表示自动切换。 -
slaveThreshold
: 延迟阈值,超过该值的从库不会被选中。
2. 垂直切分
2.1 概述
垂直切分是指将不同的表或业务模块拆分到不同的数据库中,以减少单个数据库的压力。Mycat支持通过配置schema
和table
来实现垂直切分。
2.2 配置示例
在schema.xml
中配置垂直切分:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="t_user" dataNode="dn1" />
<table name="t_order" dataNode="dn2" />
</schema>
<dataNode name="dn1" dataHost="localhost1" database="testdb1" />
<dataNode name="dn2" dataHost="localhost2" database="testdb2" />
2.3 关键参数解释
-
table name
: 表名。 -
dataNode
: 数据节点名称,对应具体的数据库实例。
3. 水平切分
3.1 概述
水平切分是指将同一张表的数据拆分到多个数据库中,以分散数据存储压力。Mycat支持通过配置分片规则来实现水平切分。
3.2 配置示例
在rule.xml
中配置水平切分规则:
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<property name="count">2</property>
</function>
在schema.xml
中应用分片规则:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="t_order" dataNode="dn1,dn2" rule="auto-sharding-long"/>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="testdb1" />
<dataNode name="dn2" dataHost="localhost2" database="testdb2" />
3.3 关键参数解释
-
tableRule name
: 分片规则名称。 -
columns
: 分片列。 -
algorithm
: 分片算法。 -
function name
: 自定义函数名称。 -
class
: 分片函数类。 -
property
: 函数属性。
4. ER分片
4.1 概述
ER分片是指根据实体关系(Entity-Relationship)进行分片,确保相关联的数据能够被路由到同一个分片中,从而提高查询效率。Mycat支持通过配置ER分片规则来实现这一功能。
4.2 配置示例
在schema.xml
中配置ER分片:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="t_user" dataNode="dn1" primaryKey="id" />
<table name="t_order" dataNode="dn1" primaryKey="id" parentTable="t_user" joinKey="user_id" childKey="id"/>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="testdb1" />
4.3 关键参数解释
-
parentTable
: 父表名称。 -
joinKey
: 父表的关联字段。 -
childKey
: 子表的关联字段。
5. 全局表
5.1 概述
全局表是指在整个集群中只有一份的数据表,通常用于存储一些公共的、不经常变化的数据。Mycat支持通过配置全局表来实现这一功能。
5.2 配置示例
在schema.xml
中配置全局表:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="t_config" dataNode="dn1" type="global" />
</schema>
<dataNode name="dn1" dataHost="localhost1" database="testdb1" />
5.3 关键参数解释
-
type
: 表类型,global
表示全局表。
Mycat 是一个开源的分布式数据库系统,它支持读写分离、垂直切分(按业务逻辑拆分)、水平切分(按数据量拆分)、ER 分片(实体关系分片)和全局表等特性。下面是一个结合这些特性的实际应用场景示例。
应用场景
假设我们有一个电商系统,需要处理大量的用户订单和商品信息。为了提高系统的性能和可扩展性,我们可以使用 Mycat 进行如下配置:
- 读写分离:将读操作和写操作分开,减轻主库的压力。
- 垂直切分:将用户信息和订单信息分别存储在不同的数据库中。
- 水平切分:将订单信息按用户ID进行切分,存储在不同的分片中。
- ER 分片:确保相关联的数据存储在同一分片中。
- 全局表:将一些不经常变化且访问频繁的数据(如地区信息)存储在全局表中。
Mycat 配置文件示例
1. schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 定义全局表 -->
<table name="region" dataNode="dn1" rule="none" />
<!-- 垂直切分 -->
<table name="user" dataNode="dn1" />
<table name="order" dataNode="dn2,dn3" rule="mod-long-2" />
<!-- ER 分片 -->
<table name="order_item" dataNode="dn2,dn3" rule="mod-long-2" parentTable="order" />
</mycat:schema>
2. rule.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<!-- 水平切分规则 -->
<tableRule name="mod-long-2">
<rule>
<columns>user_id</columns>
<algorithm>mod-long-2</algorithm>
</rule>
</tableRule>
<!-- 分片算法 -->
<function name="mod-long-2" class="io.mycat.route.function.PartitionByMod">
<property name="count">2</property>
</function>
</mycat:rule>
3. server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<!-- 数据节点配置 -->
<dataNode name="dn1" dataHost="host1" database="db1" />
<dataNode name="dn2" dataHost="host2" database="db2" />
<dataNode name="dn3" dataHost="host3" database="db3" />
<!-- 数据源配置 -->
<dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://192.168.1.1:3306/db1" user="root" password="password">
<readHost host="hostS1" url="jdbc:mysql://192.168.1.2:3306/db1" user="root" password="password" />
</writeHost>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="jdbc:mysql://192.168.1.3:3306/db2" user="root" password="password">
<readHost host="hostS2" url="jdbc:mysql://192.168.1.4:3306/db2" user="root" password="password" />
</writeHost>
</dataHost>
<dataHost name="host3" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM3" url="jdbc:mysql://192.168.1.5:3306/db3" user="root" password="password">
<readHost host="hostS3" url="jdbc:mysql://192.168.1.6:3306/db3" user="root" password="password" />
</writeHost>
</dataHost>
</mycat:server>
解释
- schema.xml:
-
region
表被定义为全局表,存储在 dn1
数据节点上。 -
user
表存储在 dn1
数据节点上。 -
order
表按 user_id
进行水平切分,存储在 dn2
和 dn3
数据节点上。 -
order_item
表与 order
表关联,按相同的规则进行分片。
- rule.xml:
- 定义了
mod-long-2
规则,用于按 user_id
进行模运算分片。
- server.xml:
- 配置了三个数据节点
dn1
, dn2
, dn3
,每个数据节点对应一个 dataHost
。 - 每个
dataHost
配置了一个主库和一个从库,实现读写分离。
示例 SQL 语句
-- 插入用户信息
INSERT INTO user (id, name) VALUES (1, 'Alice');
-- 插入订单信息
INSERT INTO order (id, user_id, amount) VALUES (1, 1, 100);
-- 插入订单详情
INSERT INTO order_item (id, order_id, product_id, quantity) VALUES (1, 1, 101, 2);
-- 查询用户信息
SELECT * FROM user WHERE id = 1;
-- 查询订单信息
SELECT * FROM order WHERE user_id = 1;
-- 查询订单详情
SELECT * FROM order_item WHERE order_id = 1;
-- 查询全局表
SELECT * FROM region;
下面将详细介绍这些概念,并提供一些基本的配置示例。
1. 读写分离
读写分离是通过将读操作和写操作路由到不同的数据库实例来实现的。这样可以提高系统的并发处理能力,减轻单个数据库的压力。
配置示例
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" dataNode="dn1,dn2" rule="auto-sharding-long"/>
</schema>
<dataNode name="dn1" dataHost="host1" database="testdb" />
<dataNode name="dn2" dataHost="host1" database="testdb" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.1:3306" user="root" password="123456">
<readHost host="hostS1" url="192.168.1.2:3306" user="root" password="123456"/>
<readHost host="hostS2" url="192.168.1.3:3306" user="root" password="123456"/>
</writeHost>
</dataHost>
-
balance
:负载均衡类型,1
表示轮询。 -
writeType
:写入类型,0
表示所有写操作都路由到主库。 -
readHost
:读操作路由到从库。
2. 垂直切分
垂直切分是将不同的表或表的一部分分配到不同的数据库中,以减少单个数据库的压力。
配置示例
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" dataNode="dn1" />
<table name="order" dataNode="dn2" />
</schema>
<dataNode name="dn1" dataHost="host1" database="userdb" />
<dataNode name="dn2" dataHost="host2" database="orderdb" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.1:3306" user="root" password="123456"/>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="192.168.1.2:3306" user="root" password="123456"/>
</dataHost>
3. 水平切分
水平切分是将同一个表的数据按照某种规则(如哈希、范围等)分散到多个数据库中。
配置示例
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" dataNode="dn1,dn2" rule="auto-sharding-long"/>
</schema>
<dataNode name="dn1" dataHost="host1" database="userdb1" />
<dataNode name="dn2" dataHost="host1" database="userdb2" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.1:3306" user="root" password="123456"/>
</dataHost>
<tableRule name="auto-sharding-long">
<rule column="id" algorithm="hash-int"/>
</tableRule>
<algorithm name="hash-int" class="io.mycat.route.function.PartitionByLong">
<property name="partitionCount">2</property>
<property name="partitionLength">32</property>
</algorithm>
4. ER分片
ER分片是指在水平切分的基础上,保持表之间的外键关系。Mycat 通过 childTable
和 parentTable
来定义这种关系。
配置示例
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" dataNode="dn1,dn2" rule="auto-sharding-long"/>
<table name="order" dataNode="dn1,dn2" rule="auto-sharding-long" parentTable="user" joinKey="user_id" childKey="user_id"/>
</schema>
<dataNode name="dn1" dataHost="host1" database="userdb1" />
<dataNode name="dn2" dataHost="host1" database="userdb2" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.1:3306" user="root" password="123456"/>
</dataHost>
<tableRule name="auto-sharding-long">
<rule column="id" algorithm="hash-int"/>
</tableRule>
<algorithm name="hash-int" class="io.mycat.route.function.PartitionByLong">
<property name="partitionCount">2</property>
<property name="partitionLength">32</property>
</algorithm>
5. 全局表
全局表是指在所有分片中都存在的表,通常用于存储一些公共数据。
配置示例
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" dataNode="dn1,dn2" rule="auto-sharding-long"/>
<table name="config" dataNode="dn1,dn2" type="global"/>
</schema>
<dataNode name="dn1" dataHost="host1" database="userdb1" />
<dataNode name="dn2" dataHost="host1" database="userdb2" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.1:3306" user="root" password="123456"/>
</dataHost>
总结
以上配置示例展示了如何在 Mycat 中实现读写分离、垂直切分、水平切分、ER分片和全局表。每种配置都有其特定的应用场景,可以根据实际需求进行选择和组合。希望这些示例对你有所帮助!如果有任何问题或需要进一步的帮助,请随时告诉我。
- 点赞
- 收藏
- 关注作者
评论(0)