MyCat 读写分离 数据库分库分表 中间件 安装部署,及简单使用

MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。

MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度

网上很有多相关资源,也可以直接访问Mycat官网。

http://www.mycat.io/

环境

MySql-Master:192.168.252.121
MySql-Slave:192.168.252.122

Mycat:192.168.252.123

MySql 主从复制

参考我的另一篇文章-搭建 MySQL 5.7.19 主从复制

在 MySql-Master:192.168.252.121 建库,测试主从复制是否可用

CREATE DATABASE `db_1`;
CREATE DATABASE `db_2`;
CREATE DATABASE `db_3`;

Mycat 安装部署

cd /opt
tar -zxvf Mycat-server-1.6.5-release-20171029183033-linux.tar.gz -C /usr/local/

更好看目录结构,下tree(可选)

yum -y install tree
tree /usr/local/mycat/
/usr/local/mycat/
├── bin
│?? ├── dataMigrate.sh
│?? ├── init_zk_data.sh
│?? ├── mycat
│?? ├── rehash.sh
│?? ├── startup_nowrap.sh
│?? ├── wrapper-linux-ppc-64
│?? ├── wrapper-linux-x86-32
│?? └── wrapper-linux-x86-64
├── catlet
├── conf
│?? ├── autopartition-long.txt
│?? ├── auto-sharding-long.txt
│?? ├── auto-sharding-rang-mod.txt
│?? ├── cacheservice.properties
│?? ├── dbseq.sql
│?? ├── ehcache.xml
│?? ├── index_to_charset.properties
│?? ├── log4j2.xml
│?? ├── migrateTables.properties
│?? ├── myid.properties
│?? ├── partition-hash-int.txt
│?? ├── partition-range-mod.txt
│?? ├── rule.xml
│?? ├── schema.xml
│?? ├── sequence_conf.properties
│?? ├── sequence_db_conf.properties
│?? ├── sequence_distributed_conf.properties
│?? ├── sequence_time_conf.properties
│?? ├── server.xml
│?? ├── sharding-by-enum.txt
│?? ├── wrapper.conf
│?? ├── zkconf
│?? │?? ├── autopartition-long.txt
│?? │?? ├── auto-sharding-long.txt
│?? │?? ├── auto-sharding-rang-mod.txt
│?? │?? ├── cacheservice.properties
│?? │?? ├── ehcache.xml
│?? │?? ├── index_to_charset.properties
│?? │?? ├── partition-hash-int.txt
│?? │?? ├── partition-range-mod.txt
│?? │?? ├── rule.xml
│?? │?? ├── schema.xml
│?? │?? ├── sequence_conf.properties
│?? │?? ├── sequence_db_conf.properties
│?? │?? ├── sequence_distributed_conf-mycat_fz_01.properties
│?? │?? ├── sequence_distributed_conf.properties
│?? │?? ├── sequence_time_conf-mycat_fz_01.properties
│?? │?? ├── sequence_time_conf.properties
│?? │?? ├── server-mycat_fz_01.xml
│?? │?? ├── server.xml
│?? │?? └── sharding-by-enum.txt
│?? └── zkdownload
│??     └── auto-sharding-long.txt
.....
省略更多

7 directories, 95 files

安装 JDK

下载Linux环境下的jdk1.8,请去(官网)中下载jdk的安装文件

我在百度云盘分下的链接:http://pan.baidu.com/s/1jIFZF9s 密码:u4n4

上传在 /opt 目录

解压

cd /opt
tar zxvf jdk-8u144-linux-x64.tar.gz
mv jdk1.8.0_144/ /lib/jvm

配置环境变量

vi /etc/profile
#jdk
export JAVA_HOME=/lib/jvm
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH 

使环境变量生效

source /etc/profile

验证

[[email protected] ~]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

环境变量

设置 MYCAT_HOME 的变量

export PATH=${JAVA_HOME}/bin:${MYCAT_HOME}/lib:$PATH
export MYCAT_HOME=/usr/local/mycat/

使环境变量生效

source /etc/profile

配置 JDK 路径

告诉 Mycat 需要使用哪个 JDK

vim wrapper.conf
#********************************************************************
# Wrapper Properties
#********************************************************************
# Java Application
wrapper.java.command=/lib/jvm/bin/java
wrapper.working.dir=..

