登录

用Mycat 学会数据库读写分离、分表分库

高并发 热门
0 1522

安装

Mycat官网:http://www.mycat.io/ 可以了解下Mycat的背景和应用情况,这样使用起来比较有信心。

Mycat下载地址:http://dl.mycat.io/ 官网有个文档,属于详细的介绍,初次入门,看起来比较花时间。

下载: 建议大家选择 1.6-RELEASE 版本,毕竟是比较稳定的版本。

安装: 根据不同的系统选择不同的版本。包括linux、windows、mac作者考虑还是非常周全的,当然,也有源码版的。(ps:源码版的下载后,只要配置正确,就可以正常运行调试,这个赞一下。)

Mycat的安装其实只要解压下载的目录就可以了,非常简单。 安装完成后,目录如下:

0001yle="max-width:100%;">

配置

Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:

0002yle="max-width:100%;">

Mycat的架构其实很好理解,Mycat是代理,Mycat后面就是物理数据库。和Web服务器的Nginx类似。对于使用者来说,访问的都是Mycat,不会接触到后端的数据库。

我们现在做一个主从、读写分离,简单分表的示例。结构如下图:

0003yle="max-width:100%;">

Mycat作为主数据库中间件,肯定是与代码弱关联的,所以代码是不用修改的,使用Mycat后,连接数据库是不变的,默认端口是8066。连接方式和普通数据库一样,如:jdbc:mysql://192.168.0.2:8066/

server.xml

示例


yle="max-width:100%;overflow-x:auto;"><user name="test">
		<property name="password">test</property>  
    	<property name="schemas">lunch</property>  
    	<property name="readOnly">false</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>

重点关注下面这段,其他默认即可。

0004yle="max-width:100%;">

我这里配置了一个账号test 密码也是test针对数据库lunch读写权限都有,没有针对表做任何特殊的权限。

schema.xml schema.xml是最主要的配置项,首先看我的配置文件。


yle="max-width:100%;overflow-x:auto;"><?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 数据库配置,与server.xml中的数据库对应 -->
	<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
		<table name="lunchmenu" dataNode="dn1"  />
		<table name="restaurant" dataNode="dn1"  />
		<table name="userlunch" dataNode="dn1"  />
		<table name="users" dataNode="dn1"  />
		<table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1dn2"  rule="mod-long" />

		
	</schema>

<!-- 分片配置 -->
	<dataNode name="dn1" dataHost="test1" database="lunch" />
	<dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理数据库配置 -->
	<dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
		<heartbeat>select user();</heartbeat>
		<writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">	
		</writeHost>
	</dataHost>

	<dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
		<heartbeat>select user();</heartbeat>
		<writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">	
		</writeHost>
	</dataHost>

</mycat:schema>

0005yle="max-width:100%;">

每个节点的属性逐一说明:

0006yle="max-width:100%;">

0007yle="max-width:100%;">

应用场景

数据库分表分库

配置如下:


yle="max-width:100%;overflow-x:auto;"><?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 数据库配置,与server.xml中的数据库对应 -->
	<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
		<table name="lunchmenu" dataNode="dn1"  />
		<table name="restaurant" dataNode="dn1"  />
		<table name="userlunch" dataNode="dn1"  />
		<table name="users" dataNode="dn1"  />
		<table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1dn2"  rule="mod-long" />

		
	</schema>

<!-- 分片配置 -->
	<dataNode name="dn1" dataHost="test1" database="lunch" />
	<dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理数据库配置 -->
	<dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
		<heartbeat>select user();</heartbeat>
		<writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">	
		</writeHost>
	</dataHost>

	<dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
		<heartbeat>select user();</heartbeat>
		<writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">	
		</writeHost>
	</dataHost>

</mycat:schema>


我在192.168.0.2、192.168.0.3均有数据库lunch。

lunchmenu、restaurant、userlunch、users这些表都只写入节点dn1,也就是192.168.0.2这个服务,而dictionary写入了dn1、dn2两个节点,也就是192.168.0.2、192.168.0.3这两台服务器。分片的规则为:mod-long。

主要关注rule属性,rule属性的内容来源于rule.xml这个文件,Mycat支持10种分表分库的规则,基本能满足你所需要的要求,这个必须赞一个,其他数据库中间件好像都没有这么多。

table中的rule属性对应的就是rule.xml文件中tableRule的name具体有哪些分表和分库的实现,建议还是看下文档。我这里选择的mod-long就是将数据平均拆分。因为我后端是两台物理库,所以rule.xml中mod-long对应的function count为2,见下面部分代码:


