windows环境使用mycat分库分表的安装与配置


windows环境使用mycat分库分表的安装与配置


一、mycat介绍

mycat官网地址: http://www.mycat.org.cn/

简介:

  • mycat是一款支持mysql数据库分库分表以及读写分离的开源中间件
  • MyCat后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储
  • 支持事务、ACID、可以替代MySQL的加强版数据库

MyCat的应用场景:
以下是几个典型应用场景:
1、 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换
2、 分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片
3、 多租户应用,每个应用一个库,但应用程序只连接MyCat,从而不改造程序本身,实现多租户
4、 报表系统,借助于MyCat的分表能力,处理大规模报表的统计
5、 替代HBase,分析大数据
6、 作为海量数据实时查询的一种方案,比如100亿条频繁查询的记录需要在3秒内查询出结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时MyCat可能是最简单有效的选择。

二、window10环境下安装流程
1.下载win10环境支持的版本
在这里插入图片描述

下载好了以后,解压即可,解压到本地的文件夹下,为了防止莫名奇妙的问题,建议都放置到纯英文目录下。

2.mycat目录介绍
解压好以后,我们进入mycat 的目录,目录结构如下所示:
在这里插入图片描述
主要目录介绍:

1.bin目录:里面主要是mycat的启动/重启/停止的文件
2.conf目录:mycat的主要配置目录,我们最常用的是里面的server.xml,schema.xml,rule.xml3个配置文件
3.logs目录:日志目录,会记录启动,停止,执行的日志等等

3.mycat配置
在启动目录之前,我们要先配置一下基础的信息情况,否则启动会抛异常。mycat是java代码编写的,所以,有问题我们可以看到日志文件中抛出的各种异常原因:
学java的伙伴是不是有种很熟悉的感觉哈…

错误样例1
FATAL  | wrapper  | 2020/12/04 13:55:15 | OpenSCManager failed - 拒绝访问。 (0x5)
ERROR  | wrapper  | 2020/12/04 13:56:20 | CreateService failed - 指定的服务已存在。 (0x431)
ERROR  | wrapper  | 2020/12/04 13:58:28 | CreateService failed - 指定的服务已存在。 (0x431)
STATUS | wrapper  | 2020/12/04 13:58:33 | Starting the Mycat-server service...
STATUS | wrapper  | 2020/12/04 13:58:33 | --> Wrapper Started as Service
STATUS | wrapper  | 2020/12/04 13:58:33 | Launching a JVM...
INFO   | jvm 1    | 2020/12/04 13:58:35 | 错误: 代理抛出异常错误: java.rmi.server.ExportException: Port already in use: 1984; nested exception is: 
INFO   | jvm 1    | 2020/12/04 13:58:35 | 	java.net.BindException: Address already in use: JVM_Bind
ERROR  | wrapper  | 2020/12/04 13:58:36 | JVM exited while loading the application.
INFO   | wrapper  | 2020/12/04 13:58:38 | Waiting to start...
STATUS | wrapper  | 2020/12/04 13:58:40 | Launching a JVM...

错误样例2
2020-12-05 09:46:55.064 ERROR [Timer1] (io.mycat.net.NIOSocketWR.checkAlive(NIOSocketWR.java:78)) - 
java.nio.channels.ClosedChannelException: null
	at sun.nio.ch.SocketChannelImpl.ensureReadOpen(Unknown Source) ~[?:1.8.0_102]
	at sun.nio.ch.SocketChannelImpl.read(Unknown Source) ~[?:1.8.0_102]
	at io.mycat.net.NIOSocketWR.checkAlive(NIOSocketWR.java:76) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.net.AbstractConnection.checkAlive(AbstractConnection.java:635) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.ConQueue.takeIdleCon(ConQueue.java:22) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.ConMap.tryTakeCon(ConMap.java:52) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.ConMap.tryTakeCon(ConMap.java:32) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.datasource.PhysicalDatasource.getConnection(PhysicalDatasource.java:534) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.sqlengine.SQLJob.run(SQLJob.java:70) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.heartbeat.MySQLDetector.heartbeat(MySQLDetector.java:112) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.heartbeat.MySQLHeartbeat.heartbeat(MySQLHeartbeat.java:142) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.datasource.PhysicalDatasource.doHeartbeat(PhysicalDatasource.java:464) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.backend.datasource.PhysicalDBPool.doHeartbeat(PhysicalDBPool.java:436) [Mycat-server-1.6.7.6-release.jar:?]
	at io.mycat.MycatServer$8$1.run(MycatServer.java:964) [Mycat-server-1.6.7.6-release.jar:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_102]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_102]
	at java.lang.Thread.run(Unknown Source) [?:1.8.0_102]