wrapper.conf jvm调优参数,不合理,需改进

# Java Additional Parameters
#wrapper.java.additional.1=
wrapper.java.additional.1=-DMYCAT_HOME=.
wrapper.java.additional.2=-server
wrapper.java.additional.3=-XX:MaxPermSize=64M
wrapper.java.additional.4=-XX:+AggressiveOpts
wrapper.java.additional.5=-XX:MaxDirectMemorySize=2G
wrapper.java.additional.6=-Dcom.sun.management.jmxremote
wrapper.java.additional.7=-Dcom.sun.management.jmxremote.port=1984
wrapper.java.additional.8=-Dcom.sun.management.jmxremote.authenticate=false
wrapper.java.additional.9=-Dcom.sun.management.jmxremote.ssl=false
wrapper.java.additional.10=-Xmx4G
wrapper.java.additional.11=-Xms1G

jvm参数调优,以16G内存服务器为例

# Java Additional Parameters
#wrapper.java.additional.1=
wrapper.java.additional.1=-DMYCAT_HOME=.
wrapper.java.additional.2=-server
wrapper.java.additional.3=-XX:MaxPermSize=64M
wrapper.java.additional.4=-XX:+AggressiveOpts
#堆内存适度大小,直接映射内存尽可能大,两种一起占据服务器的1/2-2/3的内存
wrapper.java.additional.5=-XX:MaxDirectMemorySize=6G
wrapper.java.additional.6=-Dcom.sun.management.jmxremote
wrapper.java.additional.7=-Dcom.sun.management.jmxremote.port=1984
wrapper.java.additional.8=-Dcom.sun.management.jmxremote.authenticate=false
wrapper.java.additional.9=-Dcom.sun.management.jmxremote.ssl=false
#无论扩展还是缩减新生代空间或老年代空间都需要进行Full GC,而Full GC会降低程序的吞吐量并导致更长的延迟。
wrapper.java.additional.10=-Xmx4G
wrapper.java.additional.11=-Xms4G

配置 Mycat

配置文件非常多.如果只是简单配置在不同的服务器上进行读写分离只需要配置两个文件 server.xmlschema.xml

schema.xml 中定义逻辑库,表、分片节点等内容
rule.xml 中定义分片规则
server.xml 中定义用户以及系统相关变量,如端口等

server.xml

server.xml 几乎保存了所有 mycat 需要的系统配置信息。其在代码内直接的映射类为 System Config 类。

vim server.xml
<user name="root" defaultAccount="true">
    <property name="password">123456</property>
    <property name="schemas">test_schema</property>

    <!-- 表级 DML 权限设置 -->
    <!--
    <privileges check="false">
        <schema name="test_schema" dml="0110" >
            <table name="tb01" dml="0000"></table>
            <table name="tb02" dml="1111"></table>
        </schema>
    </privileges>
     -->
</user>

<user name="user">
    <property name="password">user</property>
    <property name="schemas">test_schema</property>
    <property name="readOnly">true</property>
</user>

server.xml 中的标签本就不多,这个标签主要用于定义登录 mycat 的用户和权限。

例如上面的例子中,我定义了一个用户,用户名为 root 、密码也为 123456,可访问的 schema 也只有 test_schema 一个 逻辑库。

官方完整的默认配置 server.xml

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">809600000</property>

    <!--默认是65535 64K 用于sql解析时最大文本长度 -->
    <!--<property name="maxStringLiteralLength">65535</property>-->
    <!--<property name="sequnceHandlerType">1</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">3800000</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>-->
</system>

schema.xml

schema 标签用于定义 My Cat 实例中的逻辑库,My Cat 可以有多个逻辑库,每个逻辑库都有自己的相关配
置。可以使用 schema 标签来划分这些不同的逻辑库。

vim schema.xml
<?xml version="1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- 设置表的存储方式.schema name="test_schema" 与 server.xml中的 test_schema 设置一致  -->
    <schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="test_one" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-date"/>
    </schema>

    <!-- 设置dataNode 对应的数据库,及 mycat 连接的地址dataHost -->
    <dataNode name="dn1" dataHost="dh_test" database="db_1"/>
    <dataNode name="dn2" dataHost="dh_test" database="db_2"/>
    <dataNode name="dn3" dataHost="dh_test" database="db_3"/>

    <!-- mycat 逻辑主机dataHost对应的物理主机.其中也设置对应的mysql登陆信息 -->
    <dataHost name="dh_test" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
        <!--<heartbeat>select user()</heartbeat>-->
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="192.168.252.121:3306" user="root" password="mima">
            <readHost host="hostS2" url="192.168.252.122:3306" user="root" password="mima"/>
        </writeHost>
    </dataHost>

