海量数据存储与查询 MyCat(未完成)(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 海量数据存储与查询 MyCat(未完成)(三)

四、Mycat分片技术

4.1 垂直拆分-分库

前沿

目前很多互联网系统都存在单表数据量过大的问题,这就降低了查询速度,影响了客户体验。为了提高查询速度,我们可以优化sql语句,优化表结构和索引,不过对那些百万级千万级的数据库表,即便是优化过后,查询速度还是满足不了要求。

垂直分库

就是将不同业务的数据表存放到不同的数据库服务器中。

实现分库

我们选择master1和slave1作为存放不同表的服务器。但是需要注意的是这两个服务器是存在主从复制的,我们需要将这两个服务器的主从复制关掉。

mysql> stop slave;
#查看主从复制是否关闭
show slave status \G;

修改mycat配置文件schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
  <!-- 数据库配置 与server.xml 中的数据库对应 -->
    <schema name="db_test" checkSQLschema="false" dataNode="dn1" sqlMaxLimit="100">
      <!--如果是customer表就存放在dn2节点上,其他的表存放在dn1数据节点上-->
      <table name="customer" dataNode="dn2"/>
    </schema>
  <!-- 两个数据节点 dn1,2 上都要创建 orders 数据库 -->
    <dataNode name="dn1" dataHost="host1" database="orders" />
    <dataNode name="dn2" dataHost="host2" database="orders" />
  <!-- 两个数据库 肯定两个 dataHost -->
    <dataHost name="host1" maxCon="1000" minCon="10" balance="0"
             writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM1" url="192.168.66.100:3350" user="root"
                  password="123456">
        </writeHost>
    </dataHost>
    <dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM2" url="192.168.66.100:3360" user="root" password="123456">
        </writeHost>
    </dataHost>
</mycat:schema>

启动/重新启动mycat

mycat start/restart

开启3350和3360两个docker容器master1和slave1(此时两者不具备主从复制关系).

docker start master1
docker start slave1
#分别进入到容器
docker exec -it master1 /bin/bash
docker exec -it slave1/bin/bash
#分别进入两个数据库
mysql -uroot -p123456
#分别创建orders表
mysql> create database orders;

进入mycat,并创建表验证垂直分库

mysql -uroot -p123456 -h192.168.66.100 -P8066
create table customer(
  id int auto_increment,
  name varchar(200),
 primary key(id)
);
create table orders(
  id int auto_increment,
  order_type int,
  customer_id int,
  amount decimal(10,2),
 primary key(id)
);
create table orders_detail(
  id int auto_increment,
  order_id int,
  detail varchar(200),
 primary key(id)
);
create table dict_order_type(
  id int auto_increment,
  order_type varchar(200),
 primary key(id)
);

master1节点中的数据表

mysql> show tables;
+------------------+
| Tables_in_orders |
+------------------+
| dict_order_type  |
| orders           |
| orders_detail    |
+------------------+
3 rows in set (0.00 sec)

slave1节点中的数据表

mysql> show tables;
+------------------+
| Tables_in_orders |
+------------------+
| customer         |
+------------------+
1 row in set (0.00 sec)

综上,垂直分库成功!

4.2 水平拆分-分表

前言

上面谈到垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题。

水平拆分

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。

理解:

我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。

实现分表

1、 选择要拆分的表

MySQL 单表存储数据条数是有瓶颈的,单表达到 1000 万条数据就达到了瓶颈,会影响查询效率,需要进行水平拆分(分表)进行优化。

2、分表字段

以 orders 表为例,可以根据不同字段进行分表

编号 分表字段 效果
1 id 查询订单注重时效,历史订单被查询的次数少,如此分片会造成一个节点访问多,一个访问少,不平均。
2 customer_id 根据客户 id 去分,两个节点访问平均。

3、 修改配置文件 schema.xml

为 orders 表设置数据节点为 dn1、dn2,并指定分片规则为 mod_rule(自定义的名字)

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" dataNode="db_node1"  sqlMaxLimit="100">
       <table name="orders" dataNode="db_node1,db_node2" rule="mod_rule"/>
        </schema>
        <dataNode name="db_node1" dataHost="db_host1" database="orders" />
        <dataNode name="db_node2" dataHost="db_host2" database="orders" />
        <dataHost name="db_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.66.100:3350" user="root" password="123456">   
                </writeHost>
        </dataHost>
        <dataHost name="db_host2" 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.66.100:3360" user="root" password="123456">   
                </writeHost>
        </dataHost>
</mycat:schema>

4、修改配置文件rule.xml

分片规则:

在 rule 配置文件里新增分片规则 mod_rule,并指定规则适用字段为 customer_id, 还有选择分片算法 mod-long(对字段求模运算),customer_id 对两个节点求模,根据结果分片.配置算法 mod-long 参数 count 为 2,两个节点。

<tableRule name="mod_rule">
 <rule>
  <columns>customer_id</columns>
  <algorithm>mod-long</algorithm>
 </rule>
</tableRule>
<function name="mod-long"   class="io.mycat.route.function.PartitionByMod">
 <!-- 物理主机的节点数 -->
 <property name="count">2</property>
</function>

5、 重启Mycat,让配置生效

6、 在数据节点dn1,dn2上建orders表

create table orders(
  id int auto_increment,
  order_type int,
  customer_id int,
  amount decimal(10,2),
 primary key(id)
);

7、 连接mycat并添加数据

mysql -uroot -p123456 -h192.168.66.100 -P8066
INSERT INTO orders(id,order_type,customer_id,amount) VALUES (1,101,100,100100);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);