下面我们就来重点介绍一下mycat的基本配置信息

1. 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/">
	<system>
	<property name="nonePasswordLogin">0</property> <!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户-->
	<property name="ignoreUnknownCommand">0</property><!-- 0遇上没有实现的报文(Unknown command:),就会报错、1为忽略该报文,返回ok报文。
	在某些mysql客户端存在客户端已经登录的时候还会继续发送登录报文,mycat会报错,该设置可以绕过这个错误-->
	<property name="useHandshakeV10">1</property>
    <property name="removeGraveAccent">1</property>
	<property name="useSqlStat">0</property>  <!-- 1为开启实时统计、0为关闭 -->
	<property name="useGlobleTableCheck">0</property>  <!-- 1为开启全加班一致性检测、0为关闭 -->
	<property name="sqlExecuteTimeout">300</property>  <!-- SQL 执行超时 单位:秒-->
		<property name="sequenceHandlerType">1</property>
	<!--<property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>
	INSERT INTO `travelrecord` (`id`,user_id) VALUES ('next value for MYCATSEQ_GLOBAL',"xxx");
	-->
	<!--必须带有MYCATSEQ_或者 mycatseq_进入序列匹配流程 注意MYCATSEQ_有空格的情况-->
	<property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>
	<property name="subqueryRelationshipCheck">false</property> <!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false -->
	<property name="sequenceHanlderClass">io.mycat.route.sequence.handler.HttpIncrSequenceHandler</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 | type 2 NettyBufferPool -->
		<property name="processorBufferPoolType">0</property>
		<!--默认是65535 64K 用于sql解析时最大文本长度 -->
		<!--<property name="maxStringLiteralLength">65535</property>-->
		<!--<property name="sequenceHandlerType">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="dataNodeIdleCheckPeriod">300000</property> 5 * 60 * 1000L; //连接空闲检查
			<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">0</property>

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

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

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

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


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

		<!-- XA Recovery Log日志路径 -->
		<!--<property name="XARecoveryLogBaseDir">./</property>-->

		<!-- XA Recovery Log日志名称 -->
		<!--<property name="XARecoveryLogBaseName">tmlog</property>-->
		<!--如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接-->
		<property name="strictTxIsolation">false</property>
		<!--如果为0的话,涉及多个DataNode的catlet任务不会跨线程执行-->
		<property name="parallExecute">0</property>
	</system>
	
	<!-- 全局SQL防火墙设置 -->
	<!--白名单可以使用通配符%或着*-->
	<!--例如<host host="127.0.0.*" user="root"/>-->
	<!--例如<host host="127.0.*" user="root"/>-->
	<!--例如<host host="127.*" user="root"/>-->
	<!--例如<host host="1*7.*" user="root"/>-->
	<!--这些配置情况下对于127.0.0.1都能以root账户登录-->
	<!--
	<firewall>
	   <whitehost>
	      <host host="1*7.0.0.*" user="root"/>
	   </whitehost>
       <blacklist check="false">
       </blacklist>
	</firewall>
	-->

	<user name="root" defaultAccount="true">
		<property name="password">root</property>
		<property name="schemas">TESTDB</property>
		<property name="defaultSchema">TESTDB</property>
		<!--No MyCAT Database selected 错误前会尝试使用该schema作为schema,不设置则为null,报错 -->
	</user>

	<user name="user">
		<property name="password">user</property>
		<property name="schemas">TESTDB</property>
		<property name="readOnly">true</property>
		<property name="defaultSchema">TESTDB</property>
	</user>

</mycat:server>

其实里面本身的介绍已经很详细了,重点给大家看下我修改的部分:
重点就算登陆的用户和密码了:这里的schemas其实就是下面schema.xml里的逻辑数据库名称,到下问中大家可以看到。
在这里插入图片描述

2. 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">
		<!-- auto sharding by id (long) -->
		<!--splitTableNames 启用<table name 属性使用逗号分割配置多个表,即多个表使用这个配置-->