</mycat:schema>

如上所示的配置就配置了1个逻辑库,逻辑库的概念和 MYSQL 数据库中 Database 的概念相同,我们在查询这个逻辑库中表的时候需要切换到该逻辑库下才可以查询到所需要的表。

schema 标签

用于定义 My Cat 实例中的逻辑库,My Cat 可以有多个逻辑库,每个逻辑库都有自己的相关配
置。可以使用 schema 标签来划分这些不同的逻辑库。

data Node 属性

该属性用于绑定逻辑库到某个具体的 database 上,1.3 版本如果配置了 data Node,则不可以配置分片表,
1.4 可以配置默认分片,只需要配置需要分片的表即可

data Host 标签

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

name 属性

唯一标识 data Host 标签,供上层的标签使用。

max Con 属性

指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的 write Host、read Host 标签都会使用这个属性的值来实例化出连接池的最大连接数。

min Con 属性

指定每个读写实例连接池的最小连接,初始化连接池的大小。

balance 属性

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

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

write Type 属性

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

  1. write Type="0", 所有写操作发送到配置的第一个 write Host,第一个挂了切到还生存的第二个write Host,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
  2. write Type="1",所有写操作都随机的发送到配置的 write Host,1.5 以后废弃不推荐。

**switch Type 属性

-1 表示不自动切换
1 默认值,自动切换
2 基于 My SQL 主从同步的状态决定是否切换

db Type 属性

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

db Driver 属性

指定连接后端数据库使用的 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。

switch Type 属性

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

temp Read Host Available 属性

如果配置了这个属性 write Host 下面的 read Host 仍旧可用,默认 0 可配置(0、1)

rule.xml

rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有 table Rule 和 function 这两个标签。在具体使用过程中可以按照需求添加 table Rule 和 function。

vim rule.xml
<tableRule name="sharding-by-date">
    <rule>
        <columns>create_time</columns>
        <algorithm>sharding-by-date-day</algorithm>
    </rule>
</tableRule>

<function name="sharding-by-date-day" class="io.mycat.route.function.PartitionByDate">
    <property name="dateFormat">yyyy-MM-dd</property>
    <property name="sBeginDate">2017-11-15</property>
    <property name="sEndDate">2017-11-17</property>
    <property name="sPartionDay">1</property>
</function>

这个标签定义表规则。
定义的表规则,在 schema.xml:

tableRule name="sharding-by-date"

<schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
    <table name="test_one" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-date"/>
</schema>

启动 Mycat

/usr/local/mycat/bin
./mycat start

查看日志

启动 mycat 的日志

less /usr/local/mycat/logs/wrapper.log

访问 mycat 的日志

less /usr/local/mycat/logs/mycat.log

使用 Mycat

登录 Mycat 切换到 test_schema 逻辑库

mysql -uroot -p123456 -h192.168.252.123 -P 8066

创建库/表

mysql> use test_schema;
Database changed
mysql> show tables;
+-----------------------+
| Tables in test_schema |
+-----------------------+
| test_one              |
+-----------------------+
1 row in set

mysql> 

只需要在 Mycat 服务器执行以下脚本,就会自动同步到 MySql-Master:192.168.252.121 MySql-Slave:192.168.252.122

