读写分离介绍

基于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数据库主机配置标签;

一个逻辑库,对应多个逻辑表,每个逻辑表如上图,可以水平分片(我们后面会细讲),分成一个或者多个数据分片节点,每个数据分片节点对应一个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

在mycat逻辑库中执行insert into student values(2, @@hostname);
由于我们之前配置mysql主从的时候binlog_format选择是mix,看不到变化,如果使用的是statement,就会看到主库和从库的hostname不一样,并且逻辑库与从库是保持一致,因为mycal会根据操作类型select选择从库查询数据。
因为使用了mix模式,现在看到的是逻辑库、主库、从库数据一致。