Mycat背景

Mycat的前身是阿里巴巴大名鼎鼎的Cobar,Cobar在开源了一段时间后,就没有再维护了,阿里巴巴放弃了该项目,再加上Cobar在使用过程中也发现存在一些问题。

2013年国内一批开源软件爱好者对Cobar这个项目进行了改进,并命名为Mycat,这就是MyCat的诞生。

MyCat是完全免费开源的,不属于任何商业公司。

Mycat于2014年首次在上海的《中华架构师》大会上对外宣讲,随后越来越多的项目采用了Mycat。

截至2015年11月,超过300个项目采用Mycat,涵盖银行、电信、电子商务、物流、移动应用、O2O的众多领域和公司。

Mycat官网:http://www.mycat.org.cn/ 

Mycat是什么

Mycat是一个开源数据库中间件,是一个实现了MySQL协议的的数据库中间件服务器,我们可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问Mycat,而Mycat再使用MySQL原生(Native)协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,包括SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储;

一般地,Mycat主要用于代理MySQL数据库,虽然它也支持去访问其他类型的数据库;

Mycat的默认端口是8066,一般地,我们可以使用常见的对象映射框架比如MyBatis操作Mycat。

Mycat主要能做什么

1、数据库的读写分离

通过Mycat可以自动实现写数据时操作主数据库,读数据时操作从数据库,这样能有效地减轻数据库压力,也能减轻IO压力。

实现读写分离,当主出现故障后,Mycat自动切换到另一个主上,进而提供高可用的数据库服务,当然我需要部署多主多从的模式

mysql利用中间关系表的操作 mysql中间键_数据库

如果有了Mycat,客户端直接连接Mycat,可以实现读写分离,如果主出现问题,会自动切换到从服务器上

读写分离基于主从复制的基础之上

2、数据库分库分表

分库分表指的是对数据库数据的拆分,分为两种:水平拆分和垂直拆分

2.1、水平切分(横向切分)

根据表中数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库服务器上面

2.2、垂直切分(纵向切分)

按照不同的表来切分到不同的数据库服务器之上

结论

  • 性能有瓶颈了,可以读写分离
  • 数据库容量有瓶颈了,可以分库分表

Mycat环境搭建

1、下载

官网下载上传到linux服务器

找个地方建一个空文件夹

mysql利用中间关系表的操作 mysql中间键_数据库_02

2、解压

tar  –zxvf  Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

3、java语言开发的直接解压即可使用

Tomcat

ZooKeeper

ActiveMQ

Mycat

4、Mycat日常管理命令

4.1、Mycat启动

切换到mycat的bin路径下,执行

./mycat start    重启 ./mycat restart

4.2、Mycat关闭

切换到mycat的bin路径下,执行

./mycat stop

4.3、暂停

./mycat pause

4.4、mycat启动日志:

查看logs/下的wrapper.log和mycat.log可以查看运行时问题和异常。

cat ./logs/wrapper.log

4.5、mycat 应用日志:

cat ./logs/mycat.log

4.6、Mycat命令行(先了解,后面会用到)

登录mycat命令行,使用mysql的命令行工具来操作的:

mysql -umycat -p -P8066 -h127.0.0.1

mycat默认数据访问端口是8066

当我们在linux上使用该命令行登录时,127.0.0.1是我们虚拟机的本地,而不是windows系统的本地

use mycatdb;  进入逻辑库

insert into t_orders(name) values('华为手机');

4.7、MyCat配置文件

4.7.1、server.xml

主要用于配置mycat需要的服务器信息

常用配置:

  • 配置序列生成方式
  • 配置mycat的访问账户和密码
  • 配置mycat逻辑数据库

4.7.2、schema.xml

用于配置的逻辑数据库的映射、表、分片规则、数据结点及真实的数据库信息;

常用配置:

  • 配置逻辑库映射
  • 配置读写结点
  • 配置真实的数据库
  • 配置垂直切分的表

4.7.3、rule.xml

定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有 tableRule 和 function 这两个标签。在具体使用过程中可以按照需求添加 tableRule 和 function

Mycat读写分离

先在从节点查看主从复制是否开启

mysql利用中间关系表的操作 mysql中间键_mysql利用中间关系表的操作_03

配置server.xml文件

为了看的更清晰,可以将配置文件先下载到本地,使用文本编辑工具进行编辑

注意编码方式设置为UTF-8

下载命令:  sz 下载文件名

mysql利用中间关系表的操作 mysql中间键_读写分离_04

上传命令:  rz -y 上传文件名

上传成功后记得打开上传文件看自己修改的配置是否正确;

