分布式数据库中间件 MyCat | 分库分表实践
MyCat 简介
MyCat
是一个功能强大的分布式数据库中间件,是一个实现了 MySQL
协议的 Server
,前端人员可以把它看做是一个数据库代理中间件,用 MySQL
客户端工具和命令行访问;而后端人员可以用 MySQL
原生协议与多个 MySQL
服务器通信,也可以用 JDBC
协议与大多数主流数据库服务器通信。可以用作 读写分离、分库分表(分片)、容灾备份、多租户应用开发、大数据基础设施,使底层数据架构具备很强的适应性和灵活性。
MyCat
的智能优化模块可以使系统的数据访问瓶颈和热点一目了然,并且可以将这些统计分析数据自动或手工调整后端存储,将不同的表映射到不同存储引擎上,而整个应用的代码可以一行也不用变。
具体应用场景
- 读写分离:支持读写分离,主从切换,此配置最简单;
- 分库分表:对于超过 1000 万的表进行分片,最大支持 1000 亿的单表分片;
- 多租户应用:每个应用一个库,但应用程序只连接 MyCat,使程序不用改造本身,实现多租户化;
- 替代
Hbase
:用于分析大数据; - 报表系统:借助 MyCat 的分表能力,处理大规模报表的统计;
- 海量数据查询:比如 10 亿条频繁查询的记录需要在 3 秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时 MyCat 可能是最简单有效的选择。
本文主要实践核心功能 分库分表。
分库分表原理剖析
指通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果。
根据切分规则的类型可以分为以下两种切分模式。
垂直切分:最大特点是规则简单,适合各业务之间的的耦合度非常低、相互影响小、业务逻辑非常清晰的系统。在这种系统中,可以很容易 将不同业务模块所使用的的表切到不同的数据库中。
水平切分:相对来说复杂一些,因为要 将同一个表中的不同数据切分到不同的数据库中,后期的数据维护也更为复杂一些。
垂直切分
一个数据库由很多表构成,每个表对应着不同的业务,垂直切分就是按照业务将表进行分类,从而分布到不同的数据库上面,这样也就将压力分担到不同的数据库上,如图。
一个架构设计好的系统其总体功能通常是由多个功能模块所组成的,而每一个功能模块的数据对应到数据库中就是一个或多个表。而在架构设计中,各个功能模块相互之间的交互点越少和越统一,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好,这样的系统也就越容易实现垂直切分。
但是往往系统中有些表难以做到完全的独立,存在跨库 join
的情况,对于这类分库,可以共用一个数据源,业务之间通过接口来调用。
优点:规则明确、业务清晰、更易于整合和扩展、维护简单。
缺点:部分业务表无法 join
,需要通过业务接口方式解决,提高系统复杂度;各业务存在单库性能瓶颈,不易于数据扩展和性能提高;事务处理复杂问题。
由于垂直切分是将表按照业务分类切分到不同的单库中,所有导致某些业务表过于庞大,存在单库读写与存储瓶颈,则需要水平切分来解决。
水平切分
水平切分不是将表按照业务分类,而是按照某个字段的某种规则分散到多个库中,每个表中包含一部分数据,如图。
拆分数据需要定义分片规则,拆分的第一原则是找到 拆分维度。比如:从会员的角度来分析,需要查询会员某天某月某个订单,那么就需要按照日期来拆分,不同的数据按照会员 ID 做分组。
优点:拆分规则抽象好;不存在单库数据瓶颈问题;提高系统稳定性和负载能力。
缺点:事务一致性难以解决;数据扩展和维护的难度极大;跨库 join 性能差。
附:多数据源管理方案
- 第一种:客户端模式,在每个应用程序中配置管理自己需要的一个或多个数据源,直接访问各个数据库。
- 第二种:通过中间代理层来统一管理所有的数据源。
搭建环境
均采用 Docker Compose 搭建服务
部署 3 台 MySQL 容器
分别创建 3 份 docker-compose.yml
文件
mysql-01
version: '3.1'
services:
mysql-1:
image: mysql
container_name: mysql-01
environment:
MYSQL_ROOT_PASSWORD: 123456
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
ports:
- 3306:3306
volumes:
- ./data:/var/lib/mysql
mysql-02
version: '3.1'
services:
mysql-2:
image: mysql
container_name: mysql-02
environment:
MYSQL_ROOT_PASSWORD: 123456
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
ports:
- 3307:3306
volumes:
- ./data:/var/lib/mysql
mysql-03
version: '3.1'
services:
mysql-3:
image: mysql
container_name: mysql-03
environment:
MYSQL_ROOT_PASSWORD: 123456
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
ports:
- 3308:3306
volumes:
- ./data:/var/lib/mysql
分别启动 3 台容器
$ docker-compose up -d
部署 MyCat 容器
克隆项目
$ git clone https://github.com/antoniopeng/docker.mycat.git
构建镜像
$ cd docker.mycat
$ docker-compose build
启动容器
$ docker-compose up -d
配置数据库分片
此处以 水平切分 为例
配置用户名和密码
$ vi config/mycat/server.xml
找到第 90 行,参考配置如下:
<mycat:server xmlns:mycat="http://io.mycat/">
<user name="root">
<property name="password">123456</property>
<property name="schemas">hellomycat</property>
<property name="usingDecrypt">0</property>
</user>
</mycat:server>
配置数据库节点
$ vi config/mycat/schema.xml
参考配置如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="hellomycat" checkSQLschema="true" sqlMaxLimit="100">
<table />
</schema>
<dataNode name="dataNode1" dataHost="dataHost1" database="hellomycat_1" />
<dataNode name="dataNode2" dataHost="dataHost2" database="hellomycat_2" />
<dataNode name="dataNode3" dataHost="dataHost3" database="hellomycat_3" />
<dataHost name="dataHost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost
host="192.168.127.130"
url="jdbc:mysql://192.168.127.130:3306?useSSL=false&serverTimezone=UTC&characterEncoding=utf8"
user="root" password="123456">
</writeHost>
</dataHost>
<dataHost name="dataHost2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost
host="192.168.127.130"
url="jdbc:mysql://192.168.127.130:3307?useSSL=false&serverTimezone=UTC&characterEncoding=utf8"
user="root" password="123456">
</writeHost>
</dataHost>
<dataHost name="dataHost3" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost
host="192.168.127.130"
url="jdbc:mysql://192.168.127.130:3308?useSSL=false&serverTimezone=UTC&characterEncoding=utf8"
user="root" password="123456">
</writeHost>
</dataHost>
</mycat:schema>
分片规则配置如下
$ vi config/mycat/rule.xml
第 32 行配置
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
第 105 行配置
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>
自定义数字范围分片规则
$ vi config/mycat/autopartition-long.txt
配置如下:
# range start-end ,data node index
# K=1000,M=10000.
# ID 0-5000000 保存在 dataNode1
0-500M=0
# ID 5000000-10000000 保存在 dataNode2
500M-1000M=1
# ID 10000000-15000000 保存在 dataNode3
1000M-1500M=2
验证是否成功
使用 MySQL 客户端工具连接 MyCat,默认端口号为 8066
。
分别在 3 个数据库中创建表,只需要 ID 一个字段即可:
create table sys_user (id int not null primary key);
新增数据:
insert into sys_user(id) values(2000000);
insert into sys_user(id) values(7000000);
insert into sys_user(id) values(1200000);
新增后如果 3 个数据库的表中都出现了一条数据,则说明分片成功。
- 文章作者:彭超
- 本文首发于个人博客:https://antoniopeng.com/2020/08/20/%E5%88%86%E5%B8%83%E5%BC%8F/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%E9%97%B4%E4%BB%B6%20MyCat%20-%20%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8%E5%AE%9E%E8%B7%B5/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 彭超的博客 | Antonio Blog
分布式数据库中间件 MyCat | 分库分表实践的更多相关文章
- MyCat | 分库分表实践
引言 先给大家介绍2个概念:数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式. 切分模式 一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之 ...
- MySQL 高可用:mysql+mycat实现数据库分片(分库分表)
本文引用于http://blog.csdn.net/kk185800961/article/details/51147029 MySQL 高可用:mysql+mycat实现数据库分片(分库分表) 什么 ...
- MariaDB Spider 数据库分库分表实践
分库分表 一般来说,数据库分库分表,有以下做法: 按哈希分片:根据一条数据的标识计算哈希值,将其分配到特定的数据库引擎中: 按范围分片:根据一条数据的标识(一般是值),将其分配到特定的数据库引擎中: ...
- MySQL+MyCat分库分表 读写分离配置
一. MySQL+MyCat分库分表 1 MyCat简介 java编写的数据库中间件 Mycat运行环境需要JDK. Mycat是中间件.运行在代码应用和MySQL数据库之间的应用. 前身 : cor ...
- 《MyCat分库分表策略详解》
在我们的项目发展到一定阶段之后,随着数据量的增大,分库分表就变成了一件非常自然的事情.常见的分库分表方式有两种:客户端模式和服务器模式,这两种的典型代表有sharding-jdbc和MyCat.所谓的 ...
- MyCat分库分表入门
1.分区 对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm. 根据一定的规则把数据文件(MYD)和索引文件(MYI)进行了分割,分区后 ...
- 分布式数据库中间件Mycat百亿级数据存储(转)
此文转自: https://www.jianshu.com/p/9f1347ef75dd 2013年阿里的Cobar在社区使用过程中发现存在一些比较严重的问题,如高并发下的假死,心跳连接的故障,只实现 ...
- 分布式数据库中间件 MyCat 搞起来!
关于 MyCat 的铺垫文章已经写了三篇了: MySQL 只能做小项目?松哥要说几句公道话! 北冥有 Data,其名为鲲,鲲之大,一个 MySQL 放不下! What?Tomcat 竟然也算中间件? ...
- 分库分表实践-Sharding-JDBC
最近一段时间在研究分库分表的一些问题,正好周末有点时间就简单做下总结,也方便自己以后查看. 关于为什么要做分库分表,什么是水平分表,垂直分表等概念,相信大家都知道,这里就不在赘述了. 本文只讲述使用S ...
随机推荐
- 面试题四十二:连续子数组的最大和,要求时间复杂度为 n
方法一:举例分析数组的规律,累加数组逐步保存最大值:累加中和<0,则遗弃前面的累加和:重新开始: int FindMaxArray(int [] A) { if(A= ...
- Kubernetes实战总结 - DevOps实现
一.概述 Git:一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. Jenkins:一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作. M ...
- PHP 循环 - For 循环基础讲解
PHP 循环 - For 循环 循环执行代码块指定的次数,或者当指定的条件为真时循环执行代码块. for 循环 for 循环用于您预先知道脚本需要运行的次数的情况. 语法 for (初始值; 条件; ...
- PHP is_bool() 函数
is_bool() 函数用于检测变量是否是布尔型.高佣联盟 www.cgewang.com PHP 版本要求:PHP 4, PHP 5, PHP 7 语法 bool is_bool ( mixed $ ...
- PHP is_nan() 函数
实例 判断一个值是否为非数值: <?phpecho is_nan(200) . "<br>";echo is_nan(acos(1.01));?>高佣联盟 ...
- PHP xml_set_character_data_handler() 函数
定义和用法 xml_set_character_data_handler() 函数为 XML 解析器建立字符数据处理器. 该函数规定当解析器在 XML 文件中找到字符数据时所调用的函数.高佣联盟 ww ...
- luogu P4321 随机漫游 期望dp 二进制 高斯消元
LINK:随机漫游 非常妙的一道题. 容易想到倒推期望. 设状态 f[i][j]表示到达第i个点 此时已经到达的集合为j能走到全集的期望边数. 只要求出来这个就能O(1)回答询问. \(f[i][j] ...
- intel:spectre&Meltdown侧信道攻击(二)
上面一篇介绍了spectre&meltdown基本原理和简单的demo方案,今天继续学习一下该漏洞发现团队原始的POC:https://spectreattack.com/spectre.pd ...
- 关于 ORA-01033: ORACLE initialization or shutdown in progress
第一步: 这个错误首先查看服务进程是否正常启动: 第二步: 一般情况下第一步都没问题,问题出在可能误删了日志文件: 当然可能不是你删除的,可能被某些清理软件删除的: 或者是其他情况导致日志出错 ...
- springMVC请求路径 与实际资源路径关系
个人理解: 请求路径可以分为两部分:不通过springmvc转发的url:通过springmvc转发的url: 通过特定的配置,告诉springmvc哪些url需要从springmvc处理,处理后再跳 ...