本文共 6416 字,大约阅读时间需要 21 分钟。
MYCAT基于阿里开源的Cobar产品而研发,Java语言编写的数据库中间件,使用NIO重构了网络模块,并且优化了Buffer内核,增强了聚合,Join等基本特性,实现了MySql协议的服务器,其核心功能是分库分表,配合数据库的主从模式还可以实现读写分离。类似的中间件还有电信udal的插件dbproxy、淘宝的TDDL等,使用者直接连接mycat,
mysql底层对于他们是透明的。
介绍一些mycat相关概念:
逻辑上的切分,在物理层面使用分库(database)、分表(table)实现切分。
(1)纵向切分/垂直切分
分库
单库不能解决大规模并发写入的问题,因此会建立定义数据库 workDB、商品数据库 payDB、用户数据库 userDB、日志数据库 logDB
优点:
减少增量数据写入时的锁对查询的影响。
由于单表数量下降,常见的查询操作由于减少了需要扫描的记录,使得单表单次查询所需检索的行数变少,减少了磁盘IO、时延变短。
缺点:
无法解决单表数据量太大的问题。
(2)横向切分/水平切分
分表
当一个表中的数据量过大时,我们可以把该表的数据按照某种规则,进行划分,然后存储到多个结构相同的表上。
优点:
单表的并发能力提高了,磁盘的I/O性能也提高了
如果出现高并发的话,总表可以根据不同的查询,将并发压力发到不同的小表里。
缺点:
无法实现表连接查询
MyCat中定义的database是逻辑上存在的,使用者能操作,但底层存储层面不存在,是针对纵向切分提供的概念
MyCat中定义的table,是逻辑上存在,物理上不存在的,是针对横向切分提供的概念
物理MySql存放的主机地址,可以使用主机名,IP,域名定义
配置物理的database,数据保存的物理节点就是database
按照某种业务规则把数据分到某个分片的规则就是分片规则,如取模,哈希等
主机名 | ip | 端口 | 备注 |
shard12 | 172.16.23.170 | 3306,8066,9066 | mgr当前主节点(读写),mycat安装节点,8066:服务端口,9066:管理端口 |
catdb | 172.16.23.171 | 3306 | mgr当前从节点1(只读),若shard12有问题,此节点会接管主节点角色 |
rac2 | 10.45.53.31 | 3306 | mgr当前从节点2(只读) |
(1)下载安装Mycat 1.6.7.4
(这个1.6最初版本的rule不能实现库内分表)
cd /mysql
tar -xvf /soft/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
mycat安装完成后,目录如下:
bin mycat命令,启动、重启、停止等
catlet catlet为Mycat的一个扩展功能
conf Mycat 配置信息,重点关注
lib Mycat引用的jar包,Mycat是java开发的
logs 日志文件,包括Mycat启动的日志(wrapper.log)和运行的日志(mycat.log)
Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:
server.xml Mycat的配置文件,设置账号、参数等
schema.xml Mycat对应的物理数据库和数据库表的配置
rule.xml Mycat分片(分库分表)规则,直接用默认的就好
(2)配置文件修改
cd mycat/conf
root@shard12[/mysql/mycat1.6.7.4/conf]#cat server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="useSqlStat">0</property> <!-- 1为开启实时统计、0为关闭 -->
<property name="useGlobleTableCheck">0</property> <!-- 1为开启全加班一致性检测、0为关闭 -->
<property name="ignoreUnknownCommand">0</property><!-- 0遇上没有实现的报文(Unknown command:),就会报错、1为忽略该报文 -->
<property name="serverPort">8066</property> <property name="managerPort">9066</property>
<property name="sequnceHandlerType">2</property>
<property name="useZKSwitch">false</property>
<property name="charset">utf8</property>
<!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena-->
<property name="processorBufferPoolType">0</property>
<property name="useOffHeapForMerge">1</property>
<property name="memoryPageSize">1m</property>
</system>
<user name="root"> <!--登录mycat的用户 -->
<property name="password">123</property> <!--密码 -->
<property name="schemas">MYCAT</property> <!--逻辑schema库名 -->
</user>
</mycat:server>
注:server.xml的schema名需要大写,否则报schema mycat not exist
root@shard12[/mysql/mycat1.6.7.4/conf]#cat 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都有company表的全部记录 -->
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
<!-- 单片表 ,datanode是dn1 -->
<table name="test" primaryKey="ID" autoIncrement="true" dataNode="dn1" rule="rule1" />
<!-- 库内分表,dn1内分表,分表规则是取模,part1(余数0),part2(余数1),part3(余数2) -->
<table name="part" primaryKey="ID" autoIncrement="true" dataNode="dn1" subTables="part$1-3" rule="mod-long" />
<!-- 分片表,每个datanode只有new表的部分记录,分片规则是mod取模 -->
<table name="new" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="mod-long" />
</schema>
<!-- 定义dn1,dn2,dn3,datahost是下面定义的localhost1,分别对应手动创建的db1,db2,db3 -->
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost1" database="db2" />
<dataNode name="dn3" dataHost="localhost1" database="db3" />
<!-- 定义localhost1,整合了mgr的三个节点端口及ip,定义了写节点和读节点等 -->
<!-- 定义localhost1,整合了mgr的三个节点端口及ip,定义了写节点和读节点等 -->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="shard12" url="172.16.23.170:3306" user="root"
password="123">
<!-- can have multi read hosts -->
<readHost host="catdb" url="172.16.23.171:3306" user="root" password="123" />
<readHost host="rac2" url="10.45.53.31:3306" user="root" password="123" />
</writeHost>
<writeHost host="catdb" url="172.16.23.171:3306" user="root" password="123">
<readHost host="rac2" url="10.45.53.31:3306" user="root" password="123" />
</writeHost>
</dataHost>
</mycat:schema>
Balance参数设置:
1. balance=“0”, 所有读操作都发送到当前可用的writeHost上
2. balance=“1”,所有读操作都随机的发送到readHost
3. balance=“2”,所有读操作都随机的在writeHost、readhost上分发
WriteType参数设置:
1. writeType=“0”, 所有写操作都发送到可用的writeHost上
2. writeType=“1”,所有写操作都随机的发送到readHost
3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发
readHost是从属于writeHost的,即意味着它从那个writeHost获取同步数据,因此,当它所属的writeHost宕机了,则它也不会再参与到读写分离中来,这是因为此时,它的数据已经“不可靠”了;
基于这个考虑,mycat若想在主节点宕机的情况下,从节点还能读取数据,则需要在Mycat里配置为两个writeHost并设置banlance=1
(3)启动mycat
cd /mysql/mycat/bin/
./mycat start
(4)登录mgr主节点,创建分库db1-db3
mysql -uroot -p123 -P 3306 -h 172.16.23.170
create database db1;
create database db2;
create database db3;
(5)登录mgr主节点,创建分表part1-part3
mysql -uroot -p123 -P 3306 -h 172.16.23.170
create table part1(id int primary key,pname varchar(10));
create table part2(id int primary key,pname varchar(10));
create table part3(id int primary key,pname varchar(10));
(6)登录mycat,创建逻辑表
逻辑库mycat是自动建立的,底层没有mycat库,底层只有db1,db2,db3
mysql -uroot -p123 -P 8066 -h 172.16.23.170
create table company(id int primary key,cname varchar(10));
create table test(id int primary key,tname varchar(10));
create table part(id int primary key,pname varchar(10));
create table new(id int primary key,nname varchar(10));
(7)插入数据,查看数据分片分表的情况
若想新增分片表,需要修改配置文件schema.xml,可以重启mycat生效,也可以登录管理端口reload config生效
mysql -uroot -p123 -P 9066 -h 172.16.23.170
reload @@config;或reload @@config_all;
(HY000): Reload config failure 说明配置文件配置有误
可以看出分片表跨越了多个分片整合结果
可以看出库内分表跨越了多个分表整合结果
insert分片表时,即使是全部字段都有值,也需要在指定列名,否则报错
全局表insert可以不指定列明
for i in `seq 1 10`; do mysql -h 172.16.23.170 -P8066 -uroot -p123 -e "select @@hostname;"; done
将当前mgr主节点mysql进程停掉,主节点由catdb主机接管(接管顺序参照 主节点failover测试)
此时由于schema.xml中定义了两个writehost,catdb开始担任writehost角色,mycat依旧可读写,现在的读节点只剩rac2
若此时恢复shard12主机的mysql进程和组复制进程,catdb还是writehost,shard12和catdb接管读负载均衡的任务
转载地址:http://alwmf.baihongyu.com/