zoukankan      html  css  js  c++  java
  • mycat读写分离

    读写分离,简单的说就是把对数据库的读与写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。在很多系统中读操作的比例远高于写操作,所以对应的读操作的数据库可以有多台,通过负载均衡技术进一步分摊读操作的压力,让整个数据库系统高效,平稳地运行。而这些读写分离所需要的复杂数据库架构,要对开发人员和应用程序透明。这里我们通过mycat来实现上述的功能。

    mycat读写分离的控制由mycat的schema.xml配置文件中datahost标签的balance属性来实现。

    基于mysql的读写分离

    首先搭建MySQL的主从分离,因为这里只是测试mysql的读写分离,不再说明主从复制的搭建过程。主从搭建。

    主服务器:10.0.102.221
    从服务器:10.0.102.222
    备主服务器:10.0.102.179

    搭建过程: 在221和222之间搭建主从架构,在221和179之间搭建互为主从架构即可。也就是这三台服务器构成一个双主一从架构,主意和MySQL5.7的多源复制架构区分。
    多源复制

    搭建好测试需要的MySQL架构之后,然后开始配置mycat的读写分离。schema.xml中的主要部分配置文件如下:

            <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
                    <!-- auto sharding by id (long) 
                    <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur" /> -->
                    <table name="employee" dataNode="dn1"/>             #在这里没有分片操作,因此没有rule属性
            </schema>
            <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                    /> -->
            <dataNode name="dn1" dataHost="split-one" database="mytest" />            #指定dataNode
            <!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
            <dataNode name="jdbc_dn3"       dataHost="jdbchost" database="db3" /> -->
    
            <dataHost name="split-one" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                    <heartbeat>select user()</heartbeat>
    
             #这个writeHost标签包含的一个主从的架构配置,w为master服务,r为slave服务器 <writeHost host="hostM1" url="10.0.102.221:3306" user="root" password="123456"> <readHost host="hostS2" url="10.0.102.222:3306" user="root" password="123456" /> </writeHost>
    #这个writehost标签包含的是一个备用的主服务器。 <writeHost host="hostM2" url="10.0.102.179:3306" user="root" password="123456" /> </dataHost>

    上面配置修改成功之后,启动mycat,登录到管理端口:

    mysql> show @@datasource;
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | DATANODE | NAME   | TYPE  | HOST         | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | dn1      | hostM1 | mysql | 10.0.102.221 | 3306 | W    |      0 |   10 | 1000 |      14 |         0 |          0 |
    | dn1      | hostM2 | mysql | 10.0.102.179 | 3306 | W    |      0 |    1 | 1000 |       4 |         0 |          0 |
    | dn1      | hostS2 | mysql | 10.0.102.222 | 3306 | R    |      0 |    3 | 1000 |       7 |         0 |          0 |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    3 rows in set (0.01 sec)

    上面提到过,mycat的主从分离是有参数balance控制,下面根据不同的balance值测试对应读写分离。

    balance值为0时:不开启读写分离机制,所有的读操作都发送到当前可用的writeHost上。

    #插入数据,写入数据,发现这时候所有的读写都分配到当前可用的writeHost上,也就是主master上。
    mysql> show @@datasource; +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+ | DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD | +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+ | dn1 | hostM1 | mysql | 10.0.102.221 | 3306 | W | 0 | 10 | 1000 | 94 | 11 | 1 | | dn1 | hostM2 | mysql | 10.0.102.179 | 3306 | W | 0 | 1 | 1000 | 72 | 0 | 0 | | dn1 | hostS2 | mysql | 10.0.102.222 | 3306 | R | 0 | 6 | 1000 | 78 | 0 | 0 | +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+ 3 rows in set (0.00 sec) mysql>

    balance值为1时全部的readHost与stand by writeHost都参与select语句的负载均衡。

    mysql> show @@datasource;
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | DATANODE | NAME   | TYPE  | HOST         | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | dn1      | hostM1 | mysql | 10.0.102.221 | 3306 | W    |      0 |   10 | 1000 |      19 |         0 |          1 |
    | dn1      | hostM2 | mysql | 10.0.102.179 | 3306 | W    |      0 |    1 | 1000 |      18 |        10 |          0 |
    | dn1      | hostS2 | mysql | 10.0.102.222 | 3306 | R    |      0 |    3 | 1000 |      16 |         5 |          0 |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    3 rows in set (0.00 sec)

    #插入一条数据,是写在hostM1上,读的操作则分布在hostM2和hostS2上,测试select查询时,可以多查询几次。

    当balance值为2时所有的读操作都随机地在writeHost, readHost上分发。

    mysql> show @@datasource;
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | DATANODE | NAME   | TYPE  | HOST         | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | dn1      | hostM1 | mysql | 10.0.102.221 | 3306 | W    |      0 |   10 | 1000 |      20 |         6 |          0 |
    | dn1      | hostM2 | mysql | 10.0.102.179 | 3306 | W    |      0 |    1 | 1000 |       8 |         4 |          0 |
    | dn1      | hostS2 | mysql | 10.0.102.222 | 3306 | R    |      0 |    3 | 1000 |      14 |         7 |          0 |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    3 rows in set (0.00 sec)

    #整个架构中所有的服务器都参与读的均衡,然后再插入数据,发现还是只有主master上写!
    mysql> show @@datasource;
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | DATANODE | NAME   | TYPE  | HOST         | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | dn1      | hostM1 | mysql | 10.0.102.221 | 3306 | W    |      0 |   10 | 1000 |      32 |         6 |          2 |
    | dn1      | hostM2 | mysql | 10.0.102.179 | 3306 | W    |      0 |    1 | 1000 |      18 |         4 |          0 |
    | dn1      | hostS2 | mysql | 10.0.102.222 | 3306 | R    |      0 |    3 | 1000 |      24 |         7 |          0 |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    3 rows in set (0.01 sec)

    当balance值为3时:   所有的读请求都随机分配到writeHost对应的readHost上执行,writeHost不负担读压力,注意balance值为3只在mycat1.4版本及之后的版本中有。

    mysql> show @@datasource;
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | DATANODE | NAME   | TYPE  | HOST         | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | dn1      | hostM1 | mysql | 10.0.102.221 | 3306 | W    |      0 |   10 | 1000 |      14 |         0 |          0 |
    | dn1      | hostM2 | mysql | 10.0.102.179 | 3306 | W    |      0 |    1 | 1000 |       4 |         0 |          0 |
    | dn1      | hostS2 | mysql | 10.0.102.222 | 3306 | R    |      0 |    3 | 1000 |      17 |        10 |          0 |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    3 rows in set (0.00 sec)

    #所有的查询都被分配到对应的slave上面。

    基于mariadb的galera集群做读写分离

    mariadb的galera集群时真正的多主架构,集群中的每台服务器都可以写入数据。首先搭建mariadb集群,过程略;搭建之后,配置mycat的读写分离。

    schema.xml配置文件如下,和之前的mysql主从架构配置会有一些不同。

            <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
                    <!-- auto sharding by id (long) 
                    <table name="employee" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur" /> -->
                    <table name="employee" dataNode="dn1"/>
            </schema>
            <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                    /> -->
            <dataNode name="dn1" dataHost="split-one" database="mytest" />
            <!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
            <dataNode name="jdbc_dn3"       dataHost="jdbchost" database="db3" /> -->
    
            <dataHost name="split-one" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                    <heartbeat>show status like "wsrep%"</heartbeat>
    
                    <writeHost host="hostM1" url="10.0.102.204:3306" user="root"
                                       password="123456">
                    </writeHost>
    
                    <writeHost host="hostM2" url="10.0.102.221:3306" user="root"
                                       password="123456" >
                    </writeHost>
    
                    <writeHost host="hostM3" url="10.0.102.222:3306" user="root"
                                       password="123456" >
                    </writeHost>
            </dataHost>
    mysql> show @@datasource;
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | DATANODE | NAME   | TYPE  | HOST         | PORT | W/R  | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    | dn1      | hostM1 | mysql | 10.0.102.204 | 3306 | W    |      0 |    1 | 1000 |       1 |         0 |          0 |
    | dn1      | hostM2 | mysql | 10.0.102.221 | 3306 | W    |      0 |   10 | 1000 |      11 |         0 |          0 |
    | dn1      | hostM3 | mysql | 10.0.102.222 | 3306 | W    |      0 |    1 | 1000 |       1 |         0 |          0 |
    +----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
    3 rows in set (0.01 sec)
    
    mysql> show @@heartbeat;
    +--------+-------+--------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
    | NAME   | TYPE  | HOST         | PORT | RS_CODE | RETRY | STATUS | TIMEOUT | EXECUTE_TIME | LAST_ACTIVE_TIME    | STOP  |
    +--------+-------+--------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
    | hostM1 | mysql | 10.0.102.204 | 3306 |       1 |     0 | idle   |       0 | 19,19,19     | 2019-01-21 14:43:51 | false |
    | hostM2 | mysql | 10.0.102.221 | 3306 |       1 |     0 | idle   |       0 | 16,16,16     | 2019-01-21 14:43:51 | false |
    | hostM3 | mysql | 10.0.102.222 | 3306 |       1 |     0 | idle   |       0 | 17,17,17     | 2019-01-21 14:43:51 | false |
    +--------+-------+--------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
    3 rows in set (0.00 sec)
    
    mysql> 

    mariadb的读写分离基本与上面mysql主从保持一致,不再重复测试。

    当balance的值为0时:不进行读写分离,所有的读写都走配置的dataHost的第一个writeHost
    当balance值为1时:全部的readHost和stand by writeHost都参与select语句的负载均衡。如果第一个节点未带slave节点,则三个节点中,一个作为写,另外两个作为读
    当balance为2时所有的读操作随机地在writeHost,readHost上分发。
    balance值为3时所有的读请求都随机地分发至writeHost对应的readHost执行,writeHost不负担读的压力。如果writeHost没有对应的readHost,则查询分发至writeHost。

    测试的过程中需要注意:一条insert语句插入多条记录,write_load的值只增加1.
    在插入数据测试的时候,可以采用如下方式查看,插入一个特殊的值,来确定数据究竟插入到了哪一个服务器中。

    mysql> insert into employee(id, name) values(4, @@HOSTNAME);
    Query OK, 1 row affected (0.04 sec)
    
    mysql> select * from employee where id =4;
    +------+-------+
    | id   | name  |
    +------+-------+
    |    4 | test2 |
    +------+-------+
    1 row in set (0.06 sec)
    
    mysql> 
  • 相关阅读:
    linux高可用集群(HA)原理详解
    【C#/WPF】修改图像的DPI、Resolution
    【C#】图像的变形/变换/扭曲。用Emgu或YLScsFreeTransform(FreeImageTransformation)或MagickImage
    【C#】遍历List列表的同时,移除访问到的元素
    【WPF】动态设置Binding的ConverterParameter转换器参数
    【SVN/Visual Studio】清除/更换AnkhSVN的用户登录信息
    【C#】允许泛型方法<T>返回空值Null
    【C#】时间日期格式转换:long和DateTime相互转换
    【C#/WPF】ListView的MVVM例子,及禁止拖动ListView的头部Header
    【C#/WPF】保存BitmapImage数据到文件中
  • 原文地址:https://www.cnblogs.com/wxzhe/p/10298731.html
Copyright © 2011-2022 走看看