mysql基于mycat实现读写分离
mycat数据库代理中间件
Mycat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理(类似于Mysql Proxy),用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里
后端可以支持MySQL、SQLServer、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种NoSQL方式的存储
mycat特点:
- 支持SQL92标准
- 遵守MySQL 原生协议,跨语言,跨平台,跨数据库的通用中间件代理
- 基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluster集群
- 支持Galera for MySQL集群,Percona Cluster或者MariaDB cluster
- 基于Nio实现,有效管理线程,高并发问题
- 支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数,支持跨库分页
- 支持单库内部任意join,支持跨库2表join,甚至基于caltlet的多表join
- 支持通过全局表,ER关系的分片策略,实现了高效的多表join查询
- 支持多租户方案
- 支持分布式事务(弱xa)
- 支持全局序列号,解决分布式下的主键生成问题
- 分片规则丰富,插件化开发,易于扩展
- 强大的web,命令行监控
- 支持前端作为mysq通用代理,后端JDBC方式支持Oracle、DB2、SQL Server 、 mongodb
- 支持密码加密
- 支持服务降级
- 支持IP白名单
- 支持SQL黑名单、sql注入攻击拦截
- 支持分表(1.6)
- 集群基于ZooKeeper管理,在线升级,扩容,智能优化,大数据处理(2.0开发版)
mycat原理:
请求到达时,把sql语句拦截,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户
mycat使用场景:
Mycat适用场景
- 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换
- 分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片
- 多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化
- 报表系统,借助于Mycat的分表能力,处理大规模报表的统计
- 替代Hbase,分析大数据
- 作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择
- Mycat长期路线图
- 强化分布式数据库中间件的方面的功能,使之具备丰富的插件、强大的数据库智能优化功能、全面的系统监控能力、以及方便的数据运维工具,实现在线数据扩容、迁移等高级功能
- 进一步挺进大数据计算领域,深度结合Spark Stream和Storm等分布式实时流引擎,能够完成快速的巨表关联、排序、分组聚合等 OLAP方向的能力,并集成一些热门常用的实时分析算法,让工程师以及DBA们更容易用Mycat实现一些高级数据分析处理功能
Mycat不适合场景:
- 设计使用Mycat时有非分片字段查询,请慎重使用Mycat,可以考虑放弃!
- 设计使用Mycat时有分页排序,请慎重使用Mycat,可以考虑放弃!
- 设计使用Mycat时如果要进行表JOIN操作,要确保两个表的关联字段具有相同的数据分布,否则请
- 慎重使用Mycat,可以考虑放弃!
- 设计使用Mycat时如果有分布式事务,得先看是否得保证事务得强一致性,否则请慎重使用Mycat,可以考虑放弃!
mycat高可用搭配:
在生产环境中, Mycat节点最好使用双节点, 即双机热备环境, 防止Mycat这一层出现单点故障
- Keepalived + Mycat + Mysql
- Keepalived + LVS + Mycat + Mysql
- Keepalived + Haproxy + Mycat + Mysql
使用mycat:
依赖于jdk
github下载:https://github.com/MyCATApache/Mycat-Server
下载地址: http://dl.mycat.org.cn/ #以前可用,博主现在写本文时似乎不可用
mycat程序:
端口:8066
默认用户: root
默认密码: 123456
mycat [子命令]
console
start
stop
restart
status
dump
mycat安装目录结构:
目录 | 说明 |
---|---|
bin | mycat命令,启动、重启、停止等 |
catlet | catlet为Mycat的一个扩展功能 |
conf | Mycat 配置信息,重点关注 |
lib | Mycat引用的jar包,Mycat是java开发的 |
logs | 日志文件,包括Mycat启动的日志和运行的日志 |
version.txt | mycat版本说明 |
logs目录内容:
- wrapper.log mycat启动日志
- mycat.log mycat详细工作日志
常用的配置文件:
- server.xml : Mycat软件本身相关的配置文件,设置账号、参数等
- schema.xml : Mycat对应的物理数据库和数据库表的配置,读写分离、高可用、分布式策略定制、节点控制
- rule.xml : Mycat分片(分库分表)规则配置文件,记录分片规则列表、使用方法等
server.xml文件解读:
存放Mycat软件本身相关的配置文件,比如:连接Mycat的用户,密码,数据库名称等
标签段 | 说明 |
---|---|
<user> | 配置用户的选项,登录mycat用户,与mysql无关。下面几个都是子标签段 |
password | 密码 |
schemas | 数据库名,和schema.xml中的配置关联,多个用逗号分开,例如:db1,db2 |
privileges | 配置用户针对表的增删改查的权限 |
readOnly | 逻辑库的权限。false关闭只读(默认),true开启 |
注意:
- server.xml文件里登录mycat的用户名和密码可以任意定义,这个账号和密码是为客户机登录mycat时使用的账号信息(只是登录mycat的账户,与mysql无关)
- 逻辑库名(也就是登录mycat后显示的库名,切换这个库之后,显示的就是代理的真实mysql数据库的表)要在schema.xml里面也定义,否则会导致mycat服务启动失败(mycat这里显示一个库,虚拟出来的,要关联mysql的真实库)
- 如果定义多个标签,即设置多个连接mycat的用户名和密码,那么就需要在schema.xml文件中定义多个对应的库
schema.xml文件解读:
最主要的配置项,此文件关联mysql读写分离策略,读写分离、分库分表策略、分片节点都是在此文件中配置的
MyCat作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的MySQL物理服务器,此文件就是用来连接MySQL服务器的
标签段 | 说明 |
---|---|
schema | 数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应 |
dataNode | 分片信息,也就是分库相关配置 |
dataHost | 唯一性。真正存储数据的数据库,定义读、写主机 |
writeHost | 属于datahost标签,写数据库定义 |
readOnly | 属于writehost标签,读数据库定义 |
schema标签子参数:
name | 与server.xml中的schema对应 |
checkSQLschema | 数据库前缀相关设置,这里设false,默认true |
qlMaxLimit | 查询时默认的limit,避免查询全表 |
randomDataNode | 为随机分页 |
table标签子参数:
name | 表名,物理数据库中表名 |
dataNode | 表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name |
primaryKey | 主键字段名,自动生成主键时需要设置 |
autoIncrement | 是否自增 |
rule | 分片规则名,具体规则下文rule详细介绍 |
dataNode标签子参数:
name | 节点名,与table中dataNode对应 |
datahost | 物理数据库名,与datahost中name对应 |
database | 对应mysql中的数据库 |
dataHost标签子参数:
name | 物理数据库名,与dataNode中dataHost对应 |
balance | 均衡负载模式 |
writeType | 写入方式 |
dbType | 真实数据库是哪个 |
heartbeat | 心跳检测语句,注意语句结尾的分号要加 |
maxCon | 指定每个实例连接池的最大连接 |
minCon | 每个读写实例连接池的最小连接 |
balance参数的配置选项:
0 | 关闭读写分离,所有读都发往可用的writeHost |
1 | 一般用此模式,读请求随机分发到当前writeHost对应的readHost和standby的writeHost上。即全部的readHost与stand by writeHost参与select语句的负载均衡。简单的说,当双主双从模式(M1 ->S1 , M2->S2),正常情况下, M2,S1, S2 都参与 select语句的负载均衡 |
2 | 读请求随机分发到当前dataHost内所有的writeHost和readHost上。即所有读操作都随机的在writeHost、 readhost 上分发 |
3 | 读请求随机分发到当前writeHost对应的readHost上执行, writerHost不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有 |
writeHost和readHost 标签使用:
- 这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。有从属关系,前者配置在:dataHost,后者配置在:writeHost
- 在一个dataHost内可以定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去
mycat实现mysql读写分离:
先搭建主从复制,再做读写分离
1)B主机创建master
yum install -y mariadb-server
vim /etc/my.cnf
[mysqld]
server-id=1
log-bin
systemctl restart mariadb
mysql -e 'grant replication slave,replication client on *.* to copy@"%" identified by "123456"'
2)C主机创建slave
yum install -y mariadb-server
vim /etc/my.cnf
[mysqld]
server-id=2
log-bin
systemctl restart mariadb
mysql
->CHANGE MASTER TO
MASTER_HOST='2.2.2.12',
MASTER_USER='copy',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_USE_GTID=current_pos;
start slave;
3)A主机安装mycat、数据库客户端
yum install -y mariadb java-1.8.0-openjdk
tar xf mycat-xxx.gz -C /data ;cd /data/mycat
echo 'PATH=/data/mycat/bin:$PATH' > /etc/profile.d/mycat.sh &&. /etc/profile.d/mycat.sh
#启动mycat
mycat start
tail logs/wrapper.log #有successfull为成功
#测试登录mycat
mysql -uroot -p123456 -h2.2.2.32 -P8066 #mycat安装后自带的默认账号密码,连接的虚拟库
->show databases;
4)A主机修改mycat的配置
修改mycat连接信息: server.xml
也就是用于登录mycat的账户信息,TESTDB就是mycat程序虚拟的数据库,关联mysql真实数据库后,访问TESTDB就能看到mysql的库
#找到<user name="root" defaultAccount="true">
vim /data/mycat/conf/server.xml
<user name="root" defaultAccount="true">
<property name="password">123456</property>
#虚拟数据库定义,对应schema,xml的配置(默认TESTDB)
<property name="schemas">TESTDB</property>
修改读写分离策略: schema.xml
懒得修改的话,可以直接把配置文件清空,把我的配置模板直接复制进去
vim /data/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1" ></schema>
#database等于mysql中的真实数据库
<dataNode name="dn1" dataHost="localhost1" database="hj" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="host1" url="2.2.2.12:3306" user="root" password="123456">
#读主机必须嵌套在写主机标签内,因为读和写是从属关系
<readHost host="host2" url="2.2.2.22:3306" user="root" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
#mycat重启
mycat restart
5)在master库中授权mycat可以root登录
从库不用创建,因为会同步该用户
#schema.xml的写、读定义什么用户就授权什么
mysql -e 'grant all on *.* to root@"%" identified by "123456" with grant option'
6)在mycat主机上测试,是否使用了读写分离
可用通用日志查看sql结果,判断sql调度到哪个节点执行,master、slave都要开启
#在master上开启通用日志,并监测
mysql
->show variables like 'general_log';
set global general_log=1; \q
tail -f /var/lib/mysql/主机名.log
#在slave上开启通用日志,并监测
mysql
->show variables like 'general_log';
set global general_log=1; \q
tail -f /var/lib/mysql/主机名.log
#在mycat主机上测试
mysql -uroot -p123456 -h2.2.2.32 -P8066
->use TESTDB
insert t1 values('8','789');
select * from t1;
select @@server_id;
select @@hostname;
插入数据时,master节点的通用日志中记录
查询数据时,没有在master执行,而是在slave节点返回的数据