目录

mycat实现一主一从读写分离

读写分离介绍

http://img.cana.space/picStore/20201121141429.png

基于Mysql主从复制,我们通过Mycat,能够实现读写分离,即master主服务器实现写操作(insert,update,delete等),salve从服务器实现读操作(select等),

主服务器一旦有写入操作,从服务器通过读取binlog,来实现数据同步;Mycat也时时发送心跳包来检测mysql服务器是否可用;

读写分离核心配置详解

Mycat读写分离核心配置文件 schema.xml文件,我们对配置文件来详细介绍下;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
		<!-- auto sharding by id (long) -->
		<!--splitTableNames 启用<table name 属性使用逗号分割配置多个表,即多个表使用这个配置-->
		<table name="travelrecord,address" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" splitTableNames ="true"/>
		<!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"
			/> -->
	</schema>
	<!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
		/> -->
	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost1" database="db2" />
	<dataNode name="dn3" dataHost="localhost1" database="db3" />
	<!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
	 <dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" />
	<dataNode	name="jdbc_dn2" dataHost="jdbchost" database="db2" />
	<dataNode name="jdbc_dn3" 	dataHost="jdbchost" database="db3" /> -->
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- can have multi write hosts -->
		<writeHost host="hostM1" url="localhost:3306" user="root"
				   password="123456">
		</writeHost>
		<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
	</dataHost>
  ...

schema.xml有几个标签,分别是:mycat:schema schema主配置标签, schema逻辑库配置标签,dataNode数据节点配置标签,dataHost数据库主机配置标签;

http://img.cana.space/picStore/20201121143948.png

一个逻辑库,对应多个逻辑表,每个逻辑表如上图,可以水平分片(我们后面会细讲),分成一个或者多个数据分片节点,每个数据分片节点对应一个dataHost(数据库主机),dataHost里可以通过writeHost和readHost配置写主机和读主机;

schema标签属性介绍

定义逻辑数据库

属性 解释
name 配置逻辑库的名字(即数据库实例名);
checkSQLschema SQLschema检查,boolean类型。当前端执行【select *from USERDB.tf_user;】时(表名前指定了mycat逻辑库名),两种取值
true:mycat会把语句转换为【select * from tf_user;】
false:会报错
sqlMaxLimit 最大查询每页记录数设置 相当于sql的结果集中,加上【limit N】。
如果sql本身已经指定limit,则以sql指定的为准。
dataNode 配置数据库节点: 用于配置该逻辑库默认的分片。没有通过table标签配置的表,就会走到默认的分片上。
这里注意没有配置在table标签的表,用工具查看是无法显示的(navicat可以,syslog不行),但是可以正常使用。
如果没有配置dataNode属性,则没有配置在table标签的表,是无法使用的。

dataNode标签属性

定义数据分片节点

属性 解释
name 数据分片节点名称
dataHost 定义该数据分片节点属于哪个数据库主机
database 定义该数据分片节点属于哪个具体数据库实例上的具体库(即对应mysql中实际的DB)

dataHost标签属性

定义后端的数据库主机

属性 解释
name 指定dataHost的名字
maxCon 指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、 readHost 标签都会使用这个属性的值来实例化出连接池的最大连接数。
minCon 指定每个读写实例连接池的最小连接,初始化连接池的大小。
balance 负载均衡类型:一主一从配置成3,双主双从配置成1
(1)balance=“0”, 不开启读写分离机制,所有读操作都发送到当前可用的writeHost 上。
(2)balance=“1”,全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。
(3)balance=“2”,所有读操作都随机的在 writeHost、 readhost 上分发。
(4)balance=“3”,所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。
writeType (1)writeType=“0”, 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties.
(2)writeType=“1”,所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。
dbType 指定后端连接的数据库类型,目前支持二进制的 mysql 协议,还有其他使用 JDBC 连接的数据库。例如:mongodb、 oracle、 spark 等。
dbDriver 指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。使用native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和 maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。
switchType 主从切换
-1 表示不自动切换 1 默认值,
2 自动切换 ,基于 MySQL 主从同步的状态决定是否切换 心跳语句为 show slave status
3 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)
slaveThreshold 配置真实MySQL与MyCat的心跳

heartbeat子标签属性

心跳执行SQL

writeHost子标签属性

写主机配置

readHost子标签属性

读主机配置

属性 解释
host 用于标识不同实例,一般 writeHost 我们使用M1,readHost 我们用S1。
url 后端实例连接地址,如果是使用 native 的 dbDriver,则一般为 address:port 这种形式。用 JDBC 或其他的dbDriver,则需要特殊指定。当使用 JDBC 时则可以这么写:jdbc:mysql://localhost:3306/。
user 后端存储实例需要的用户名字
password 后端存储实例需要的密码

mycat读写分离环境准备

软件准备

mysql主从环境搭建:mysql一主一从搭建

前面我们创建了mycat容器,但是使用的随机ip,重新创建mycat容器,让ip和mysql主从在一个网段上,使用配置mysql主从使用的网络模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.查看网络模式,mysql_mysql是我们自己配置的
$ docker network list
NETWORK ID          NAME                DRIVER              SCOPE
228c5935d524        bridge              bridge              local
5764d6ad09fd        host                host                local
78bab390eeb3        mysql_mysql         bridge              local
c57b169da6a0        none                null                local
# 2.启动mycat镜像
$ docker run -p 8066:8066 \
-v ~/docker/mycat/conf/:/home/mycat/conf/ \
-v ~/docker/mycat/logs/:/home/mycat/logs/ \
--name mycat01 --net mysql_mysql --ip 182.30.0.9 \
-d lienhui68/mycat:1.0
52efe1d88686d2711bc137ddc2e9d04dbb23a7da0268811908b7f0ccf8451d49
# 3.查看ip
$ docker_ip
/mycat01 - 182.30.0.9
/affectionate_edison -
/s1 - 182.30.0.3
/m1 - 182.30.0.2
# 可以看到3个服务在一个网段上了

mycat配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<!-- 将randomDataNode改成dataNode -->
	<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
	</schema>

	<!--配置成自己的数据库-->
	<dataNode name="dn1" dataHost="localhost1" database="eden" />

	<!--
	balance="3",  所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。
	switchType="2" 基于MySQL 主从同步的状态决定是否切换

	-->

	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="2"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="182.30.0.2:3306" user="root" password="123456">
			 <!-- 配置从库 -->
			 <readHost host="hostS1" url="182.30.0.3:3306" user="root" password="123456" />
		</writeHost>
	</dataHost>
</mycat:schema>

配置完主从之后需要重启mycat容器

Mycat读写分离测试

使用navicat连接mycat逻辑库TESTDB

20201121153045

在mycat逻辑库中执行insert into student values(2, @@hostname);

由于我们之前配置mysql主从的时候binlog_format选择是mix,看不到变化,如果使用的是statement,就会看到主库和从库的hostname不一样,并且逻辑库与从库是保持一致,因为mycal会根据操作类型select选择从库查询数据。

因为使用了mix模式,现在看到的是逻辑库、主库、从库数据一致。