1. Mycat入门
1.1. 什么是Mycat
- 一个彻底开源的,面向企业应用开发的大数据库集群
- 支持事务、ACID、可以替代MySQL的加强版数据库
- 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
- 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server
- 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
- 一个新颖的数据库中间件产品
1.2. Mycat关键特性
- 支持MySQL、Oracle、DB2、SQL Server、PostgreSQL等DB的常见SQL语法
- 基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluster集群。
- 基于Nio实现,有效管理线程,解决高并发问题。
- 支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数,支持跨库分页。
- 支持单库内部任意join,支持跨库2表join,甚至基于caltlet的多表join。
- 支持通过全局表,ER关系的分片策略,实现了高效的多表join查询。
- 支持全局序列号,解决分布式下的主键生成问题。
- 分片规则丰富,插件化开发,易于扩展。
- 支持密码加密
- 支持服务降级
- 支持IP白名单
- 支持SQL黑名单、sql注入攻击拦截
1.3. MYCAT监控
- 支持对Mycat、Mysql性能监控
- 支持对Mycat的JVM内存提供监控服务
- 支持对线程的监控
- 支持对操作系统的CPU、内存、磁盘、网络的监控
1.4. 架构
1.4.1. 1.6版本架构
1.4.2. Mycat架构
1.5. 优势
- 基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得MYCAT一开始就拥有一个很好的起点
- MYCAT背后有一支强大的技术团队,其参与者都是5年以上资深软件工程师、架构师、DBA等,优秀的技术团队保证了MYCAT的产品质量。
1.6. Mycat高可用方案
1.7. Mycat 原理
- Mycat 的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的 SQL 语句,首先对 SQL 语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此 SQL 发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户
1.8. 应用场景
- 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;
- 分表分库,对于超过 1000 万的表进行分片,最大支持 1000 亿的单表分片;
- 多租户应用,每个应用一个库,但应用程序只连接 Mycat,从而不改造程序本身,实现多租户化;
- 报表系统,借助于 Mycat 的分表能力,处理大规模报表的统计;
- 替代 Hbase,分析大数据;
- 作为海量数据实时查询的一种简单有效方案,比如 100 亿条频繁查询的记录需要在 3 秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时 Mycat 可能是最简单有效的选择。
1.9. Mycat中的概念
1.9.1. 逻辑库(schema)
- 数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库。
1.9.2. 逻辑表(table)
- 既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成
1.9.3. 分片节点(dataNode)
- 数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点
(dataNode)
1.9.4. 节点主机(dataHost)
- 数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)
1.9.5. 分片规则(rule)
- 一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。
1.9.6. 全局序列号(sequence)
- 数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯一性标识,这种保证全局性的数据唯一标识的机制就是全局序列号(sequence)。
1.9.7. 多租户
- 多租户技术或称多重租赁技术,是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。在云计算时代,多租户技术在共用的数据中心以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍然可以保障客户的数据隔离。目前各种各样的云计算服务就是这类技术范畴,例如阿里云数据库服务(RDS)、阿里云服务器等等。
多租户在数据存储上存在三种主要的方案,分别是:
1.9.7.1. 独立数据库
- 这是第一种方案,即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本也高。
1.9.7.2. 共享数据库,隔离数据架构
- 这是第二种方案,即多个或所有租户共享 Database,但是每个租户一个 Schema。
1.9.7.3. 共享数据库,共享数据架构
- 这是第三种方案,即租户共享同一个 Database、同一个 Schema,但在表中通过 TenantID 区分租户的数据。这是共享程度最高、隔离级别最低的模式
1.10. 快速搭建
1.10.1. 基础环境
- MyCAT 是使用 JAVA 语言进行编写开发,使用前需要先安装 JAVA 运行环境(JRE),由于 MyCAT 中使用了JDK7 中的一些特性,所以要求必须在 JDK7 以上的版本上运行。
1.10.2. docker搭建
1.下载jdk,地址 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
2. 下载mycat,http://dl.mycat.io/1.6.6.1/
3. 解压mycat,tar -zxvf Mycat-server-1.6.6.1-release.tar.gz
4. 编写Dockerfile文件
FROM ubuntu
ADD jdk-8u201-linux-x64.tar.gz /usr/local/src
ADD mycat /usr/local/src/mycat
ENV JAVA_HOME=/usr/local/src/jdk1.8.0_201
ENV PATH=$JAVA_HOME/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
EXPOSE 8666 9666 3366
RUN chmod -R 777 /usr/local/src/mycat/bin
CMD ["./usr/local/src/mycat/bin/mycat", "console"]
-
mycat安装包中主要看conf文件下面的server.xml和schema.xml两个配置文件,修改成自己的mysql配套属性
root表示用户名、220316表示登陆密码、mycat是在shema.xml中配置的名称。
mycat为应用的名称也就是我们在server.xml提到的名称、database为数据库名称、url为数据库链接地址。
上述主从模式,需要提前自己配置mysql的主从模式,可参考我原先的博客 https://www.cnblogs.com/sky-chen/p/10053314.html -
docker build -t mycat:1.0 . //注意最后有个空格加点
-
docker run --name mycat -di -p 8666:8066 -p 9666:9066 -v /root/mydocker/docker-mycat/mycat/conf:/usr/local/src/mycat/conf mycat:1.0
1.10.3. 分库分表实战
- 我在服务器启动了3306和3307两个端口作为两台mysql
- 主要是配置conf下的配置文件
- server.xml配置,主要改动user标签
<user name="tzxylao" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">mycat</property>
</user>
- schema.xml配置,需要注意的,schema标签name表示连接的逻辑库,对程序员暴露,我测试的hotnews表;dataNode标签中的database表示实际分片中真实数据库名
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="mycat" checkSQLschema="false" sqlMaxLimit="100">
<table name="hotnews" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"
rule="mod-long" />
</schema>
<dataNode name="dn1" dataHost="localhost1" database="mycat_test" />
<dataNode name="dn2" dataHost="localhost2" database="mycat_test" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="jdbc:mysql://47.99.85.92:3306" user="tzxylao"
password="123456">
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" dbType="mysql" writeType="0" switchType="1"
dbDriver="jdbc">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="jdbc:mysql://47.99.85.92:3307" user="tzxylao" password="123456">
</writeHost>
</dataHost>
</mycat:schema>
- 这里我只测试了 mod-long 模式,取模分组
- 在mycat逻辑库环境插入数据
insert into hotnews (id,name) values (1,"tom1");
insert into hotnews (id,name) values (2,"tom2");
insert into hotnews (id,name) values (3,"tom3");
insert into hotnews (id,name) values (4,"tom4");
insert into hotnews (id,name) values (5,"tom5");
结果
1.10.4. 主从配置实战
- 参考我的另一篇实战 https://www.cnblogs.com/sky-chen/p/10053314.html
- 如果报错 sql_mode=only_full_group_by问题
执行以下语句
set sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
- 主要修改schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="mycat" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn3">
<table name="hotnews" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"
rule="mod-long" />
</schema>
<dataNode name="dn1" dataHost="localhost1" database="mycat_test" />
<dataNode name="dn2" dataHost="localhost2" database="mycat_test" />
<dataNode name="dn3" dataHost="localhost3" database="slave_test" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="jdbc:mysql://47.99.85.92:3306" user="tzxylao"
password="123456">
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" dbType="mysql" writeType="0" switchType="1"
dbDriver="jdbc">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="jdbc:mysql://47.99.85.92:3307" user="tzxylao" password="123456">
</writeHost>
</dataHost>
<dataHost name="localhost3" maxCon="1000" minCon="10" balance="0" dbType="mysql" writeType="0" switchType="1"
dbDriver="jdbc">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM3" url="jdbc:mysql://47.99.85.92:3306" user="tzxylao" password="123456">
<readHost host="hostS3" url="jdbc:mysql://47.99.85.92:3307" user="tzxylao" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
- 结果
- 当我关闭主服务器,情况如下,也不能查询
6. 启动主服务器后立刻插入,可以读取到数据,但是查询从服务器,暂时还没有数据,也就是说,刚启动主服务器的时候,主从同步还在连接中,此时读的是主库。当主从连接完成,从库也有了相应数据
7. 接下来测试,关闭从库,马上读取和插入,结果发现,插入可以进行,读取不成功;稍过一会,读取有事成功有时不成功
- 不成功时显示
8. 说明从库挂了,mycat有几率读取主库数据
参考 https://blog.csdn.net/linzhiqiang0316/article/details/79619246