<!--fetchStoreNodeByJdbc 启用ER表使用JDBC方式获取DataNode-->
		<!--<table name="user" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-intfile" autoIncrement="true" fetchStoreNodeByJdbc="true">
			<childTable name="user" primaryKey="id" joinKey="id" parentKey="id"> </childTable>
		</table>-->
		<table name="user" dataNode="dn1,dn2" rule="mod-long"/>
		<table name="company" dataNode="dn1"/>
		<table name="tenant" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2" rule="mod-long"/>
	</schema>
	
	<dataNode name="dn1" dataHost="localhost1" database="mycat_db1" />
	<dataNode name="dn2" dataHost="localhost1" database="mycat_db2" />
	
	<dataHost name="localhost1" maxCon="999" minCon="10" balance="0"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="localhost:3306" user="root" password="root">
		</writeHost>
	</dataHost>
</mycat:schema>

原文件解压后里面的样例内容还是很多的,我删掉了多余的介绍,保留的自己需要的部分:
重点给大家看下修改了的地方
在这里插入图片描述
3. rule.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:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
	<tableRule name="rule1">
		<rule>
			<columns>id</columns>
			<algorithm>func1</algorithm>
		</rule>
	</tableRule>

	<tableRule name="sharding-by-date">
		<rule>
			<columns>createTime</columns>
			<algorithm>partbyday</algorithm>
		</rule>
	</tableRule>

	<tableRule name="rule2">
		<rule>
			<columns>user_id</columns>
			<algorithm>func1</algorithm>
		</rule>
	</tableRule>

	<tableRule name="sharding-by-intfile">
		<rule>
			<columns>sharding_id</columns>
			<algorithm>hash-int</algorithm>
		</rule>
	</tableRule>
	<tableRule name="auto-sharding-long">
		<rule>
			<columns>id</columns>
			<algorithm>rang-long</algorithm>
		</rule>
	</tableRule>
	<tableRule name="mod-long">
		<rule>
			<columns>id</columns>
			<algorithm>mod-long</algorithm>
		</rule>
	</tableRule>
	<tableRule name="sharding-by-murmur">
		<rule>
			<columns>id</columns>
			<algorithm>murmur</algorithm>
		</rule>
	</tableRule>
	<tableRule name="crc32slot">
		<rule>
			<columns>id</columns>
			<algorithm>crc32slot</algorithm>
		</rule>
	</tableRule>
	<tableRule name="sharding-by-month">
		<rule>
			<columns>create_time</columns>
			<algorithm>partbymonth</algorithm>
		</rule>
	</tableRule>
	<tableRule name="latest-month-calldate">
		<rule>
			<columns>calldate</columns>
			<algorithm>latestMonth</algorithm>
		</rule>
	</tableRule>

	<tableRule name="auto-sharding-rang-mod">
		<rule>
			<columns>id</columns>
			<algorithm>rang-mod</algorithm>
		</rule>
	</tableRule>

	<tableRule name="jch">
		<rule>
			<columns>id</columns>
			<algorithm>jump-consistent-hash</algorithm>
		</rule>
	</tableRule>

	<function name="murmur"
			  class="io.mycat.route.function.PartitionByMurmurHash">
		<property name="seed">0</property><!-- 默认是0 -->
		<property name="count">2</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
		<property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160-->
		<!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 -->
		<!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
			用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 -->
	</function>

	<function name="crc32slot"
			  class="io.mycat.route.function.PartitionByCRC32PreSlot">
		<property name="count">2</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
	</function>
	<function name="hash-int"
			  class="io.mycat.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-int.txt</property>
	</function>
	<function name="rang-long"
			  class="io.mycat.route.function.AutoPartitionByLong">
		<property name="mapFile">autopartition-long.txt</property>
	</function>
	<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		<!-- how many data nodes -->
		<property name="count">2</property>
	</function>

	<function name="func1" class="io.mycat.route.function.PartitionByLong">
		<property name="partitionCount">8</property>
		<property name="partitionLength">128</property>
	</function>
	<function name="latestMonth"
			  class="io.mycat.route.function.LatestMonthPartion">
		<property name="splitOneDay">24</property>
	</function>
	<function name="partbymonth"
			  class="io.mycat.route.function.PartitionByMonth">
		<property name="dateFormat">yyyy-MM-dd</property>
		<property name="sBeginDate">2015-01-01</property>
	</function>


	<function name="partbyday"
			  class="io.mycat.route.function.PartitionByDate">
		<property name="dateFormat">yyyy-MM-dd</property>
		<property name="sNaturalDay">0</property>
		<property name="sBeginDate">2014-01-01</property>
		<property name="sEndDate">2014-01-31</property>
		<property name="sPartionDay">10</property>
	</function>

	<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
		<property name="mapFile">partition-range-mod.txt</property>
	</function>

	<function name="jump-consistent-hash" class="io.mycat.route.function.PartitionByJumpConsistentHash">
		<property name="totalBuckets">3</property>
	</function>
