初识Mycat以及数据分片

Mycat概述


Mycat并不是一个存储数据的服务器,更像是一个连接各种数据的数据引擎。对于开发人员来说,Mycat就是一款分库分表的工具。只是该工具对于分库分表的性能相对高处很多,而且他不仅仅可以用做分库分表,还能用做读写分离、以及容灾备份。

 

Mycat为什么被称为数据库中间件


在这里插入图片描述

被称为中间件要从他的一个主要功能说起,那就是分片分库。对于分片分库的所有支持和操作,不管是路由,分发等等都并没有给真是的数据库带来存储的类似存储引擎的作用,只是对保证了多库,分表的数据有效分离和获取。图中的位置就是为了突出Mycat它的一个作用,已经它在我们整个系统架构中间的位置。

 

Mycat的安装与配置


这里安装配置不多说,就是安装JDK和mycat的解压,mycat不需要预编译安装,解压直接使用就行

[root@mysql ] yum list java-*

[root@mysql ] yum install java-1.8.0-openjdk

[root@mysql ]mv Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz  /usr/src/

[root@mysql ]tar xf  Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz

[root@mysql ]cd /usr/local/mycat/bin

[root@mysql bin]# ./mycat start

[root@mysql ] yum list java-*

[root@mysql ] yum install java-1.8.0-openjdk

[root@mysql ]mv Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz  /usr/src/

[root@mysql ]tar xf  Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz

[root@mysql ]cd /usr/local/mycat/bin

[root@mysql bin]# ./mycat start

 

Mycat的报错解决


[root@mysql ~]# tail -100f /usr/local/mycat/logs/wrapper.log

STATUS | wrapper  | 2020/03/27 08:39:11 | Launching a JVM...

INFO   | jvm 2    | 2020/03/27 08:39:12 | OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=64M; support was removed in 8.0

ERROR  | wrapper  | 2020/03/27 08:39:12 | JVM exited while loading the application.

INFO   | jvm 2    | 2020/03/27 08:39:12 | Error: Exception thrown by the agent : java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException: mysql: mysql: Name or service not known

 

如果mycat报错,无非是内存问题或者是主机名的问题,修改方法如下所示

[root@mysql ~]# vim /usr/local/mycat/conf/wrapper.conf

wrapper.java.additional.5=-XX:MaxDirectMemorySize=512M

wrapper.java.additional.10=-Xmx512M

wrapper.java.additional.11=-Xms512M

 

[root@mysql ~]# vim /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 mysql

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6 mysql

 

Mycat的启动和登入


启动Mycat

[root@mysql ~]# /usr/local/mycat/bin/mycat start

[root@mysql ~]# /usr/local/mycat/bin/mycat status

Mycat-server is running (3731).

[root@mysql ~]# netstat -tpln | grep 8066  --成功启动后通过mysql客户端工具输入root密码123456就可以登入到mycat了

tcp        0      0 :::8066                     :::*                        LISTEN      3733/java  

 

登入mycat中间件

 

(1)客户端工具sqllog进行登入

 

 

(2)linux上MySQL客户端工具进行登入

[root@slave2 ~]# mysql -uroot -p123456 -h 192.168.179.69 -P8066 -DTESTDB

mysql> show databases;

+----------+

| TESTDB   |

+----------+

 

server.xml


server.xml: mycat的系统信息等。

<user name="root"> //应用程序中配置的用户名、密码及数据库名称
    <property name="password">123456</property>
    <property name="schema">TESTDB</property> //指定的schema
</user>

 

schema.xml


