zoukankan      html  css  js  c++  java
  • MyCAT实现MySQL读写分离架构

    在MySQL中间件出现之前,对于MySQL主从集群,如果要实现其读写分离,一般是在程序端实现,这样就带来一个问题,即数据库和程序的耦合度太高,如果数据库的地址发生改变,那么程序端也要进行相应的修改,如果数据库不小心挂掉了,则同时也意味着程序的不可用,而这对很多应用来说,并不能接受。

    引入MySQL中间件能很好的对程序端和数据库进行解耦,这样,程序端只需关注数据库中间件的地址,而无需知晓底层数据库是如何提供服务。

    作为当前炙手可热的MySQL中间件,MyCAT实现MySQL主从集群的读写分离自是应有之义,其配置也相当简单。

    step1:准备mysql集群环境

    本次使用三个实例组成MySQL主从集群,来验证MyCAT的读写分离功能,其实,一主一从就可以满足,之所以用三个,是为了验证MyCAT的分片功能。

    集群组成如下:

    角色 主机名 主机IP

    master mysql-server1 192.168.244.145

    slave mysql-server2 192.168.244.146

    slave mysql-server3 192.168.244.144

    在这里,还是使用Travelrecord表进行测试。

    step2:编辑MyCAT的配置文件schema.xml

    关于dataHost的配置信息如下:

    <dataHost name="localhost1"
              maxCon="1000"
              minCon="10"
              balance="1"
              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="hostS1" url="192.168.244.146:3306" user="root" password="123456"/>
    	<writeHost host="hostS2" url="192.168.244.144:3306" user="root" password="123456"/>
    </dataHost>
    

    这里面,有两个参数需要注意,balance和 switchType。

    其中,balance指的负载均衡类型,目前的取值有4种:

    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不负担读压力

    switchType指的是切换的模式,目前的取值也有4种:

    1. switchType='-1' 表示不自动切换

    2. switchType='1' 默认值,表示自动切换

    3. switchType='2' 基于MySQL主从同步的状态决定是否切换,心跳语句为 show slave status

    4. switchType='3'基于MySQL galary cluster的切换机制(适合集群)(1.4.1),心跳语句为 show status like 'wsrep%'。

    因此,该配置文件中的balance="1"意味着作为stand by writeHost的hostS1和hostS2将参与select语句的负载均衡,这就实现了主从的读写分离,switchType='-1'意味着当主挂掉的时候,不进行自动切换,即hostS1和hostS2并不会被提升为主,仍只提供读的功能。这就避免了将数据写进slave的可能性,毕竟,单纯的MySQL主从集群并不允许将数据读进slave中,除非配置的是双master。

    step3:验证读写分离

    下面进行读写分离实现的验证

    1、创建Travelrecord表

    create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int);
    

    2、插入数据

    mysql> insert into travelrecord(id,user_id,traveldate,fee,days)  values(1,@@hostname,20160101,100,10);
    Query OK, 1 row affected, 1 warning (0.02 sec)
    
    mysql> insert into travelrecord(id,user_id,traveldate,fee,days)  values(5000001,@@hostname,20160102,100,10);
    Query OK, 1 row affected, 1 warning (0.01 sec)
    

    在这里,用了一个取巧的方法,即对user_id插入了当前实例的主机名,这样可直观的观察读写是否分离以及MyCAT的分片功能。能这样做的原因在于我当前的MySQL版本-5.6.26默认是基于statement的复制,如果是基于row的复制,则这个方法将不可取。

    3、查询数据

    mysql> select * from travelrecord;
    +---------+---------------+------------+------+------+
    | id      | user_id       | traveldate | fee  | days |
    +---------+---------------+------------+------+------+
    |       1 | mysql-server2 | 2016-01-01 |  100 |   10 |
    | 5000001 | mysql-server3 | 2016-01-02 |  100 |   10 |
    +---------+---------------+------------+------+------+
    2 rows in set (0.01 sec)
    
    mysql> select * from travelrecord;
    +---------+---------------+------------+------+------+
    | id      | user_id       | traveldate | fee  | days |
    +---------+---------------+------------+------+------+
    | 5000001 | mysql-server3 | 2016-01-02 |  100 |   10 |
    |       1 | mysql-server2 | 2016-01-01 |  100 |   10 |
    +---------+---------------+------------+------+------+
    2 rows in set (0.02 sec)
    
    mysql> select * from travelrecord;
    +---------+---------------+------------+------+------+
    | id      | user_id       | traveldate | fee  | days |
    +---------+---------------+------------+------+------+
    | 5000001 | mysql-server3 | 2016-01-02 |  100 |   10 |
    |       1 | mysql-server3 | 2016-01-01 |  100 |   10 |
    +---------+---------------+------------+------+------+
    2 rows in set (0.01 sec)
    
    mysql> select * from travelrecord;
    +---------+---------------+------------+------+------+
    | id      | user_id       | traveldate | fee  | days |
    +---------+---------------+------------+------+------+
    | 5000001 | mysql-server3 | 2016-01-02 |  100 |   10 |
    |       1 | mysql-server3 | 2016-01-01 |  100 |   10 |
    +---------+---------------+------------+------+------+
    2 rows in set (0.01 sec)
    
    mysql> select * from travelrecord;
    +---------+---------------+------------+------+------+
    | id      | user_id       | traveldate | fee  | days |
    +---------+---------------+------------+------+------+
    |       1 | mysql-server2 | 2016-01-01 |  100 |   10 |
    | 5000001 | mysql-server2 | 2016-01-02 |  100 |   10 |
    +---------+---------------+------------+------+------+
    

    从上面的输出结果,可以得出以下两点:

    一、该配置已实现读写分离,读出来的数据没有master节点的。

    二、MyCAT的随机分发不是基于statement的,即一个select语句查询其中一个节点,另外一个select语句查询另外一个节点。它分发针对的是片的,同一个select语句的结果是有不同dataNode返回的。

    不仅如此,从MyCAT日志中也可以获取读写分离的相关信息,当然,前提是MyCAT的日志级别是debug。

    日志相关信息如下:

    step4:验证mater挂了,slave依然能提供读的功能

    对于MySQL主从集群,我们的需求是master挂了,slave还能提供读的功能。

    1、首先,人为的关闭主库

    [root@mysql-server1 ~]# /etc/init.d/mysqld stop
    

    2、登录MyCAT

    [root@mysql-server1 ~]# mysql -utest -ptest -h127.0.0.1 -P8066 -DTESTDB
    

    3、插入数据

    mysql> insert into travelrecord(id,user_id,traveldate,fee,days)  values(10000001,@@hostname,20160103,100,10);
    ERROR 1184 (HY000): Connection refused
    mysql> select * from travelrecord;
    +---------+---------------+------------+------+------+
    | id      | user_id       | traveldate | fee  | days |
    +---------+---------------+------------+------+------+
    |       1 | mysql-server2 | 2016-01-01 |  100 |   10 |
    | 5000001 | mysql-server3 | 2016-01-02 |  100 |   10 |
    +---------+---------------+------------+------+------+
    2 rows in set (0.02 sec)
    

    可见无法插入数据,但不影响读取数据。

    至此,MyCAT实现MySQL的读写分离部署测试完毕。

    总结:

    1. 其实,刚开始配置的是readHost节点,配置如下:
     <dataHost name="localhost1" 
               maxCon="1000" 
               minCon="10" 
               balance="1"
               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">
    	<!-- can have multi read hosts -->
    	<readHost host="hostS1" url="192.168.244.146:3306" user="root" password="123456" />
        																</writeHost>
    </dataHost>
    

    但这种方式有个问题,即master挂了以后,slave也不能提供服务,而这违反了MySQL主从集群的初衷。

    1. 如果开启了事务模式,即set autocommit=0,则事务内的读走的是master节点,而不是从节点。
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
  • 相关阅读:
    Parameter Binding in ASP.NET Web API
    Which HTTP methods match up to which CRUD methods?
    ErrorHandling in asp.net web api
    HttpStatusCode
    Autofac Getting Started(默认的构造函数注入)
    Autofac Controlling Scope and Lifetime
    luvit 被忽视的lua 高性能框架(仿nodejs)
    undefined与null的区别
    VsCode中使用Emmet神器快速编写HTML代码
    字符串匹配---KMP算法
  • 原文地址:https://www.cnblogs.com/hhddd-1024/p/14584613.html
Copyright © 2011-2022 走看看