分库分表、部署MyCAT服务、分片规则

2021-08-13  本文已影响0人  秋天丢了李姑娘

分库分表

概述

数据切分方式

垂直(纵向)切分

水平(横向)切分

MyCAT

概述

分片规则

工作过程

  1. 解析SQL命令涉及到的表

  2. 然后看对表的配置,如果有分片规则,则获取SQL命令里分片字段的值,并匹配分片函数,获得分片列表

  3. 然后将SQL命令发往对应的数据库服务器去执行

  4. 最后收集和处理所有分片结果数据,并返回到客户端

部署MyCAT服务

graph LR
c(client:192.168.1.10)-->mc(mycat:192.168.1.15)
mc-->db1(db1:192.168.1.11)
mc-->db2(db2:192.168.1.12)
mc-->db3(db3:192.168.1.13)

配置MyCat服务器

[root@mycat1 ~]# yum -y install java-1.8.0-openjdk

[root@mycat1 ~]# which java
/usr/bin/java
[root@mycat1 ~]# java -version
openjdk version "1.8.0_222-ea"
OpenJDK Runtime Environment (build 1.8.0_222-ea-b03)
OpenJDK 64-Bit Server VM (build 25.222-b03, mixed mode)
[root@mycat1 ~]# tar xf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@mycat1 ~]# mv mycat /usr/local/

# 设置PATH环境变量
[root@mycat1 ~]# vim /etc/profile.d/mycat.sh
export PATH=$PATH:/usr/local/mycat/bin
[root@mycat1 ~]# source /etc/profile.d/mycat.sh
# 保持默认配置即可
[root@mycat1 ~]# vim /usr/local/mycat/conf/server.xml
# 该文件中用户及逻辑库的说明如下:
<user name="root">      <!--连接mycat服务时使用的用户名-->
     <property name="password">123456</property>   <!--用户连接mycat用户时使用的密码-->
     <property name="schemas">TESTDB</property>    <!--逻辑库名-->
</user>
<user name="user">
                <property name="password">user</property>
                <property name="schemas">TESTDB</property>
                <property name="readOnly">true</property>     <!--只读权限,连接mycat服务后只有读记录的权限,不写这一行则是可读可写   -->
</user>
[root@mycat1 ~]# vim /usr/local/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">  <!--对TESTDB库下的表做分片存储 -->
        <!-- auto sharding by id (long) -->
        <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />  <!-- 对travelrecord表做分片存储 -->

        <!-- global table is auto cloned to all defined data nodes ,so can join
            with any table whose sharding node is in the same data node -->
        <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
        <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
        <!-- random sharding using mod sharind rule -->
        <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
               rule="mod-long" />
        <!-- <table name="dual" primaryKey="ID" dataNode="dnx,dnoracle2" type="global"
            needAddLimit="false"/> <table name="worker" primaryKey="ID" dataNode="jdbc_dn1,jdbc_dn2,jdbc_dn3"
            rule="mod-long" /> -->
        <table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
               rule="sharding-by-intfile" />
        <table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"
               rule="sharding-by-intfile">
            <childTable name="orders" primaryKey="ID" joinKey="customer_id"
                        parentKey="id">
                <childTable name="order_items" joinKey="order_id"
                            parentKey="id" />
            </childTable>
            <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
                        parentKey="id" />
        </table>
        <!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"
            /> -->
    </schema>
    <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
        /> -->
    <!-- 定义数据库主机名及存储数据的库 -->
    <dataNode name="dn1" dataHost="mysql1" database="db1" />
    <dataNode name="dn2" dataHost="mysql2" database="db2" />
    <dataNode name="dn3" dataHost="mysql3" database="db3" />

  <!-- 定义mysql1主机名对应的数据库服务器ip地址 -->
    <dataHost name="mysql1" 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.1.11:3306" user="mycatadmin"
                   password="NSD2021@tedu.cn">
        </writeHost>
    </dataHost>

    <dataHost name="mysql2" maxCon="1000" minCon="10" balance="0"
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM2" url="192.168.1.12:3306" user="mycatadmin"
                   password="NSD2021@tedu.cn">
        </writeHost>
    </dataHost>

    <dataHost name="mysql3" maxCon="1000" minCon="10" balance="0"
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM3" url="192.168.1.13:3306" user="mycatadmin"
                   password="NSD2021@tedu.cn">
        </writeHost>
    </dataHost>