</mycat:rule>

里面配置的内容看似很多,其实都是配置的各种分片规则,有根据日期的,范围的,取模的等等;
因为我测试的是根据取模来分片的,且只分2个片。
所以,这个配置文件只改了一个地方,其它地方原封不动,就是下面截图的部分:默认是3个分片,我给改成2个:
在这里插入图片描述

4. mysql数据库准备:
上面都配置好了以后,就是创建配置文件中相关的数据库信息了。
如下截图内容:
在这里插入图片描述
所有的配置文件修改好以后,不要忘记保存,保存好以后再启动mycat;

5. 启动mycat

注意:1.mycat在windows环境下需要用管理员权限去启动
2.本机的java环境也安装完成,且是正常可执行的。

我喜欢的打开方式是使用开始菜单,可以查看执行效果:
在这里插入图片描述

1.打开以后,进入到mycat的bin目录下:学习的朋友替换成自己的路径地址:

C: cd C:\MyProgram\programs\Mycat-server-1.6.7.6-release-20201126013625-win\mycat\bin

2.执行启动脚本:mycat.bat start

C:\MyProgram\programs\Mycat-server-1.6.7.6-release-20201126013625-win\mycat\bin>mycat.bat start
wrapper  | Starting the Mycat-server service...
wrapper  | Waiting to start...
wrapper  | Mycat-server started.

3.查看执行状态:mycat.bat status

C:\MyProgram\programs\Mycat-server-1.6.7.6-release-20201126013625-win\mycat\bin>mycat.bat status
wrapper  | The Mycat-server Service is installed.
wrapper  |   Start Type: Automatic
wrapper  |   Interactive: No
wrapper  |   Running: Yes

看到上面的这个状态就是表示成功启动了,就可以关键命令行界面了,关了之后mycat也是启动状态
4.停止的话也很简单:mycat.bat stop

C:\MyProgram\programs\Mycat-server-1.6.7.6-release-20201126013625-win\mycat\bin>mycat.bat stop
wrapper  | Stopping the Mycat-server service...
wrapper  | Mycat-server stopped.

注意:
如果启动失败的话,很可能是配置文件有错误,可以到logs目录下去查看日志信息,找到错误原因。
实际中,大部分启动失败的原因是因为配置文件有错误。

6.验证
用native连接上mycat,连接方法和mysql一样,端口8066:用户名和密码就是server.xml中配置的超管用户root,密码也是root;实际生产密码可千万不能这样配置,必须按照密码安全策略去设置账号和密码,我这只是为了方便:

在这里插入图片描述
连接上以后,打开sql查询编辑器:随机插入几条数据

INSERT INTO user (`id`, `username`, `age`, `phone`) VALUES ('1', 'tom1', '22', '13200000000');
INSERT INTO user (`id`, `username`, `age`, `phone`) VALUES ('2', 'tom2', '22', '13200000000');
INSERT INTO user (`id`, `username`, `age`, `phone`) VALUES ('3', 'tom3', '22', '13200000000');

执行完成以后,我们先打开mycat中的user表,查看下user表的数据信息:
在这里插入图片描述可以看到数据已经生成,但是id的这个顺序很奇怪,和我们直接在mysql操作的结果好像不太一样:这个就需要大家去了解一下mycat的取模执行原理了,本文不做过多讲解。

接下来,我们再看下mysql的两个实际库中的user表的结果:可以发现id1、3、5、7是在mycat_db2中,id2、4、6、8是在mycat_db1中。原因就算我设置的分片规则是根据2个分片按照2进行取模的。
在这里插入图片描述
关于mycat还有很多的坑需要我们去踩,这里只是最基本的一个使用介绍。让我们拿起枪,再接再励,继续踩坑。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37488998/article/details/110679222