什么是mycat?
MyCat是一款由阿里Cobar演变而来的用于支持数据库,读写分离、分表分库的分布式中间件。
Mycat支持Oracle、MSSQL、MYSQL、PG、DB2关系型数据库,同时也支持MongDB等非关系型数据库。
MyCat原理MyCat主要是通过SQL的拦截,然后经过一定规则的分片解析、路由分析、读写分离分析、缓存分析等,然后将SQL发给后端真实的数据块,并将返回的结果做适当处理返回给客户端。
基于mycat实现读写分离
读写分离,简单地说就是把数据库的读和写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。主数据库进行写操作后,数据及时同步到所读的数据库,尽可能保证读、写数据库的数据一致,比如Mysql的主从复制、oracle的data guard、SQL Server的复制订阅等。
mycat原理:会拦截客户端的所有jdbc请求,进行转发到不同的数据库
Linux环境安装MyCat实现读写分离
1、上传安装Mycat-server-1.6.5-release-20180122220033-linux.tar
2、解压安装包tar –zxvf
3、配置schema.xml和server.xml
4、客户端连接端口号:8066
配置文件介绍:
文件 | 说明 |
---|---|
server.xml | Mycat的配置文件,设置账号、参数等 |
schema.xml | Mycat对应的物理数据库和数据库表的配置 |
rule.xml | Mycat分片(分库分表)规则 |
schema.xml配置文件
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- TESTDB1 是mycat的逻辑库名称,链接需要用的 -->
<schema name="mycat_testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
<!-- database 是MySQL数据库的库名 -->
<dataNode name="dn1" dataHost="localhost1" database="test" />
<!--
dataNode节点中各属性说明:
name:指定逻辑数据节点名称;
dataHost:指定逻辑数据节点物理主机节点名称;
database:指定物理主机节点上。如果一个节点上有多个库,可使用表达式db$0-99, 表示指定0-99这100个数据库;
dataHost 节点中各属性说明:
name:物理主机节点名称;
maxCon:指定物理主机服务最大支持1000个连接;
minCon:指定物理主机服务最小保持10个连接;
writeType:指定写入类型;
0,只在writeHost节点写入;
1,在所有节点都写入。慎重开启,多节点写入顺序为默认写入根据配置顺序,第一个挂掉切换另一个;
dbType:指定数据库类型;
dbDriver:指定数据库驱动;
balance:指定物理主机服务的负载模式。
0,不开启读写分离机制;
1,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡;
2,所有的readHost与writeHost都参与select语句的负载均衡,也就是说,当系统的写操作压力不大的情况下,所有主机都可以承担负载均衡;
-->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 可以配置多个主从 -->
<writeHost host="hostM1" url="192.168.212.202:3306" user="root" password="root">
<!-- 可以配置多个从库 -->
<readHost host="hostS2" url="192.168.212.203:3306" user="root" password="root" />
</writeHost>
</dataHost>
</mycat:schema>
server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License. - You
may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
- - Unless required by applicable law or agreed to in writing, software -
distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License for the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<!-- 读写都可用的用户 -->
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">mycat_testdb</property>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<!-- 只读用户 -->
<user name="user">
<property name="password">user</property>
<property name="schemas">mycat_testdb</property>
<property name="readOnly">true</property>
</user>
</mycat:server>
192.168.212.206_root连接的是mycat,然后mycat根据schema.xml配置文件中的dataNode中配置的数据库,可以打开对应的库,然后根据server.xml中配置的不同用户实现不同的读写权限。
当你连接mysql进行添加表的操作时,主从表也会跟着改变
SpringBoot动态数据源切换原理
底层是通过aop技术去判断业务逻辑层的方法前缀,如果是select前缀,就走读的数据源,否则就走写的数据源
SpringBoot整合读写分离
**
配置多个数据源
@Aspect
@Component
@Lazy(false)
@Order(0) // Order设定AOP执行顺序 使之在数据库事务上先执行
public class SwitchDataSourceAOP {
// 这里切到你的方法目录
@Before("execution(* com.mayikt.service.*.*(..))")
public void process(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
if (methodName.startsWith("get") || methodName.startsWith("count") || methodName.startsWith("find")
|| methodName.startsWith("list") || methodName.startsWith("select") || methodName.startsWith("check")) {
// 读
DataSourceContextHolder.setDbType("selectDataSource");
} else {
// 切换dataSource
DataSourceContextHolder.setDbType("updateDataSource");
}
}
}
分表分库
数据库集群会产生哪些问题?
1.自增id问题
2.数据关联查询问题(水平拆分)
3.数据同步问题
2.数据库集群的话,如果自动增长id产生重复的话?如何解决?
1.UUID形式(不是很推荐) 如果是oracle比较推荐
2.设置数据库的步长
可以通过SHOW VARIABLKES LIKE ‘auto_inc%’查询步长
如下图表示起始值为1,步长为1
可以手动设置:
修改自增的步长
SET @@auto_increment increment=10
修改起始值
SET @@auto_incrementoffset=5
这样就不会导致id重复
但是有缺点,无法扩展新的mysql,不然生成步长的规则可能会发生变化。
数据库分表分库
在数据库分表分库原则中,遵循两个设计理念 垂直拆分、水平拆分
垂直拆分:
就是根据不同的业务,拆分成不同的数据库,比如会员数据库,订单数据库,支付数据库、消息数据库等。
大型互联网电商平台、微服务项目架构
优点:拆分后业务清晰,拆分规则明确,系统之间整合或扩展容易。
缺点:部分业务表无法join,只能通过接口方式解决,提高了系统复杂度存在分布式事务问题
水平拆分:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆分到不同的数据库中。
该方式提高了系统的稳定性跟负载能力,但是跨域join性能较差。
mycat实现水平分片策略
mycat支持10种分片策略
1.分片枚举算法
这种规则适合于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国的省分区县固定的,这类业务使用这一规则。
分片枚举算法就是根据不同的枚举(常量),进行分类存储。
应用场景:可以使用分片枚举实现根据地区进行分类存储到不同数据库进行存放。
环境搭建:
1.先定义枚举(地区),每个地方指定数据库存放位置
2.
存入:根据匹配的规则来,如果输入的该列名称等于配置的枚举文件,会自动存入响应的数据库
读取:根据分片字段查询即可
2.取模算法
根据id求模进行分片
如果你是查询所有的情况下,他会在每个库查一下,日志中会存在三条语句,然后把所有的结果集整合
根据id查询的话就会取模,然后到对应的数据库去查询
如果是根据非分片字段查询,select*from user_info where name=”name3”,它就会去三个数据库进行查询
select * from user_info limit 0,2,会出现什么结果?
他会去三个数据库分别查询汇总,然后随机返回
如果排序?
select * from user_info order by id desc limit 0,2
先汇总,在排序,找出最大的
先在db1里面查询两条数据,然后再到db2,和db3随机取一条