Mycat是基于Java编写的实现了MySQL协议的数据库中间件,可以将它看成一个数据库代理,可以直接用MySQL客户端工具访问。其核心功能是分库分表和读写分离。
MyCat 是基于阿里开源的 Cobar 产品而研发,Cobar 的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得 Mycat 变得非常的强大。
官网 http://www.mycat.org.cn/
1.1 Mycat作用
1.1.1 数据分片
数据分片包括里:垂直分片和水平分片,垂直分片包括:垂直分库和垂直分表,水平分片包括: 水平分库和水平分表。
1)垂直分库
- 数据库中不同的表对应着不同的业务,垂直切分是指按照业务的不同将表进行分类,分布到不同的数据库上面
- 将数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果
2) 垂直分表
表中字段太多且包含大字段的时候,在查询时对数据库的IO、内存会受到影响,同时更新数据时,产生的binlog文件会很大,MySQL在主从同步时也会有延迟的风险。
- 将一个表按照热字段(访问频繁)、大字段和其他字段分开,存储热字段的表更新频繁,存储冷字段或者大字段的表反问频率低,可以分散压力。
比如下面的商品表,我们把大字段商品详情字段提取出来,单独放在一张表
垂直拆分带来优缺点:
- 解决业务层面的耦合,业务清晰
- 能对不同业务的数据进行分级管理、维护、监控、扩展等
- 高并发场景下,垂直分库一定程度的提高访问性能
- 垂直拆分没有彻底解决单表数据量过大的问题
3)水平分库
没有单独的水平分库,水平分库就是水平分库分表,将单张表的数据切分到多个服务器上去,每个服务器具有相同的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈.
如下图,将商城商品表分到两个数据库服务器中
4) 水平分表
将一个张的数据分表不同的表中,但是这些表还在同一个库,解决的单表数据过大的问题,可以加快单表数据查询,新增压力。但是没有解决单库的数据和并发瓶颈。
总结
- 垂直分库: 根据不同业务的数据,分别存放在不同的数据库服务器(实例)中。
- 垂直分表: 将一个表按照字段分成多表,每个表存储其中一部分字段。
- 水平分库: 把一张表的数据按照一定规则,分配到不同的库,每一个库只有这张表的部分数据,这些库可以在一个服务器也可以在多个服务器。
- 水平分表: 把一张表的数据按照一定规则,分配到同一个数据库的多张表中,每个表只有原表的部分数据.
1.2.2 读写分离
主库负责处理事务性的写(增删改)操作,从库负责处理读(查询)操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。
但是读写分离也会带来一些问题,参考 读写分离
1.2.3 多数据源整合
Mycat可以整合多数据源
1.3 Mycat与ShardingJDBC的区别
- mycat是一个中间件的第三方应用,sharding-jdbc是一个jar包
- 使用mycat时不需要修改代码,而使用sharding-jdbc时会和代码耦合
- Mycat 是基于 Proxy,它复写了 MySQL 协议,需要独立部署服务,需要运维团队维护,而 Sharding-JDBC 是基于 JDBC 的扩展,是以 jar 包的形式提供轻量级服务的。
- Mycat(proxy中间件层)
- Sharding-jdbc应用层
1.4 Mycat2新特性
新特性总结
- 多语句,指的是可以批量执行建表语句
- 支持blob,blob二进制大对象
- 全局二级索引,用全局二级索引后,能有效减少全表扫描,对于减少连接使用,减少计算节点与存储节点的数据传输有帮助.
- 支持任意跨库跨表join查询
- 支持跨库跨表的关联子查询
- 支持分库同时分表,把分库分表合一,统一规划
- 存储过程: 存储过程支持多结果集返回、支持接收affectRow
- 支持逻辑视图
- 支持批量插入: 支持rewriteInsertBatchedStatementBatch参数(设置为true),用于提高批量插入性能。
- 支持执行计划管理:Mycat2的执行计划管理主要作用是管理执行计划,加快SQL到执行计划的转换。
- 路由注释,Mycat2对于路由注释的支持更加快捷方便,减少繁琐的配置
- 自动hash分片算法: 由1.6版本的手动配置算法,到2.0的自动hash分
- 支持第三方工具
- 单表映射物理表,可以直接将单表映射到物理表,更快速的创建数据库表
- XA事务,首先数据库要支持XA事务
- 支持MySQL8
1.5 Mycat2 核心概念
- 逻辑库
-
- 对数据进行分片之后,从原来的与一个库,被切分为了多个分片数据库,所有的分片数据库构成了整个完整的数据库存储。Mycat在操作时,使用逻辑库代表整个完整的数据库集群,方便对于整个集群进行操作。
- 物理库
-
- MySQL中真实存在的数据库
- 物理表
-
- MySQL中真实存在的表
- 分片键
-
- 用于分片的数据库字段,是将数据库进行水平拆分的关键字段
- 例:将订单表的订单主键设置为分片键,根据订单主键进行取模分片。
- 物理分表
-
- 指的是已经进行数据拆分的,在数据库上面的物理表,是分片表的一个分区,多个物理分表中的数据汇总起来就是逻辑表的全部数据。
- 物理分库
-
- 一般是指包含多个分表的库,数据切分之后每一个大表被分不到不同的数据库上面,每个表分片所在的数据库就是物理分库。
- 单表
-
- 没有分片,没有数据冗余的表
- 全局表
-
- 变动不频繁
- 数据总量变化不大
- 经常被用来进行关联查询
- 全局表不分表,在所有的库中都有一份复制,都有全量数据。在每个数据库中都有这样一张或几张全局表。比如说: 地址表 、字典表 这一类都是属于全局表
- ER表
-
- Mycat提出了基于E-R关系的数据分片策略,子表的记录与所有关联的父表的记录存放在同一个数据分片上,子表依赖于父表,通过表分组保证 数据的join不会跨库。
- 原型库
-
- 原型库是Mycat2后面的数据库,MySQL
1.6 Mycat核心配置
1.6.1 用户配置
1)配置用户相关信息的目录在: mycat/conf/users
2)命名方式:{用户名}.user.json
3)配置内容如下:
{
"dialect":"mysql",
"ip":null,
"password":"123456",
"transactionType":"xa",
"username":"root"
}
字段含义
ip:客户端访问ip,建议为空,填写后会对客户端的ip进行限制
username:用户名
password:密码
isolation:设置初始化的事务隔离级别
READ_UNCOMMITTED :1
READ_COMMITTED :2
REPEATED_READ:3,默认
SERIALIZABLE:4
tractionType:事务类型,可选值, 可以通过语句实现切换
set transaction policy ='xa'
set transaction.policy ='proxy'
proxy 表示本地事务,在涉及大于1个数据库的事务, commit阶段失败会导致不一致,但是兼容性最好xa事务,需要确认存储节点集群类型是否支持XA.
1.6.2 数据源配置
配置Mycat连接的数据源信息1)所在目录 mycat/conf/datasources2)命名方式 {数据源名字} . datasource.json3)配置内容如下:
{
"dbType":"mysql",
"idleTimeout":60000,
"initSqls":[],
"initSqlsGetConnection":true,
"instanceType":"READ_WRITE",
"maxCon":1000,
"maxConnectTimeout":3000,
"maxRetryCount":5,
"minCon":1,
"name":"prototypeDs",
"password":"123456",
"type":"JDBC",
"url":"jdbc:mysql://192.168.58.100:3310/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8",
"user":"mycat",
"weight":0
}
字段含义
dbType:数据库类型,mysql
name:用户名
password:密码
type:数据源类型,默认JDBC
url:访问数据库地址
idleTimeout:空闲连接超时时间
initSqls:初始化sql
initSqlsGetConnection:对于jdbc每次获取连接是否都执行initSqls
nstanceType:配置实例只读还是读写, 可选值:READ_WRITE,READ,WRITE
weight:负载均衡权重
连接相关配置
"maxCon": 100,
"maxConnectTimeout" : 3000,
"RetryCount" : 5,
"minCon": 1,
1.6.3 集群配置
1)配置集群信息,所在目录 mycat/conf/clusters
2)命名方式:{集群名字} . cluster.json
3)配置内容如下:
{
"clusterType":"MASTER_SLAVE", //主从集群
"heartbeat":{ //心跳检查
"heartbeatTimeout":1000,
"maxRetry":3,
"minSwitchTimeInterval":300,
"slaveThreshold":0
},
"masters":[
"prototypeDs" //主节点
],
"maxCon":200,
"name":"prototype",
"readBalanceType":"BALANCE_ALL", //负载均衡策略
"switchType":"SWITCH" //表示进行主从切换
}
字段含义
clusterType:集群类型,可选值:
SINGLE_NODE:单一节点
MASTER_SLAVE:普通主从
JSTER:garela- cluster/PXC 集群
MHA: MHA集群
MGR: MGR集群
readBalanceType:查询负载均衡策略,可选值:
BALANCE_ALL(默认值),获取集群中所有数据源
BALANCE_ALL_READ,获取集群中允许读的数据源
BALANCE_READ_WRITE,获取集群中允许读写的数据源,但允许读的数据源优先
BALANCE_NONE,获取集群中允许写数据源,即主节点中选择
switchType:切换类型
1.6.4 逻辑库表
1)配置逻辑库表,实现分库分表,所在目录 mycat/conf/schemas2)命名方式 {库名} . schema.json3)配置内容如下:
vim mysql.schema.json
{
"customTables":{},
"globalTables":{}, //全局表配置
"normalProcedures":{},
"normalTables":{ // MySQL中真实表信息
"users":{
//建表语句
"createTableSQL":"CREATE TABLE user_db.users (\n\tid INT(11) PRIMARY KEY AUTO_INCREMENT,\n\tNAME VARCHAR(20) DEFAULT NULL,\n\tage INT(11) DEFAULT NULL\n)",
"locality":{
"schemaName":"user_db", //物理库
"tableName":"users", //物理表
"targetName":"prototype" //指向集群或者数据源
}
}
},
"schemaName":"user_db",
"shardingTables":{}, //分片表配置
"views":{}
}
//详细分库分表配置,后面的内容会有讲解
注意:配置的schema的逻辑库逻辑表必须在原型库(prototype)中有对应的物理库物理表,否则不能启动
总结
分库分表解决三个问题:
- 单库承载并发限制(一般是2-3k)
- 单库表数据量过大引起的查询性能问题
- 单库存储数据的限制
但是分库分表完美的解决了这些问题吗?
- 每个节点分一部分数据,各个节点的数据都是唯一的,如果一个节点宕机,那么这部分数据不可用,服务收到影响
- 数据分散到多个节点上,如果数据热度不一致,访问量在不同节点无法平均怎么办?
- 如果分库方案不合理导致数据没有平均的分散到各个节点上怎么办?
- 随着数据增加原来的分库分表方案不能满足需求需要扩展将会很麻烦,需要重新迁移数据
- 分库分表后可能面临分布式ID、分布式事务的处理
上面这些问题都是分库分表带来的一些问题,最主要的一个问题就是单节点故障,数据只存在一个节点上,其他节点没有备份。如果讲数据分片,每个分片在不同节点都有副本,那么是不是可以解决这个问题。那么这就成了一个分布式数据库了,我们真正需要的是分布式数据库,才能解决上面所有的问题。参考https://blog.csdn.net/qq_36037795/article/details/142329972