mysql> CREATE TABLE `test_one` (
    `id` BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT ‘id‘,
    `name` VARCHAR (50) DEFAULT NULL COMMENT ‘名称‘,
    `remark` VARCHAR (500) DEFAULT NULL COMMENT ‘备注‘,
    `create_time` datetime DEFAULT NULL COMMENT ‘创建时间‘,
    PRIMARY KEY (`id`)
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8mb4 COMMENT = ‘测试‘;

Query OK, 0 rows affected

登录 Mycat 管理端

mysql -uroot -p123456 -h192.168.252.123 -P 9066

RS_CODE 为 1 表示心跳正常,--查看读写分离的机器配置情况

mysql> show @@datanode;
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| NAME | DATHOST      | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| dn1  | dh_test/db_1 |     0 | mysql |      0 |    3 | 1000 |      11 |          0 |        0 |       0 |            -1 |
| dn2  | dh_test/db_2 |     0 | mysql |      0 |    3 | 1000 |       7 |          0 |        0 |       0 |            -1 |
| dn3  | dh_test/db_3 |     0 | mysql |      0 |    4 | 1000 |      26 |          0 |        0 |       0 |            -1 |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
3 rows in set

mysql> show @@heartbeat;
+--------+-------+-----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
| NAME   | TYPE  | HOST            | PORT | RS_CODE | RETRY | STATUS | TIMEOUT | EXECUTE_TIME | LAST_ACTIVE_TIME    | STOP  |
+--------+-------+-----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
| hostM1 | mysql | 192.168.252.121 | 3306 |       1 |     0 | idle   |       0 | 2,3,3        | 2017-11-17 16:54:26 | false |
| hostS2 | mysql | 192.168.252.122 | 3306 |       1 |     0 | idle   |       0 | 2,2,2        | 2017-11-17 16:54:26 | false |
+--------+-------+-----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
2 rows in set

mysql> 

测试分片

按日期(天)分片

登录 Mycat 管理端

mysql -uroot -p123456 -h192.168.252.123 -P 9066

RS_CODE 为 1 表示心跳正常,--查看读写分离的机器配置情况

mysql> show @@datanode;
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| NAME | DATHOST      | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| dn1  | dh_test/db_1 |     0 | mysql |      0 |    3 | 1000 |      11 |          0 |        0 |       0 |            -1 |
| dn2  | dh_test/db_2 |     0 | mysql |      0 |    3 | 1000 |       7 |          0 |        0 |       0 |            -1 |
| dn3  | dh_test/db_3 |     0 | mysql |      0 |    4 | 1000 |      26 |          0 |        0 |       0 |            -1 |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
3 rows in set

配置按日期(天)分片,2017-11-15,2017-11-16,2017-11-17 ,一天一个分片,执行完一下的 sql 可以发现数据 ,会按照分片规则进入不同的,分片,数据库

rule.xml

<tableRule name="sharding-by-date">
    <rule>
        <columns>create_time</columns>
        <algorithm>sharding-by-date-day</algorithm>
    </rule>
</tableRule>

<function name="sharding-by-date-day" class="io.mycat.route.function.PartitionByDate">
    <property name="dateFormat">yyyy-MM-dd</property>
    <property name="sBeginDate">2017-11-15</property>
    <property name="sEndDate">2017-11-17</property>
    <property name="sPartionDay">1</property>
</function>

name 属性指定唯一的名字,用于标识不同的表规则。

内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。

columns 内指定要拆分的列名字。

algorithm 使用 function 标签中的 name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。table 标签内使用。让逻辑表使用这个规则进行分片。

配置说明:

  • columns :标识将要分片的表字段
  • algorithm :分片函数
  • dateFormat :日期格式
  • sBeginDate :开始日期
  • sEndDate:结束日期
  • sPartionDay :分区天数,即默认从开始日期算起,分隔 5 天一个分区

schema.xml

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

    <!-- 设置表的存储方式.schema name="test_schema" 与 server.xml中的 test_schema 设置一致  -->
    <schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="test_one" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-date"/>
    </schema>

    <!-- 设置dataNode 对应的数据库,及 mycat 连接的地址dataHost -->
    <dataNode name="dn1" dataHost="dh_test" database="db_1"/>
    <dataNode name="dn2" dataHost="dh_test" database="db_2"/>
    <dataNode name="dn3" dataHost="dh_test" database="db_3"/>

    <!-- mycat 逻辑主机dataHost对应的物理主机.其中也设置对应的mysql登陆信息 -->
    <dataHost name="dh_test" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
        <!--<heartbeat>select user()</heartbeat>-->
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="192.168.252.121:3306" user="root" password="mima">
            <readHost host="hostS2" url="192.168.252.122:3306" user="root" password="mima"/>
        </writeHost>
    </dataHost>

</mycat:schema>

登录 Mycat 服务端

mysql -uroot -p123456 -h192.168.252.123 -P 8066
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_1‘, ‘2017-11-15 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_2‘, ‘2017-11-16 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_3‘, ‘2017-11-17 00:00:00‘);