在mycat中可以看到全部的6条数据,但是在两个节点中只能看到3条数据。

4.3 ER表

分片 join

在上一小结主要是实现了数据表的水平拆分,但是在做表和表之间的连接查询的时候会出问题,假设我们用orders表和orders_details表做关联查询,sql发送到mycat的时候发现orders表做水平拆分后出现在好几个数据库服务器中,于是就将sql发送给这些服务器,但是有些服务器不存在orders_detilas表,执行sql会返回错误。这就是分片join错误。

ER 表

将子表的存储位置依赖于主表,并且物理上紧邻存放因此彻底解决了JION的效率和性能问题,根据这一思路,提出了基于E-R关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上。说人话就是我们将表和表之间基于某种关系或指定分为子表和父表,mycat会将子表的数据存放在含有父表的数据库服务器上。

修改配置文件schema.xml配置父子关系

<schema name="TESTDB" checkSQLschema="false" dataNode="db_node1"  sqlMaxLimit="100">
       <table name="orders" dataNode="db_node1,db_node2" rule="mod_rule">
             #childTable:子表
            <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
       </table>
 </schema>

重启Mycat服务

mycat restart

分别在两个数据库中创建orders数据库,其中一个数据库不含orders_detail表

向mycat中添加数据

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
10月前
|
NoSQL MongoDB
12 MongoDB - 数据查询(消除重复)
12 MongoDB - 数据查询(消除重复)
196 0
|
存储 关系型数据库 MySQL
海量数据存储与查询 MyCat(未完成)(二)
海量数据存储与查询 MyCat(未完成)(二)
|
3月前
|
存储 监控 NoSQL
MongoDB索引解析:工作原理、类型选择及优化策略
MongoDB索引解析:工作原理、类型选择及优化策略
|
2月前
|
SQL canal Serverless
Serverless 应用引擎使用问题之每次记录的数据很少,如何不使用外链数据库储存数据
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
2月前
|
运维 关系型数据库 分布式数据库
PolarDB产品使用问题之将部分表设置为压缩表,是否会对节点的整体性能影响
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
2月前
|
SQL
云架构数据倾斜问题之在SQL数据源读取查询时合并小文件如何解决
云架构数据倾斜问题之在SQL数据源读取查询时合并小文件如何解决
|
4月前
|
分布式计算 Java 关系型数据库
|
4月前
|
存储 关系型数据库 MySQL
史上最全MySQL剖析:优化+存储+查询+索引+复制+可扩展+高可用
在互联网行业,MySQL数据库毫无疑问已经是最常用的数据库,LAMP (Linux +Apache + MySQL + PHP)甚至已经成为专有名词,也是很多中小网站建站的首选技术架构。
|
10月前
|
算法 数据库
数据库系列课程(06)-MyCat分片按省操作数据库例子
数据库系列课程(06)-MyCat分片按省操作数据库例子
37 0
|
SQL 关系型数据库 MySQL
海量数据存储与查询 MyCat(未完成)(一)
海量数据存储与查询 MyCat(未完成)(一)