使用mycat配置Mysql读写分离

上一节我们完成了Mysql主从复制 这一节我们使用mycat配置Mysql来完成读写分离。Mycat 1.4 支持MySQL主从复制状态绑定的读写分离机制,让读更加安全可靠。

Mycat下载地址:https://github.com/MyCATApache/Mycat-download

下载完之后 
 

tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/

cd /usr/local/mycat/conf

vim schema.xml

先把所有内容注释:ctrl+v ,shift+g,i,#,esc即可。然后输入:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="aplus" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="maple" />
        <!--
                     0:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
        1:全部的readHost与stand by writeHost参与select语句的负载均衡,
        2:所有读操作都随机在writeHost、readHost上分发
        3:所有读请求随机分发到writeHost对应的readHost执行,writeHost不负担读压力
        -->
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="106.15.184.65:3306" user="root" password="oo63JOdpEy2BL7xgwL">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS1" url="47.111.97.134:3306" user="root" password="gWseMybonuVHAYr5p" weight="1" />
                </writeHost>
        </dataHost>
</mycat:schema>

或者

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="aplus" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="maple" />
        <!--
                     0:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
        1:全部的readHost与stand by writeHost参与select语句的负载均衡,
        2:所有读操作都随机在writeHost、readHost上分发
        3:所有读请求随机分发到writeHost对应的readHost执行,writeHost不负担读压力
        -->
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
			<heartbeat>select user()</heartbeat>
			<!-- can have multi write hosts -->
			<writeHost host="hostM1" url="106.15.184.65:3306" user="root" password="oo63JOdpEy2BL7xgwL" />
			<writeHost host="hostS1" url="47.111.97.134:3306" user="root" password="gWseMybonuVHAYr5p" />
		</dataHost>
</mycat:schema>

以上两种取模第一种当写挂了读不可用,第二种可以继续使用,事务内部的一切操作都会走写节点,所以读 操作不要加事务,如果读延时较大,使用根据主从延时的读写分离,或者强制走写节点。

强制走从:
/*!mycat:db_type=slave*/ select * from travelrecord
/*#mycat:db_type=slave*/ select * from travelrecord
强制走写:
/*#mycat:db_type=master*/ select * from travelrecord
/*!mycat:db_type=master*/ select * from travelrecord

1.4 开始支持 MySQL 主从复制状态绑定的读写分离机制,让读更加安全可靠,配置如下: MyCAT 心跳检查语句配置为 show slave status ,dataHost 上定义两个新属性: switchType="2" 与 slaveThreshold="100",此时意味着开启 MySQL 主从复制状态绑定的读写分离与切换机制,Mycat 心跳机 制通过检测 show slave status 中的 "Seconds_Behind_Master", "Slave_IO_Running", "Slave_SQL_Running" 三个字段来确定当前主从同步的状态以及 Seconds_Behind_Master 主从复制时延, 当 Seconds_Behind_Master>slaveThreshold 时,读写分离筛选器会过滤掉此 Slave 机器,防止读到很久之 前的旧数据,而当主节点宕机后,切换逻辑会检查 Slave 上的 Seconds_Behind_Master 是否为 0,为 0 时则 表示主从同步,可以安全切换,否则不会切换。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="aplus" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="maple" />
        <!--
                     0:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
        1:全部的readHost与stand by writeHost参与select语句的负载均衡,
        2:所有读操作都随机在writeHost、readHost上分发
        3:所有读请求随机分发到writeHost对应的readHost执行,writeHost不负担读压力
        -->
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
			<heartbeat>show slave status </heartbeat>
			<!-- can have multi write hosts -->
			<writeHost host="hostM1" url="106.15.184.65:3306" user="root" password="oo63JOdpEy2BL7xgwL" />
			<writeHost host="hostS1" url="47.111.97.134:3306" user="root" password="gWseMybonuVHAYr5p" />
		</dataHost>
</mycat:schema>

1.4.1 开始支持 MySQL 集群模式,让读更加安全可靠,配置如下: MyCAT 心跳检查语句配置为 show status like ‘wsrep%’ , dataHost 上定义两个新属性: switchType="3" 此时意味着开启 MySQL 集群复制状态状态绑定的读写分离与切换机制,Mycat 心跳机制通过检测集群复制时延 时,如果延时过大或者集群出现节点问题不会负载改节点。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="aplus" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="maple" />
        <!--
                     0:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
        1:全部的readHost与stand by writeHost参与select语句的负载均衡,
        2:所有读操作都随机在writeHost、readHost上分发
        3:所有读请求随机分发到writeHost对应的readHost执行,writeHost不负担读压力
        -->
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="3" >
			<heartbeat> show status like ‘wsrep%’</heartbeat>
			<writeHost host="hostM1" url="106.15.184.65:3306" user="root" password="oo63JOdpEy2BL7xgwL" />
			<writeHost host="hostS1" url="47.111.97.134:3316" user="root" password="gWseMybonuVHAYr5p" />
		</dataHost>