在 MySql-Master 执行 ,查看分片是否均匀

mysql -uroot -p123456 -h192.168.252.121 -P 3306
mysql> select min(create_time),max(create_time) from db_1.test_one;
+---------------------+---------------------+
| min(create_time)    | max(create_time)    |
+---------------------+---------------------+
| 2017-11-15 00:00:00 | 2017-11-15 00:00:00 |
+---------------------+---------------------+
1 row in set

mysql> select min(create_time),max(create_time) from db_2.test_one;
+---------------------+---------------------+
| min(create_time)    | max(create_time)    |
+---------------------+---------------------+
| 2017-11-16 00:00:00 | 2017-11-16 00:00:00 |
+---------------------+---------------------+
1 row in set

mysql> select min(create_time),max(create_time) from db_3.test_one;
+---------------------+---------------------+
| min(create_time)    | max(create_time)    |
+---------------------+---------------------+
| 2017-11-17 00:00:00 | 2017-11-17 00:00:00 |
+---------------------+---------------------+
1 row in set

mysql> 

自然月分片

在 MySql-Master:192.168.252.121 建库,测试主从复制是否可用

CREATE DATABASE `db_1`;
CREATE DATABASE `db_2`;
CREATE DATABASE `db_3`;
CREATE DATABASE `db_4`;
CREATE DATABASE `db_5`;
CREATE DATABASE `db_6`;
CREATE DATABASE `db_7`;
CREATE DATABASE `db_8`;
CREATE DATABASE `db_9`;
CREATE DATABASE `db_10`;
CREATE DATABASE `db_11`;
CREATE DATABASE `db_12`;

登录 Mycat 管理端

mysql -uroot -p123456 -h192.168.252.123 -P 9066

查看分片情况

mysql> show @@datanode;
+------+---------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| NAME | DATHOST       | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |
+------+---------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| dn1  | dh_test/db_1  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn10 | dh_test/db_10 |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn11 | dh_test/db_11 |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn12 | dh_test/db_12 |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn2  | dh_test/db_2  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn3  | dh_test/db_3  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn4  | dh_test/db_4  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn5  | dh_test/db_5  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn6  | dh_test/db_6  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn7  | dh_test/db_7  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn8  | dh_test/db_8  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn9  | dh_test/db_9  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
+------+---------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
12 rows in set

mysql> 

rule.xml

按月份列分区 ,每个自然月一个分片

<tableRule name="sharding-by-month">
    <rule>
        <columns>create_time</columns>
        <algorithm>partbymonth</algorithm>
    </rule>
</tableRule>

<function name="partbymonth" class="io.mycat.route.function.PartitionByMonth">
    <property name="dateFormat">yyyy-MM-dd</property>
    <property name="sBeginDate">2017-01-01</property>
</function>

配置说明:

  • columns 分片字段,字符串类型
  • dateFormat : 日期字符串格式
  • sBeginDate : 开始日期

schema.xml

<?xml version="1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- 设置表的存储方式.schema name="test_schema" 与 server.xml中的 test_schema 设置一致  -->
    <schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="test_one" primaryKey="id" dataNode="dn$1-12" rule="sharding-by-month"/>
    </schema>

    <!-- 设置dataNode 对应的数据库,及 mycat 连接的地址dataHost -->
    <dataNode name="dn1"  dataHost="dh_test" database="db_1"  />
    <dataNode name="dn2"  dataHost="dh_test" database="db_2"  />
    <dataNode name="dn3"  dataHost="dh_test" database="db_3"  />
    <dataNode name="dn4"  dataHost="dh_test" database="db_4"  />
    <dataNode name="dn5"  dataHost="dh_test" database="db_5"  />
    <dataNode name="dn6"  dataHost="dh_test" database="db_6"  />
    <dataNode name="dn7"  dataHost="dh_test" database="db_7"  />
    <dataNode name="dn8"  dataHost="dh_test" database="db_8"  />
    <dataNode name="dn9"  dataHost="dh_test" database="db_9"  />
    <dataNode name="dn10" dataHost="dh_test" database="db_10" />
    <dataNode name="dn11" dataHost="dh_test" database="db_11" />
    <dataNode name="dn12" dataHost="dh_test" database="db_12" />

    <!-- mycat 逻辑主机dataHost对应的物理主机.其中也设置对应的mysql登陆信息 -->
    <dataHost name="dh_test" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
        <!--<heartbeat>select user()</heartbeat>-->
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="192.168.252.121:3306" user="root" password="mima">
            <readHost host="hostS2" url="192.168.252.122:3306" user="root" password="mima"/>
        </writeHost>
    </dataHost>

