MySQL:10.MyCAT实现读写分离

简介

关键特性

支持SQL92标准
支持MySQL、Oracle、DB2、SQL Server、PostgreSQL等DB的常见SQL语法
遵守Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理。
基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluster集群。
支持Galera for MySQL集群,Percona Cluster或者MariaDB cluster
基于Nio实现,有效管理线程,解决高并发问题。
支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数,支持跨库分页。
支持单库内部任意join,支持跨库2表join,甚至基于caltlet的多表join。
支持通过全局表,ER关系的分片策略,实现了高效的多表join查询。
支持多租户方案。
支持分布式事务(弱xa)。
支持XA分布式事务(1.6.5)。
支持全局序列号,解决分布式下的主键生成问题。
分片规则丰富,插件化开发,易于扩展。
强大的web,命令行监控。
支持前端作为MySQL通用代理,后端JDBC方式支持Oracle、DB2、SQL Server 、 mongodb 、巨杉。
支持密码加密
支持服务降级
支持IP白名单
支持SQL黑名单、sql注入攻击拦截
支持prepare预编译指令(1.6)
支持非堆内存(Direct Memory)聚合计算(1.6)
支持PostgreSQL的native协议(1.6)
支持mysql和oracle存储过程,out参数、多结果集返回(1.6)
支持zookeeper协调主从切换、zk序列、配置zk化(1.6)
支持库内分表(1.6)
集群基于ZooKeeper管理,在线升级,扩容,智能优化,大数据处理(2.0开发版)。

什么是MYCAT

一个彻底开源的,面向企业应用开发的大数据库集群
支持事务、ACID、可以替代MySQL的加强版数据库
一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server
结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
一个新颖的数据库中间件产品

MYCAT监控

支持对Mycat、Mysql性能监控
支持对Mycat的JVM内存提供监控服务
支持对线程的监控
支持对操作系统的CPU、内存、磁盘、网络的监控

环境

第一步:下载安装

1.下载

http://dl.mycat.io

wget http://dl.mycat.io/1.6.7.1/Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz
tar vxf Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz
chmod -R 755 mycat/
mkdir mycat/logs
mv mycat/ /usr/local/

2.设置环境变量

echo "MYCAT_HOME=/usr/local/mycat" >> /etc/profile
echo 'export PATH=$MYCAT_HOME/bin:$PATH' >> /etc/profile
cat /etc/profile
source /etc/profile

3.schema.xml文件配置

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

    <!--6666666666-->
    <!--定义逻辑库名-->
    <!--sqlMaxLimit:每条执行的 SQL 语句,如果没有加上 limit 语句,MyCat 也会自动的加上所对的值-->
    <!--这里的dataNode="kpcx"对应下边的dataNode name="kpcx"-->
    <schema name="kpcx" checkSQLschema="false" sqlMaxLimit="1000" dataNode="kpcx">
    </schema>

    <schema name="kpcx_coupon" checkSQLschema="false" sqlMaxLimit="1000" dataNode="kpcx_coupon">
    </schema>

    <!---->
    <!--这里的kpcx对应上文的dataNode="kpcx"-->
    <!--这里的dataHost="localhost"对应下文的<dataHost name="localhost1"-->
    <!--这里的database="db1"为服务器上实际数据库名称-->
    <dataNode name="kpcx" dataHost="localhost" database="kpcx" />
    <dataNode name="kpcx_coupon" dataHost="localhost" database="kpcx_coupon" />

    <!--balance="2",所有读操作都随机的在 writeHost、readhost 上分发。-->
    <!-- writeType="0", 所有写操作发送到配置的第一个 writeHost
                        第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .-->
    <!--switchType  切换类型:3 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)心跳语句为 show status like ‘wsrep%’-->

    <dataHost name="localhost" maxCon="20000" minCon="50" balance="2" writeType="0" dbType="mysql" dbDriver="native" switchType="3" >
        <!--心跳检测-->
        <heartbeat>show status like 'wsrep%'</heartbeat>
        <writeHost host="hostM1" url="192.168.1.81:3306" user="kpcx" password="123456" />
        <writeHost host="hostS2" url="192.168.1.82:3306" user="kpcx" password="123456" />
        <writeHost host="hostS3" url="192.168.1.83:3306" user="kpcx" password="123456" />
    </dataHost>
</mycat:schema>