schema.xml: 定义逻辑表,表分片节点信息等。

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

    <!-- schema标签主要用于定义Mycat实例中的逻辑库。Mycat可以有多个逻辑库,每个逻辑库都有自己相关的配置 -->
    <!-- 可以使用schema标签来划分不同的逻辑库,如果不配置schema标签,则所有的表配置都会属于同一个默认的逻辑库 -->
    <!-- name="TESTDB" 给Mycat定义逻辑库名称 -->
    <!-- checkSQLschema属性值为true的时候,如果我们执行语句select * from TESTDB.table;该设置会讲TESTDB截取掉,SQL变成select * from table;该规则只能截掉schema上指定的库 -->
    <!-- sqlMaxLimit属性设置为100时,每次执行的SQL语句如果没有加上limit语句,Mycat会自动加上limit 100;不设置就会返回查询到的所有信息 -->
    <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">

        <!-- table标签定义了Mycat中的逻辑表,所有需要拆分的表都需要在table标签中定义。-->
        <!-- name属性定义逻辑表的名称,同一个schema标签中定义的table名字必须唯一 -->
        <!-- dataNode属性该属性的值需要与下面dataNode标签中的name属性的值相互对应。如果有多个值,使用','分隔 ,这个也代表需要拆分的虚拟表所在的真实节点-->
        <!-- rule属性用于指定逻辑表要使用的规则,规则的名字定义在rule.xml中定义,必须与tableRule标签中name属性一致 -->
        <!-- ruleRequired属性用于指定表是否绑定分片规则,如果配置true,但没有配置具体的rule,程序会报错。-->
        <!-- primaryKey属性对应真实表的主键 -->
        <!-- type属性定义了逻辑表的类型,目前逻辑表只有全局表和普通表两种类型。全局表对应的配置值:global,不指定普通表 -->
        <!-- autoIncrement属性默认false,设置成为true时Mycat对表使用自增长主键 -->
        <!-- subTables属性目前Mycat在1.6版本以后才开始支持分表,并且dataNode在分表条件下只能配置一个,不支持各种条件的join关联查询语句 -->
        <!-- needAddLimit指定表是否需要自动在每个语句后面加上limit限制。如果设置为true,Mycat查询的时候自动给我们加上limit 100 -->
        <table name="travelrecord" needAddLimit="true" ruleRequired="true" autoIncrement="false" primaryKey="" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"/>


    </schema>
    <!-- 一个schema代表一个逻辑库 -->
    <schema name="TEST" checkSQLschema="true" sqlMaxLimit="100">
        <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"/>
    </schema>


    <!-- dataNode属性用于绑定逻辑库和具体的数据库 -->
    <!-- name属性对应上面schema中间的DataNode的名字 -->
    <!-- database属性是指定真实数据库的名称 -->
    <!-- dataHost属性是对应数据库的Mycat逻辑库名称 -->
    <dataNode name="dn1" dataHost="Node1" database="db1"/>
    <dataNode name="dn2" dataHost="Node2" database="db2"/>
    <dataNode name="dn3" dataHost="Node3" database="db3"/>

    <!-- 它是schema.xml中最后一个标签,该标签在Mycat逻辑库中作为底层标签存在,直接定义了具体的数据库实例、读写分离和心跳语句。-->
    <!-- name属性是唯一标识dataHost标签,供上层标签使用 -->
    <!-- maxCon属性指定每个读写实例连接池的最大连接数。内嵌标签writeHost/readHost都会使用这个属性的值类实例化连接池的最大连接数 -->
    <!-- minCon属性指定每个读写实例连接池的最小连接数,初始化连接池的大小 -->
    <!-- balance属性属于负载均衡类型,目前有一下4中值
        balance="0" 不开启读写分离机制,所有的操作都发送到当前可以用的writeHost上。
        balance="1" 全部的readHost与stand by writeHost都参与select语句的负载均衡。
        balance="2" 所有的读操作都随机地在writeHost、readHost上分发。
        balance="3" 所有的读请求都随机分发到writeHost对应的readHost上执行,writeHost不负担读压力-->
    <!-- writeType属性有两种值 writeType="0" 所有的写操作都发送到配置的第1个writeHost上,writeHost1挂了则切到writeHost2上
         writeType="1" 所有的写操作都随机的发送到配置的writeHost上 -->
    <!-- dbType属性指定后端连接的数据库类型,目前除了支持二进制的MySQL协议,还支持使用JDBC连接的数据库,例如MongoDB.Oracle等 -->
    <!-- daDriver指定连接后端数据库使用的Driver,目前可选的有native和JDBC -->
    <!-- switchType属性
            switchType="-1"表示不自动切换。
            switchType="1"为默认值,表示自动切换。
            switchType="2"表示基于MySQL主从同步的状态决定是否切换。
            switchType="3"表示基于MySQL Galary Cluster的切换机制。-->
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" tempReadHostAvailable="" dbDriver="native" switchType="1" slaveThreshold="100">
        <!-- heartbeat标签指明了用于后端数据库进行心跳检查的语句,MySQL使用select user() Oracle使用select 1 from dual-->
        <heartbeat>select user()</heartbeat>
        <!-- writeHost标签和readHost标签一样,都指定Mycat后端数据库的相关配置,用于实例化后端连接池。唯一的不同是,writeHost指定写实例,readHost指定读实例 -->
        <!-- host属性用于表示不同的实例,对于writeHost我们一般使用*M1;对于readHost,我们一般使用*S1。 -->
        <!-- url属性,连接后端实例的连接地址 -->
        <!-- user属性,后端存储实例的用户名 -->
        <!-- password属性,后端存储实例的密码 -->
        <!-- weight属性在readHost中作为读节点的权重 -->
        <!-- usingDecrypt属性同server.mxl中的usingDecrypt的配置 -->
        <writeHost host="hostM1" url="192.168.222.132:3306" user="root" password="123456"></writeHost>
    </dataHost>