</mycat:schema>

登录 Mycat 服务端

mysql -uroot -p123456 -h192.168.252.123 -P 8066

只需要在 Mycat 服务器执行以下脚本,就会自动同步到 MySql-Master:192.168.252.121 MySql-Slave:192.168.252.122

mysql> CREATE TABLE `test_one` (
    `id` BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT ‘id‘,
    `name` VARCHAR (50) DEFAULT NULL COMMENT ‘名称‘,
    `remark` VARCHAR (500) DEFAULT NULL COMMENT ‘备注‘,
    `create_time` datetime DEFAULT NULL COMMENT ‘创建时间‘,
    PRIMARY KEY (`id`)
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8mb4 COMMENT = ‘测试‘;

Query OK, 0 rows affected
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_1‘,  ‘2017-01-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_2‘,  ‘2017-02-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_3‘,  ‘2017-03-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_4‘,  ‘2017-04-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_5‘,  ‘2017-05-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_6‘,  ‘2017-06-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_7‘,  ‘2017-07-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_8‘,  ‘2017-08-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_9‘,  ‘2017-09-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_10‘, ‘2017-10-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_11‘, ‘2017-11-10 00:00:00‘);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( ‘测试数据‘, ‘会分片到 db_12‘, ‘2017-12-10 00:00:00‘);

在 MySql-Master 执行 ,查看分片是否均匀

mysql -uroot -p123456 -h192.168.252.121 -P 3306
select min(create_time),max(create_time) from db_1.test_one;
select min(create_time),max(create_time) from db_2.test_one;
select min(create_time),max(create_time) from db_3.test_one;
select min(create_time),max(create_time) from db_4.test_one;
select min(create_time),max(create_time) from db_5.test_one;
select min(create_time),max(create_time) from db_6.test_one;
select min(create_time),max(create_time) from db_7.test_one;
select min(create_time),max(create_time) from db_8.test_one;
select min(create_time),max(create_time) from db_9.test_one;
select min(create_time),max(create_time) from db_10.test_one;
select min(create_time),max(create_time) from db_11.test_one;
select min(create_time),max(create_time) from db_12.test_one;

注意

启动MyCAT之前,需要先检查一些配置:

Mysql的主从复制是否正常,这个检查我在文章开头,搭建 MySQL 5.7.19 主从复制,文章链接里面有介绍

java的版本需要是1.7或以上;

Mysql的配置文件需要加一行lower_case_table_names = 1在[mysqld]栏目中,这个设置为Mysql大小写不敏感,否则可能会发生表找不到的问题;

在示例的2个数据 MySql-Master 和 MySql-Slave 上,新建3个数据库 test_one,test_two,test_three, 如不新建,可能提示找不到数据库ERROR 3009 (HY000): java.lang.IllegalArgumentException: Invalid DataSource:0(这个提示不够友好,是在运行很长一段时间后才提示);

添加 MYCAT_HOME 环境变量指向解压的mycat目录,主要是为了一些bin目录下的脚本的使用。

Contact

  • 作者:鹏磊
  • 出处:http://www.ymq.io/2017/11/15/mycat
  • Email:[email protected]
  • 版权归作者所有,转载请注明出处
  • Wechat:关注公众号,"搜云库",专注于开发技术的研究与知识分享

原文地址:http://blog.51cto.com/8888940/2060963

时间: 2024-10-07 22:38:43

MyCat 读写分离 数据库分库分表 中间件 安装部署,及简单使用的相关文章

Mycat读写分离和分库分表配置