yle="max-width:100%;overflow-x:auto;"><tableRule name="mod-long">
		<rule>
			<columns>id</columns>
			<algorithm>mod-long</algorithm>
		</rule>
	</tableRule>
	
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		<!-- how many data nodes -->
		<property name="count">2</property>
	</function>


数据库读写分离

配置如下:


yle="max-width:100%;overflow-x:auto;"><?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 数据库配置,与server.xml中的数据库对应 -->
	<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
		<table name="lunchmenu" dataNode="dn1"  />
		<table name="restaurant" dataNode="dn1"  />
		<table name="userlunch" dataNode="dn1"  />
		<table name="users" dataNode="dn1"  />
		<table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1"  />

		
	</schema>

<!-- 分片配置 -->
	<dataNode name="dn1" dataHost="test1" database="lunch" />


<!-- 物理数据库配置 -->
	<dataHost name="test1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql" dbDriver="native">
		<heartbeat>select user();</heartbeat>
		<writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">	
		<readHost host="hostM1" url="192.168.0.3:3306" user="root" password="123456">	
		</readHost>
		</writeHost>
	</dataHost>


</mycat:schema>

这样的配置与前一个示例配置改动如下: 删除了table分配的规则以及datanode只有一个 datahost也只有一台,但是writehost总添加了readhostbalance改为1,表示读写分离。 以上配置达到的效果就是102.168.0.2为主库,192.168.0.3为从库。

注意:Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhost,这个问题当时候我纠结了好久,数据写入writehost后,readhost一直没有数据,以为是自己配置的问题,后面才发现Mycat就没有实现主从复制的功能,毕竟数据库本身自带的这个功能才是最高效稳定的。

至于其他的场景,如同时主从和分表分库也是支持的了,只要了解这个实现以后再去修改配置,都是可以实现的。而热备及故障专业官方推荐使用haproxy配合一起使用,大家可以试试。

使用

Mycat的启动也很简单,启动命令在Bin目录:


yle="max-width:100%;overflow-x:auto;">##启动
mycat start

##停止
mycat stop

##重启
mycat restart


如果在启动时发现异常,在logs目录中查看日志。

  • wrapper.log 为程序启动的日志,启动时的问题看这个
  • mycat.log 为脚本执行时的日志,SQL脚本执行报错后的具体错误内容查看这个文件。mycat.log是最新的错误日志,历史日志会根据时间生成目录保存。

mycat启动后,执行命令不成功,可能实际上配置有错误,导致后面的命令没有很好的执行。

Mycat带来的最大好处就是使用是完全不用修改原有代码的,在mycat通过命令启动后,你只需要将数据库连接切换到Mycat的地址就可以了。如下面就可以进行连接了:

yle="max-width:100%;overflow-x:auto;">mysql -h192.168.0.1 -P8806 -uroot -p123456

连接成功后可以执行sql脚本了。 所以,可以直接通过sql管理工具(如:navicat、datagrip)连接,执行脚本。我一直用datagrip来进行日常简单的管理,这个很方便。

Mycat还有一个管理的连接,端口号是9906.

yle="max-width:100%;overflow-x:auto;"> mysql -h192.168.0.1 -P9906 -uroot -p123456

连接后可以根据管理命令查看Mycat的运行情况,当然,喜欢UI管理方式的人,可以安装一个Mycat-Web来进行管理,有兴趣自行搜索。

简而言之,开发中使用Mycat和直接使用Mysql机会没有差别。

常见问题

使用Mycat后总会遇到一些坑,我将自己遇到的一些问题在这里列一下,希望能与大家有共鸣:

  • Mycat是不是配置以后,就能完全解决分表分库和读写分离问题? Mycat配合数据库本身的复制功能,可以解决读写分离的问题,但是针对分表分库的问题,不是完美的解决。或者说,至今为止,业界没有完美的解决方案。 分表分库写入能完美解决,但是,不能完美解决主要是联表查询的问题,Mycat支持两个表联表的查询,多余两个表的查询不支持。 其实,很多数据库中间件关于分表分库后查询的问题,都是需要自己实现的,而且节本都不支持联表查询,Mycat已经算做地非常先进了。 分表分库的后联表查询问题,大家通过合理数据库设计来避免。
  • Mycat支持哪些数据库,其他平台如 .net、PHP能用吗? 官方说了,支持的数据库包括MySQL、SQL Server、Oracle、DB2、PostgreSQL 等主流数据库,很赞。 尽量用Mysql我试过SQL Server,会有些小问题,因为部分语法有点差异。
  • Mycat 非JAVA平台如 .net、PHP能用吗? 可以用。这一点MyCat做的也很棒。

配置视频:

http://www.jtthink.com/course/play/467


发表评论

0 个回复