</mycat:schema>

以上就是 schema.xml 的配置,下面配置 server.xml

配置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="useSqlStat">0</property>  <!-- 1为开启实时统计、0为关闭 -->
        <property name="useGlobleTableCheck">0</property>  <!-- 1为开启全加班一致性检测、0为关闭 -->

                <property name="sequnceHandlerType">2</property>
     
                <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>

        
        <user name="root">
                <property name="password">sMwxIv6jrlp0</property>
                <property name="schemas">aplus</property>

        </user>

</mycat:server>

参数说明

balance 属性

负载均衡类型,目前的取值有 3 种:

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 属性

负载均衡类型,目前的取值有 3 种:

1. writeType="0", 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个 writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .

2. writeType="1",所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。

3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。

“readHost是从属于writeHost的,即意味着它从那个writeHost获取同步数据,因此,当它所属的writeHost宕机了,则它也不会再参与到读写分离中来,即“不工作了”,这是因为此时,它的数据已经“不可靠”了。基于这个考虑,目前mycat 1.3和1.4版本中,若想支持MySQL一主一从的标准配置,并且在主节点宕机的情况下,从节点还能读取数据,则需要在Mycat里配置为两个writeHost并设置banlance=1。”

switchType 属性:

-1:表示不自动切换

1 :默认值,自动切换

2 :基于MySQL主从同步的状态决定是否切换

心跳语句为 show slave status

3:基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)

心跳语句为 show status like ‘wsrep%’

heartbeat 标签

这个标签内指明用于和后端数据库进行心跳检查的语句。例如,MYSQL 可以使用 select user(),Oracle 可以 使用 select 1 from dual 等。 这个标签还有一个 connectionInitSql 属性,主要是当使用 Oracla 数据库时,需要执行的初始化 SQL 语句就 这个放到这里面来。例如:alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss' 1.4

主从切换的语句必须是:show slave status

writeHost 标签、readHost 标签

这两个标签都指定后端数据库的相关配置给 mycat,用于实例化后端连接池。唯一不同的是,writeHost 指 定写实例、readHost 指定读实例,组着这些读写实例来满足系统的要求。在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是,如果 writeHost 指定的后端数据库宕机, 那么这个 writeHost 绑定的所有 readHost 都将不可用。另一方面,由于这个 writeHost 宕机系统会自动的检测到,并切换到备用的 writeHost 上去。

好了,介绍完上面之后,我们这里决定用:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="aplus" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="maple" />
        <!--
                                  0:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
        1:全部的readHost与stand by writeHost参与select语句的负载均衡,
        2:所有读操作都随机在writeHost、readHost上分发
        3:所有读请求随机分发到writeHost对应的readHost执行,writeHost不负担读压力
        -->
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
                        <heartbeat>show slave status </heartbeat>
                        <!-- can have multi write hosts -->
                        <writeHost host="hostM1" url="106.15.184.65:3306" user="root" password="oo63JOdpEy2BL7xgwL">
                                <readHost host="hostS2" url="47.111.97.134:3306" user="root" password="gWseMybonuVHAYr5p" />
                        </writeHost>
                        <writeHost host="hostS2" url="47.111.97.134:3306" user="root" password="gWseMybonuVHAYr5p" />
                </dataHost>
</mycat:schema>

下面开始启动

cd /usr/local/mycat/bin
./mycat start
./mycat status

代码里面连接mysql的信息,要改为:

jdbc.url=jdbc:mysql://106.15.184.65:8066/aplus?useUnicode=true&amp;characterEncoding=utf-8
jdbc.username=root
jdbc.password=sMwxIv6jrlp0

之前连接的是 安装mysql的服务器的地址,mysql的端口,数据库名,username和password。

现在连的是  安装mycat服务器的地址,mycat的端口,mycat的数据库名,mycat的username和password。

效果展示:

主:106.15.184.65

从:47.111.97.134

发现,查询的请求 随机落在 主或从上,新增的请求,全都落在了 主上。

我们  tail -f /usr/local/mycat/logs 也能看到

我们把主数据库宕机试下,下图发现3306端口已经没了

 我们再来测试下,发现主 从服务器 依然在工作

但是当我把主数据库重启的之后,service mysqld start,发现他已经变成了 从数据库了,只能接收查询的请求,不能接收 增改的请求。

这是为什么呢????求告知。。。

发布了165 篇原创文章 · 获赞 103 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/qq_33101675/article/details/89145666