MySQL 集群(三):MySQL + Mycat 实现读写分离,主备切换集群

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_37143673/article/details/102588730


本章基于: 本章基于:MySQL 集群(一):Docker 搭建 MySQL,MySQL 主从同步搭建及踩坑
MySQL 主从同步,互为主备:

  • master:127.0.0.1:7000
  • slave:127.0.0.1:7001

下载 Mycat

Mycat 官网
官方说明

我下的是 Mycat-server-1.6 Linux 版本

我的安装目录 /data/mycat

#下载
wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

#解压
tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz 

Mycat 主要文件

  • bin:Mycat 命令,启动、重启、停止等
  • catlet:支持跨分片复杂SQL实现以及存储过程支持等
  • conf:配置信息,重要
    • server.xml: Mycat 的配置文件,设置逻辑库账号,参数等
    • schema.xml:Mycat 对应的物理数据库和数据库表的配置
    • rule.xml:Mycat分片(分库分表)规则,没用到,暂时不做说明
    • wrapper.conf:内存配置
  • lib:Mycat 的 jar 包
  • logs:日志,重要
    • wrapper.log:全日志
    • mycat.log:在 Mycat 成功启动后才会出现,本次启动后的日志

端口

8066:开发端口,正常开发,操作数据库使用
9066:管理端口,一般就热刷新配置时使用

Mycat 命令

进入 Mycat 的 bin 目录下

  • ./mycat start 启动

  • ./mycat stop 停止

  • ./mycat console 前台运行

  • ./mycat install 添加到系统自动启动(暂未实现)

  • ./mycat remove 取消随系统自动启动(暂未实现)

  • ./mycat restart 重启服务

  • ./mycat pause 暂停

  • ./mycat status 查看启动状态

配置文件

server.xml

配置看着比较多,但是上面部分都是配置里自带的,只在下面 user 标签 做了修改
PS:
逻辑库可以理解为一个虚拟库,用户只需连接这个逻辑库做操作就行了,剩下至于究竟 SQL 在哪台上执行之类的,由 Mycat 自己去选择

xmlns:mycat 的值在 1.5 版本中是 http://org.opencloudb//font>
xmlns:mycat 的值在 1.6 版本中是 http://io.mycat//font>
后面文件一样,不多赘述

  • <user name="root"> ... </user> 配置逻辑库账号
  • <property name="password">123456</property> 配置逻辑库密码
  • <property name="schemas">mysql1</property> 配置对应逻辑库,多个都用这套账号密码的 , 隔开
<?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>
	-->
	
	<!-- 上面都没做改动,下面做了改动 -->
	<!-- 配置 Mycat 逻辑库访问账号密码 -->
	<user name="root">
		<property name="password">123456</property>
		<property name="schemas">mysql1</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">TESTDB</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="mysql1" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
		<!-- 这里配置分库分表,因只做读写分离所以这里暂不配置 -->
	</schema>

	<!-- 配置数据库节点 -->
	<dataNode name="dn1" dataHost="mysql1-host" database="test" />

	<!-- 具体逻辑关系配置 -->
	<!-- balance = 1:读请求随机分发到当前 writeHost 对应的 readHost 和 standby 的 writeHost 上 -->
	<!-- writeType = 0:所有写操作发送到配置的第一个writeHost,当第一个writeHost宕机时,切换到第二个writeHost,重新启动后以切换后的为准 -->
	<!-- switchType = 2:基于MySQL主从同步的状态决定是否切换 -->
	<dataHost name="mysql1-host" maxCon="1000" minCon="10" balance="1" writeType="0" switchType="2" dbType="mysql" dbDriver="native" slaveThreshold=“100”>
		<!-- 定时执行SQL保持心跳 -->
		<heartbeat>show slave status</heartbeat>
		<!-- 添加写入库配置 -->
		<writeHost host="master-node1" url="118.25.215.105:7000" user="root" password="123456">
			<!-- 添加只读库配置-->
			<readHost host="slave-node1" url="118.25.215.105:7001" user="root" password="123456" />
		</writeHost>
		<!-- 备用写节点,这样才能切过来 -->
		<writeHost host="master-node2" url="118.25.215.105:7001" user="root" password="123456"/>
	</dataHost>
</mycat:schema>

参数说明

PS:配置说明在官方的书上都有,这里对用到的做了整理,也可以自己到官网下载 PDF

schema

逻辑库设置,可以理解成 Mycat 创建的虚拟数据库,用来给用户与实际数据库之间搭建的桥梁

name:定义逻辑库的名称

checkSQLschema:设为 true 时会省略数据库前缀,据说有 Bug,一般默认 false 就好了
PS:说下我这里为什么设置为 true,因为设置成 false 的情况下,由于数据库前缀没去除,导致直接用 Navicate 等工具连接 Mycat 逻辑库后直接双击表都打不开,报库名没有。因为虚拟库的库名再实际库里是不存在的,所以写 SQL 不带库名就不存在问题,怎么选择可以自己权衡

sqlMaxLimit:当查询语句没有 limit 时就会自动帮你加上,不写就不会有这个效果,查询语句中本身有 limit 情况下以查询语句的为准

dataNode:对应的分片节点

dataNode

对应的分片节点,由于暂时没用到分片,不多介绍,配置一个就好了

name:节点名称

dataHost:分片所属的物理数据库,我的理解是对应的物理数据库的逻辑关系

database :数据库名,你具体这个节点要操作哪个数据库

dataHost(重要)

物理数据库的逻辑关系,什么读写分离,多主负载均衡,自动切换的逻辑都是这里面配,建议对着配置看

dataHost
name:实例名称,自取