Mycat是一个开源的分布式数据库系统,不同于oracle和mysql,Mycat并没有存储引擎,但是Mycat实现了mysql协议,前段用户可以把它当做一个Proxy.其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端mysql存储引擎里面.最新版本的Mycat不仅支持mysql,还可以支持MS SqlServer,Oracle,DB2等关系型数据库,而且还支持MongoDB这种NoSQL.Mycat对调用者屏蔽了后端存储具体实现. Mycat的原理是先拦截用户的SQL语句并做分

数据库分库分表中间件 Sharding-JDBC 源码分析 —— 分布式主键

关注**微信公众号:[芋道源码]**有福利: RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表 RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址 您对于源码的疑问每条留言都将得到认真回复.甚至不知道如何读源码也可以请教噢. 新的源码解析文章实时收到通知.每周更新一篇左右. 认真的源码交流微信群. 本文主要基于 Sharding-JDBC 1.5.0 正式版 1. 概述 2.KeyGenerator 2.1 D

Windows环境Mycat数据库分库分表中间件部署

下载地址MYCAT官方网站 jdk安装配置 首先去oracle官网下载并安装jdk8,添加环境变量,JAVA_HOME设置为D:\Worksoftware\Java\jdk1.8 CLASSPATH设置为.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar path系统变量追加%JAVA_HOME%\bin; Mycat安装配置 首先添加Windows环境变量,MYCAT_HOME设置为安装目录E:\WorkSoftWare\MycatServer1.5 为了降

Mysql系列五:数据库分库分表中间件mycat的安装和mycat配置详解

一.mycat的安装 环境准备:准备一台虚拟机192.168.152.128 1. 下载mycat cd /softwarewget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz 2. 解压mycat tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz 3. 剪切mycat到/usr/local目录下

Ameba读写分离_mycat分库分表_redis缓存

1 数据库的读写分离 1.1 Amoeba实现读写分离 1.1.1 定义 Amoeba是一个以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy 优点: 配置读写分离时较为简单.配置文件编写方便 可以做到整个数据库的读写分离 占用的资源较少. 缺点: 不能实现高可用 现在不更新维护了 1.2 搭建amoeba 1.2.1 安装JDK 说明:Amoeba的使用依赖于JDK. 1.2.2 安装Amoeba 说明:将Amoeba文件拖入/usr/local/src/ 将其解压 1.2

数据库分库分表中间件 Sharding-JDBC 源码分析 —— SQL 解析(六)之删除SQL

关注微信公众号:[芋道源码]有福利: RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表 RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址 您对于源码的疑问每条留言都将得到认真回复.甚至不知道如何读源码也可以请教噢. 新的源码解析文章实时收到通知.每周更新一篇左右. 认真的源码交流微信群. 本文主要基于 Sharding-JDBC 1.5.0 正式版 1. 概述 2. DeleteStatement 3. #p

170123、数据库分库分表策略的具体实现方案

相关文章: 1. 使用Spring AOP实现MySQL数据库读写分离案例分析 2.MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解 :http://blog.csdn.net/xlgen157387/article/details/51331244 3.MySQL主从复制的常见拓扑.原理分析以及如何提高主从复制的效率总结 :http://blog.csdn.net/xlgen157387/article/details/52451613 4.使用mysqlreplic

【干货】数据库分库分表基础和实践

数据库架构的演变在业务数据量比较少的时代,我们使用单机数据库就能满足业务使用,随着业务请求量越来越多,数据库中的数据量快速增加,这时单机数据库已经不能满足业务的性能要求,数据库主从复制架构随之应运而生. 主从复制是将数据库写操作和读操作进行分离,使用多个只读实例(slaver replication)负责处理读请求,主实例(master)负责处理写请求,只读实例通过复制主实例的数据来保持与主实例的数据一致性.由于只读实例可以水平扩展,所以更多的读请求不成问题,随着云计算.大数据时代的到来,事情并

数据库分库分表策略的具体实现方案

一.MySQL扩展具体的实现方式 随着业务规模的不断扩大,需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量. 关于数据库的扩展主要包括:业务拆分.主从复制,数据库分库与分表.这篇文章主要讲述数据库分库与分表 (1)业务拆分 业务起步初始,为了加快应用上线和快速迭代,很多应用都采用集中式的架构.随着业务系统的扩大,系统变得越来越复杂,越来越难以维护,开发效率变得越来越低,并且对资源的消耗也变得越来越大,通过硬件提高系统性能的方式带来的成本也越来越高. 因此,在选型初期,一个