</mycat:schema>

配置数据库服务器

[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> create database db1 default charset utf8mb4;
mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';

[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> create database db2 default charset utf8mb4;
mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';

[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> create database db3 default charset utf8mb4;
mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';

启动MyCat

# 安装mysql客户端软件
[root@mycat1 ~]# yum install -y mysql-community-client

[root@mycat1 ~]# mysql -h192.168.1.11 -umycatadmin -pNSD2021@tedu.cn
[root@mycat1 ~]# mysql -h192.168.1.12 -umycatadmin -pNSD2021@tedu.cn
[root@mycat1 ~]# mysql -h192.168.1.13 -umycatadmin -pNSD2021@tedu.cn
[root@mycat1 ~]# mycat start
[root@mycat1 ~]# netstat -tlnp | grep :8066
tcp6       0      0 :::8066                 :::*                    LISTEN      13835/java
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+
1 row in set (0.00 sec)

mysql> use TESTDB;
mysql> show tables;
+------------------+
| Tables in TESTDB |
+------------------+
| company          |
| customer         |
| customer_addr    |
| employee         |
| goods            |
| hotnews          |
| orders           |
| order_items      |
| travelrecord     |
+------------------+
9 rows in set (0.00 sec)

分片规则

枚举法

概述

配置

[root@mycat1 ~]# grep -B1 sharding-by-intfile /usr/local/mycat/conf/schema.xml
        <table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
               rule="sharding-by-intfile" />
        <table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"
               rule="sharding-by-intfile">
[root@mycat1 ~]# vim /usr/local/mycat/conf/rule.xml
<tableRule name="sharding-by-intfile">
                <rule>
                        <columns>sharding_id</columns>    <!-- 数据分片字段名 -->
                        <algorithm>hash-int</algorithm>   <!-- 使用的函数名 -->
                </rule>
</tableRule>

<function name="hash-int"
                class="io.mycat.route.function.PartitionByFileMap">
                <property name="mapFile">partition-hash-int.txt</property>   <!-- 函数调用的配置文件 -->
</function>
[root@mycat1 ~]# vim /usr/local/mycat/conf/partition-hash-int.txt
10000=0   //当sharding_id字段的值是10000时,数据存储在数据节点dn1里
10010=1   //当sharding_id字段的值是10010时,数据存储在数据节点dn2里
10020=2   //当sharding_id字段的值是10020时,数据存储在数据节点dn3里
[root@mycat1 conf]# mycat restart
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456
mysql> use TESTDB;
mysql> create table employee(id int primary key, sharding_id int, name varchar(20), birth_date date);

// 存储数据时必须指定字段名列表
mysql> insert into employee
    -> (id, sharding_id, name, birth_date)
    -> values
    -> (1, 10000, 'nb', '2000-01-01'),
    -> (2, 10010, 'wk', '1998-10-01'),
    -> (3, 10020, 'plj', '2002-05-04'),
    -> (4, 10020, 'dmy', '1990-08-02');
Query OK, 4 rows affected (0.21 sec)

mysql> select * from employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
|  1 |       10000 | nb   | 2000-01-01 |
|  2 |       10010 | wk   | 1998-10-01 |
|  3 |       10020 | plj  | 2002-05-04 |
|  4 |       10020 | dmy  | 1990-08-02 |
+----+-------------+------+------------+
4 rows in set (0.09 sec)

// 分别到3台服务器上查看记录
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db1;
mysql> select * from employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
|  1 |       10000 | nb   | 2000-01-01 |
+----+-------------+------+------------+
1 row in set (0.00 sec)

[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db2;
mysql> select * from employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
|  2 |       10010 | wk   | 1998-10-01 |
+----+-------------+------+------------+
1 row in set (0.00 sec)

[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db3;
mysql> select * from employee;
+----+-------------+------+------------+
| id | sharding_id | name | birth_date |
+----+-------------+------+------------+
|  3 |       10020 | plj  | 2002-05-04 |
|  4 |       10020 | dmy  | 1990-08-02 |
+----+-------------+------+------------+
2 rows in set (0.00 sec)

求模法

概述

配置

[root@mycat1 ~]# vim /usr/local/mycat/conf/schema.xml
... ...
        <table name="hotnews" primaryKey="ID" dataNode="dn1,dn2,dn3"
               rule="mod-long" />
... ...
[root@mycat1 ~]# vim /usr/local/mycat/conf/rule.xml
<tableRule name="mod-long">
                <rule>
                        <columns>id</columns>             <!-- 数据分片字段 -->
                        <algorithm>mod-long</algorithm>   <!-- 函数名 -->
                </rule>
        </tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
                <!-- how many data nodes -->
                <property name="count">3</property>       <!-- 指定求模数字 -->
</function>
[root@mycat1 ~]# mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456
mysql> use TESTDB;
mysql> create table hotnews(id int primary key, title varchar(50), content text);
Query OK, 0 rows affected (0.59 sec)

mysql> insert into hotnews
    -> (id, title, content)
    -> values
    -> (1, 'python讲师变更', '庞老师讲python了'),
    -> (2, 'mysql讲师变更', '张老师讲mysql'),
    -> (3, 'mysql课程更新', '增加全部sql语法'),
    -> (4, 'mysql时长', '课程共11天');
Query OK, 4 rows affected (0.14 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from hotnews;
+----+--------------------+-----------------------+
| id | title              | content               |
+----+--------------------+-----------------------+
|  1 | python讲师变更     | 庞老师讲python了      |
|  4 | mysql时长          | 课程共11天            |
|  2 | mysql讲师变更      | 张老师讲mysql         |
|  3 | mysql课程更新      | 增加全部sql语法       |
+----+--------------------+-----------------------+
4 rows in set (0.07 sec)

// 分别到3台服务器上查看记录
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db1;
mysql> select * from hotnews;
+----+-------------------+-----------------------+
| id | title             | content               |
+----+-------------------+-----------------------+
|  3 | mysql课程更新     | 增加全部sql语法       |
+----+-------------------+-----------------------+
1 row in set (0.00 sec)

[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db2;
mysql> select * from hotnews;
+----+--------------------+-----------------------+
| id | title              | content               |
+----+--------------------+-----------------------+
|  1 | python讲师变更     | 庞老师讲python了      |
|  4 | mysql时长          | 课程共11天            |
+----+--------------------+-----------------------+
2 rows in set (0.00 sec)

[root@mysql3 ~]# mysql -uroot -p'NSD2021@tedu.cn'
mysql> use db3;
mysql> select * from hotnews;
+----+-------------------+-------------------+
| id | title             | content           |
+----+-------------------+-------------------+
|  2 | mysql讲师变更     | 张老师讲mysql     |
+----+-------------------+-------------------+
1 row in set (0.00 sec)

全局表

概述

配置

[root@mycat1 ~]# grep goods /usr/local/mycat/conf/schema.xml
        <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456
mysql> use TESTDB;
mysql> create table goods(id int primary key auto_increment, name varchar(10));
Query OK, 0 rows affected (0.61 sec)

mysql> insert into goods(id, name)
    -> values
    -> (1, '奶茶'),
    -> (2, '矿泉水'),
    -> (3, '花生'),
    -> (4, '瓜子');
Query OK, 4 rows affected (0.16 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from goods;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 奶茶      |
|  2 | 矿泉水    |
|  3 | 花生      |
|  4 | 瓜子      |
+----+-----------+
4 rows in set (0.01 sec)


// 分别到3台服务器上查看记录
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db1;
mysql> select * from goods;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 奶茶      |
|  2 | 矿泉水    |
|  3 | 花生      |
|  4 | 瓜子      |
+----+-----------+
4 rows in set (0.00 sec)

[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db2;
mysql> select * from goods;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 奶茶      |
|  2 | 矿泉水    |
|  3 | 花生      |
|  4 | 瓜子      |
+----+-----------+
4 rows in set (0.00 sec)

[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db3
mysql> select * from goods;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 奶茶      |
|  2 | 矿泉水    |
|  3 | 花生      |
|  4 | 瓜子      |
+----+-----------+
4 rows in set (0.00 sec)
上一篇 下一篇

猜你喜欢

热点阅读