</mycat:schema>

 

rule.xml详解


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">

    <!-- tableRule标签主要用于定义表规则 -->
    <!-- name属性指定唯一的名字,用于标识不同的表规则 -->
    <!-- columns指定要拆分的列名字 -->
    <!-- algorithm使用function标签中的name属性,用于连接表规则和具体的路由算法,多个表规则可以连接到一个路由算法 -->
    <tableRule name="rule1">
        <rule>
            <columns>id</columns>
            <algorithm>func1</algorithm>
        </rule>
    </tableRule>

    <!-- function标签用于定义具体的拆分路由算法,对应我们上面的algorthm -->
    <!-- name指定算法的名称,在文件中唯一 -->
    <!-- class指定对应的具体的分片算法的具体类 --> 
    <!-- property具体算法的必须参数对应具体算法用到的一些属性 -->
    <function name="func1" class="io.mycat.route.function.PartitionByLong">
        <property name="partitionCount">8</property>
        <property name="partitionLength">128</property>
    </function>
</mycat:rule>

 

自己的测试,读者无需看这部分!!!!


[root@mysql conf]# vim server.xml 

[root@mysql conf]# vim  schema.xml 

针对schema.xml该条做的测试


<table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" />

 <dataNode name="dn1" dataHost="localhost1" database="db1" />
 <dataNode name="dn2" dataHost="localhost1" database="db2" />

   <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="192.168.179.66:3306" user="mycat_test"
                                   password="mycat_test">
                        <readHost host="hostS2" url="192.168.179.66:3306" user="mycat_test" password="mycat_test" />
                </writeHost>

   </dataHost>

 

192.168.179.66上MySQL创建用户并且授予权限,这样就可以登入Mycat中间件了

mysql>  create user 'mycat_test'@'%' identified by 'mycat_test';

mysql> grant all on *.* to 'mycat_test'@'%';

 

192.168.179.66上MySQL创建三个数据库

mysql> create database db1;

mysql> create database db2;

mysql> create database db3;

 

[root@slave1 ~]#  mysql -uroot -p123456 -h 192.168.179.69 -P8066

mysql> show databases;

+----------+

| DATABASE |

+----------+

| MYTEST   |

+----------+

mysql> use MYTEST;

mysql> show tables;

+------------------+

| Tables in MYTEST |

+------------------+

| company          |

| customer         |

| customer_addr    |

| employee         |

| goods            |

| hotnews          |

| orders           |

| order_items      |

| travelrecord     |

+------------------+

 

mysql> create table employee (id int primary key,name varchar(10),sharding_id int);