4.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. -->
<!--6666666666-->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
    <system>
    <property name="nonePasswordLogin">0</property> <!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户-->
    <property name="useHandshakeV10">1</property>
    <property name="useSqlStat">0</property>  <!-- 1为开启实时统计、0为关闭 -->
    <property name="useGlobleTableCheck">0</property>  <!-- 1为开启全加班一致性检测、0为关闭 -->

        <property name="sequnceHandlerType">2</property>
    <property name="subqueryRelationshipCheck">false</property> <!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false -->
      <!--  <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
        <!--  <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号-->
    <!-- <property name="processorBufferChunk">40960</property> -->
    <!-- 
    <property name="processors">1</property> 
    <property name="processorExecutor">32</property> 
     -->
        <!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
        <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">64k</property>

        <!--
            单位为k
        -->
        <property name="spillsFileBufferSize">1k</property>

        <property name="useStreamOutput">0</property>

        <!--
            单位为m
        -->
        <property name="systemReserveMemorySize">384m</property>


        <!--是否采用zookeeper协调切换  -->
        <property name="useZKSwitch">false</property>

        <!-- XA Recovery Log日志路径 -->
        <!--<property name="XARecoveryLogBaseDir">./</property>-->

        <!-- XA Recovery Log日志名称 -->
        <!--<property name="XARecoveryLogBaseName">tmlog</property>-->
        <!--如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接-->
        <property name="strictTxIsolation">false</property>

        <property name="useZKSwitch">true</property>

    </system>

    <!-- 全局SQL防火墙设置 -->
    <!--白名单可以使用通配符%或着*-->
    <!--例如<host host="127.0.0.*" user="root"/>-->
    <!--例如<host host="127.0.*" user="root"/>-->
    <!--例如<host host="127.*" user="root"/>-->
    <!--例如<host host="1*7.*" user="root"/>-->
    <!--这些配置情况下对于127.0.0.1都能以root账户登录-->
    <!--
    <firewall>
       <whitehost>
          <host host="1*7.0.0.*" user="root"/>
       </whitehost>
       <blacklist check="false">
       </blacklist>
    </firewall>
    -->

    <user name="mycat" defaultAccount="true">
        <property name="password">123456</property>
        <property name="schemas">kpcx,kpcx_coupon</property>
    </user>

    <user name="user">
        <property name="password">user</property>
        <property name="schemas">kpcx,kpcx_coupon</property>
        <property name="readOnly">true</property>
    </user>

</mycat:server>

注意:

Linux 下部署安装 MySQL,默认不忽略表名大小写
需要手动到/etc/my.cnf 下配置lower_case_table_names=1 使 Linux 环境下 MySQL 忽略表名大小写,否则使用 MyCAT 的时候会提示找不到表的错误!

主要文件说明

conf 目录下存放配置文件
    server.xml 是 Mycat 服务器参数调整和用户授权的配置文件
    schema.xml 是逻辑库定义和表以及分片定义的配置文件
    rule.xml 是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件,也在这个目录下
    配置文件修改,需要重启 Mycat 或者通过 9066 端口 reload
. lib 目录下主要存放 mycat 依赖的一些 jar 文件. 
日志存放在 logs/mycat.log 中,每天一个文件,日志的配置是在 conf/log4j.xml 中,根据自己的需要,可以调整输出级别为 debug,debug级别下,会输出更多的信息,方便排查问题.

schema.xml文件说明 - dataHost标签

作为 Schema.xml 中最后的一个标签,该标签在 mycat 逻辑库中也是作为最底层的标签存在,直接定义了具
体的数据库实例、读写分离配置和心跳语句。现在我们就解析下这个标签。

name        唯一标识 dataHost 标签,供上层的标签使用。
maxCon      指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的 writeHost、readHost 标签都会使用这个属性的值来实例化出连接池的最大连接数
minCon      指定每个读写实例连接池的最小连接,初始化连接池的大小。

balance     负载均衡类型,目前的取值有 3 种:
            balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
            balance="1",全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡
                        简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备)
                        正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。
            balance="2",所有读操作都随机的在 writeHost、readhost 上分发。
            balance="3",所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力
                        注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。

writeType   负载均衡类型,目前的取值有 3 种:
            writeType="0", 所有写操作发送到配置的第一个 writeHost
                            第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
            writeType="1",所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。

switchType  切换类型
            -1 表示不自动切换
            1 默认值,自动切换
            2 基于 MySQL 主从同步的状态决定是否切换:心跳语句为 show slave status
            3 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)心跳语句为 show status like ‘wsrep%’

dbType      指定后端连接的数据库类型,目前支持二进制的 mysql 协议,还有其他使用 JDBC 连接的数据库。例如:mongodb、oracle、spark 等。

dbDriver    指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。
            使用 native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和 maridb。
            其他类型的数据库则需要使用 JDBC 驱动来支持。从 1.6 版本开始支持 postgresql 的 native 原始协议。
            如果使用 JDBC 的话需要将符合 JDBC 4 标准的驱动 JAR 包放到 MYCAT\lib 目录下,并检查驱动 JAR 包中包括如下目录结构的文件:META-INF\services\java.sql.Driver。
            在这个文件内写上具体的 Driver 类名,例如:com.mysql.jdbc.Driver

tempReadHostAvailable   如果配置了这个属性 writeHost 下面的 readHost 仍旧可用,默认 0 可配置(0、1)。

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 上去。

host        用于标识不同实例,一般 writeHost 我们使用*M1,readHost 我们用*S1。

url         后端实例连接地址,如果是使用 native 的 dbDriver,则一般为 address:port 这种形式。
            用 JDBC 或其他的dbDriver,则需要特殊指定。当使用 JDBC 时则可以这么写:jdbc:mysql://localhost:3306/。

user        后端存储实例需要的用户名字。
password    后端存储实例需要的密码。
weight      权重 配置在 readhost 中作为读节点的权重(1.4 以后)。
usingDecrypt    是否对密码加密默认 0 否 如需要开启配置 1,同时使用加密程序对密码加密

常用命令

mycat restart
mycat pause

mycat stop
mycat start

mycat status

## 前台运行
mycat console
## 添加到系统自动启动(暂未实现)
mycat install
## 取消随系统自动启动(暂未实现)
mycat remove

附录:

官网:http://www.mycat.io/

推荐阅读更多精彩内容