<?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/">
	<system>
	<property name="useSqlStat">0</property>  <!-- 1为开启实时统计、0为关闭 -->
	<property name="useGlobleTableCheck">0</property>  <!-- 1为开启全加班一致性检测、0为关闭 -->

		<property name="sequnceHandlerType">2</property>
      <!--  <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
        <!--  <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号-->
	<!-- <property name="processorBufferChunk">40960</property> -->
	<!-- 
	<property name="processors">1</property> 
	<property name="processorExecutor">32</property> 
	 -->
		<!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena-->
		<property name="processorBufferPoolType">0</property>
		<!--默认是65535 64K 用于sql解析时最大文本长度 -->
		<!--<property name="maxStringLiteralLength">65535</property>-->
		<!--<property name="sequnceHandlerType">0</property>-->
		<!--<property name="backSocketNoDelay">1</property>-->
		<!--<property name="frontSocketNoDelay">1</property>-->
		<!--<property name="processorExecutor">16</property>-->
		<!--
			<property name="serverPort">8066</property> <property name="managerPort">9066</property> 
			<property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> 
			<property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
		<!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志-->
		<property name="handleDistributedTransactions">0</property>
		
			<!--
			off heap for merge/order/group/limit      1开启   0关闭
		-->
		<property name="useOffHeapForMerge">1</property>

		<!--
			单位为m
		-->
		<property name="memoryPageSize">1m</property>

		<!--
			单位为k
		-->
		<property name="spillsFileBufferSize">1k</property>

		<property name="useStreamOutput">0</property>

		<!--
			单位为m
		-->
		<property name="systemReserveMemorySize">384m</property>


		<!--是否采用zookeeper协调切换  -->
		<property name="useZKSwitch">true</property>


	</system>
	
	<!-- 全局SQL防火墙设置 -->
	<!-- 
	<firewall> 
	   <whitehost>
	      <host host="127.0.0.1" user="mycat"/>
	      <host host="127.0.0.2" user="mycat"/>
	   </whitehost>
       <blacklist check="false">
       </blacklist>
	</firewall>
	-->
	
	<user name="mycat">
		<property name="password">mycat</property>
		<property name="schemas">mycat001</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">mycat001</property>
		<property name="readOnly">true</property>
	</user>

</mycat:server>

schema.xml的配置,都有注释,每个标签的含义

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<!--  schema 标签用户指定一个逻辑库 
		属性name为逻辑库名称 自定义 需和server.xml中对应
			checkSQLschema 是否检查SQL语法 (建议写false不检查)
			sqlMaxLimit SQL语句的最大分页数量
			dataNode 用于指定物理库的数据节点映射的,会将某些物理库中的所有表全部映射到这个逻辑库中	
    -->
	<schema name="mycat001" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
		<!--
			talbe标签 用于映射某个表到当前逻辑库中,应用于分库分表中的水平拆分和垂直拆分
		-->
	</schema>
	<!-- dataNode 用于指定数据库节点
	     属性	name  为数据节点名称 被schema和table标签的dataNode属性所引用
			dataHost  用于指定这个物理库的读写节点
			database  用于指定物理库的具体名称
		/> -->
	<dataNode name="dn1" dataHost="localhost1" database="mycat001" />
	<!--
		dataHost标签 用于配置读写节点
		属性	name 为读写节点的名称,自定义取值。被dataNode标签的dataHost属性所引用
			maxCon 配置最大连接数
			minCon 配置最小连接数
			balance 配置负载均衡策略  取值为0,1,2,3
			writeType 过期了不用
			dbType  用于指定数据库的类型 比如mysql或oracle等等
			dbDriver 取值为native表示为mysql原生协议只有dbType为mysql时可以使用 或 jdbc可以用于连接任何一个支持JDBC的数据库
			switchType 故障切换类型 取值为-1 1 2 3  不同的故障切换类型需要不同的心跳机制
			laveThreshold  指定从节点的数量上限
	-->
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- can have multi write hosts -->
		<!--   writeHost 配置写节点
			属性  	host 为写节点名称 自定义命名需要唯一
					url 为写节点的IP及端口
					user 为写节点的用户名
					password 为写节点的密码
					MyCat 利用这个信息连接主库完成写操作	
		 -->
		<writeHost host="hostM1" url="192.168.245.71:3306" user="root"
				   password="12345678">
			<!-- can have multi read hosts -->
			<!--  readHost 配置读节点
				属性    host 为读节点名称 自定义命名需要唯一
						url 为读节点的IP及端口
						user 为读节点的用户名
						password 为读节点的密码
						MyCat 利用这个信息连接主库完成读操作
			-->
			<readHost host="hostS1" url="192.168.245.72:3306" user="root" password="12345678" />
		</writeHost>
	</dataHost>
</mycat:schema>

开启mycat服务(从库)

/usr/local/mycat/bin/mycat start 

mysql利用中间关系表的操作 mysql中间键_数据库_05

出现starting说明成功 

也可以查看一下进程是否成功

mysql利用中间关系表的操作 mysql中间键_数据库_06

成功之后我们就可以链接数据库

mysql利用中间关系表的操作 mysql中间键_mysql_07

mysql利用中间关系表的操作 mysql中间键_mysql_08

mysql利用中间关系表的操作 mysql中间键_xml_09

 这里进行测试,新建一个数据表

mysql利用中间关系表的操作 mysql中间键_xml_10

mysql利用中间关系表的操作 mysql中间键_mysql利用中间关系表的操作_11

 我们还可以添加数据试一试

mysql利用中间关系表的操作 mysql中间键_读写分离_12

去刷新一下主库和从库

mysql利用中间关系表的操作 mysql中间键_读写分离_13

读写分离的话,因为我们权限给的是root的,所以呢在从库也能添加进去数据,但是主库刷新的时候同步不过去,但是主库添加了从库可以同步过来。在读取数据的时候,如果主库没有从库有的,它读到的是从库的。大家也可以去从库添加数据然后主库没有,再查询这条语句试试,也是可以查询出来的,因为我试过了没有截图,所以就在这里做了一个总结。大家可以去尝试一下