mysql>  explain create table employee (id int primary key,name varchar(10),sharding_id int);  --通过explian可以看到,表创建在dn1和dn2节点

+-----------+-----------------------------------------------------------------------------+

| DATA_NODE | SQL                                                                         |

+-----------+-----------------------------------------------------------------------------+

| dn1       | create table employee (id int primary key,name varchar(10),sharding_id int) |

| dn2       | create table employee (id int primary key,name varchar(10),sharding_id int) |

+-----------+-----------------------------------------------------------------------------+

 

 

192.168.179.66上MySQL上可以看到创建的表进入了两个库db1 db2,可以看到mycat自动为我分配表到指定数据库中,不需要我手动指定

mysql> use db1;

mysql> show tables;

+---------------+

| Tables_in_db1 |

+---------------+

| employee      |

+---------------+

mysql> use db2;

mysql> show tables;

+---------------+

| Tables_in_db2 |

+---------------+

| employee      |

+---------------+

 

数据的分片


使用mycat中间件插入数据

mysql> insert into employee (id,name,sharding_id) values(1,'hellow','10000');

mysql> explain insert into employee(id,name,sharding_id) values(1,'hellow','10000');

+-----------+----------------------------------------------------------------------------+

| DATA_NODE | SQL                                                                        |

+-----------+----------------------------------------------------------------------------+

| dn1       | INSERT INTO employee (id, name, sharding_id) VALUES (1, 'hellow', '10000') |

+-----------+----------------------------------------------------------------------------+

mysql> insert into employee(id,name,sharding_id) values (1,'aaa',10010);

mysql>  explain insert into employee(id,name,sharding_id) values (1,'aaa',10010);
+-----------+-------------------------------------------------------------------------+
| DATA_NODE | SQL                                                                     |
+-----------+-------------------------------------------------------------------------+
| dn2       | INSERT INTO employee (id, name, sharding_id) VALUES (1, 'aaa', '10010') |
+-----------+-------------------------------------------------------------------------+

 

为什么要有sharding_id,为什么插入不同的值插入的数据库是不同的一个为dn1,一个为dn2

<table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" />

rule定义了表的分片规则,将数据分片到不同的节点上

     

[root@mysql conf]# vim rule.xml

<tableRule name="sharding-by-intfile">

                <rule>

                        <columns>sharding_id</columns>  --可以看到该列名称为sharding_id

                        <algorithm>hash-int</algorithm>   --拆分的策略

                </rule>

        

<function name="hash-int"

                class="io.mycat.route.function.PartitionByFileMap">

                <property name="mapFile">partition-hash-int.txt</property>

</function>

 

 

[root@mysql conf]# ls partition-hash-int.txt

partition-hash-int.txt

[root@mysql conf]# cat partition-hash-int.txt

10000=0

10010=1

 

 


针对schema.xml该条做的测试

<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />

通过Mycat来创建company这张表

mysql> use  MYTEST;

mysql> create table company(id int primary key,name varchar(10));

mysql> explain create table company(id int primary key,name varchar(10));;

+-----------+-----------------------------------------------------------+

| DATA_NODE | SQL                                                       |

+-----------+-----------------------------------------------------------+

| dn1       | create table company(id int primary key,name varchar(10)) |

| dn2       | create table company(id int primary key,name varchar(10)) |

| dn3       | create table company(id int primary key,name varchar(10)) |

+-----------+-----------------------------------------------------------+

 

mysql> insert into company values(1,'lulei');

mysql> explain insert into company values(1,'lulei');

+-----------+---------------------------------------+

| DATA_NODE | SQL                                   |

+-----------+---------------------------------------+

| dn1       | insert into company values(1,'lulei') |

| dn2       | insert into company values(1,'lulei') |

| dn3       | insert into company values(1,'lulei') |

+-----------+---------------------------------------+

 

mysql> explain select * from company;

+-----------+---------------------------------+

| DATA_NODE | SQL                             |

+-----------+---------------------------------+

| dn1       | SELECT * FROM company LIMIT 100 |

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值