maxCon:每个读写实例连接池的最大连接数量

minCon:每个读写实例连接池的最小连接数量,初始化连接池大小

balance:负载均衡类型

  • balance=“0”:不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上
  • balance=“1”:读请求随机分发到当前 writeHost 对应的 readHoststandbywriteHost 上。即全部的 readHoststand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1, M2->S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1,S2 都参与 select 语句的负载均衡
  • balance=“2”:读请求随机分发到当前dataHost内所有的 writeHostreadHost 上。即所有读操作都随机的在 writeHostreadhost 上分发
  • balance=“3”:读请求随机分发到当前 writeHost 对应的 readHost 上。即所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力,注意 balance=“3” 只在 1.4 及其以后版本有,1.3 没有。

writeType:同样是负载均衡类型,功能上略有不同

  • writeType=“0”:所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost。重新恢复第一个 writeHost 后,不会自动切回来,还是以第二个 writeHost 为准,切换记录在配置文件中:dnindex.properties
  • writeType=“1”:所有写操作都随机的发送到配置的 writeHostMycat 1.5 以后不再推荐使用该值

switchType:主从切换配置

  • switchType="-1":不自动切换
  • switchType=“1”:默认值,自动切换
  • switchType=“2”:基于MySQL主从同步的状态来决定是否切换。需修改 heartbeat 语句(即心跳语句):show slave status
  • switchType=“3”:基于Mysql Galera Cluster(集群多节点复制)的切换机制,适合集群,Mycat 1.4.1 及以上版本支持。需修改heartbeat语句(即心跳语句):show status like 'wsrep%'

slaveThreshold:需要这个配合 switchType 才能实现主备切换

dbType:指定后端连接的数据库类型,目前支持 mysqlmongodboraclespark

dbDriver:指定连接后端数据库使用的 Driver

指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。使用 native 的话,因为这个值执行的
是二进制的 mysql 协议,所以可以使用 mysql 和 maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。
从 1.6 版本开始支持 postgresql 的 native 原始协议。
如果使用 JDBC 的话需要将符合 JDBC 4 标准的驱动 JAR 包放到 MYCAT\lib 目录下,并检查驱动 JAR 包中
包括如下目录结构的文件:META-INF\services\java.sql.Driver。在这个文件内写上具体的 Driver 类名,例如:
com.mysql.jdbc.Driver。

heartbeat:心跳 SQL,注意 switchType 属性所需要使用对应的 SQL

writeHost:配置写实例,具体数据库配置
host:可以理解成名称,自起,日志里面根据这个 host 就知道执行的哪个数据库

url:数据库地址

user:用户名

password:密码

readHost:配置写实例,具体数据库配置,配置参照 writeHost

启动

看到 finish 10 success 10 这种的就说明这个实例连接成功了,每个实例都要看下,防止有失败的
在这里插入图片描述

Mycat 配置热刷新

连接 Mycat 管理端口 9066

服务器上修改完配置保存

#会加载schema.xml配置的调整。
reload @@config;

#刷新全部配置
reload @@config_all;

在这里插入图片描述
PS:这个刷新对日志这个刷新好像不太好使,不知道是不是 Bug

日志验证:读写分离

连接 Mycat 开发端口 8066

读写分离,balance=“1”,因此 master1 用于写,master2slave 用于读

  • master:127.0.0.1:7000(互为主备)
  • slave:127.0.0.1:7001

修改 conflog4j2.xml 文件日志等级为 debug
在这里插入图片描述
查看日志

tail -100f mycat.log

建表

CREATE TABLE `people`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NULL COMMENT '名字',
  `age` int(11) NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
);

在这里插入图片描述
通过 7000 端口看出,创建语句在 master 主库上执行的,并且 fromSlaveDB=false 也可以看出走的不是从库

新增 1 条数据

INSERT INTO people (name, age) VALUES ('小明', 12)

在这里插入图片描述
依然是写操作,走的 7000 master 主库上

查询列表

SELECT * FROM people

在这里插入图片描述
从这回的 7001 端口以及 fromSlaveDB=true 上可以看出走的从库

再次新增一条数据

INSERT INTO people (name, age) VALUES ('小红', 20)

在这里插入图片描述
写操作,再次走了 master

查询数据

SELECT * FROM people WHERE age < 20

在这里插入图片描述
读操作走了从库

日志验证:主备切换

dnindex.properties:通过查看 conf 目录下的这个文件,可以知道mycat正在使用的 writeHost,0表示schema.xmldataHost 标签下的第一个 writeHost

模拟主的宕机

停止 master 容器
在这里插入图片描述
可以看到失败一定次数后,开始尝试切换数据源

来看下 dnindex.properties
在这里插入图片描述
执行一个写操作

INSERT INTO people (name, age) VALUES ('A', 25)

在这里插入图片描述
成功转移到 slave

踩坑

Mycat 启动失败

在这里插入图片描述
在这里插入图片描述

问题描述

由于内存不足,导致内存分配失败

解决方案

修改 conf 下的 wrapper.conf 文件
这两个值原大小为 4G1G ,我这个服务器一共就 2G 所以内存不足了,可通过 top 查看服务器内存使用情况
在这里插入图片描述

Mycat 启动成功,连接数据库失败

日志报 Unknown charsetIndex:255 错误
PS:忘截图了

问题描述

由于 Mycat 字符集的配置文件匹配不到导致的错误

解决方案

conf 下的 index_to_charset.properties 文件里新增 255=utf8mb4

网上很多报的是 Unknown charsetIndex:224 同理新增 224=utf8mb4

猜你喜欢

转载自blog.csdn.net/qq_37143673/article/details/102588730