データの断片化 (mycat)

1. データ シャーディングの概念:

1.1. サブデータベースとサブテーブル

  • サブデータベース サブテーブルとは:
  • データベースサーバーに格納されたデータは、特定の方法(プログラム開発のアルゴリズムを参照)に従って分割され、単一のサーバーの負荷を分散する効果を得るために、複数のデータベースサーバーに格納されます。

ここに画像の説明を挿入

1.2. スプリット ホライズン

  • 水平分割:
  • テーブル内の指定されたフィールドのスライス ルールに従って、テーブル レコードは行に分割され、複数のデータベースに格納されます。

ここに画像の説明を挿入

1.3. 垂直分割

  • 縦割り
  • 1 つのデータベースの複数のテーブルは、業種別に分類され、異なるデータベースに格納されます。

ここに画像の説明を挿入

2. Mycat ソフトウェアの紹介:

  • mycat は、Java ベースの分散データベース システム ミドルウェアであり、同時実行性の高い環境での分散ストレージのソリューションを提供します。
  • 大量のデータ書き込みのストレージ要件には適していますが、大量のデータクエリの要求には適していません。
  • MySQL、Oracle、SQL サーバー、Mongodb などをサポートします。
  • データの読み取りと書き込みの分離およびデータの断片化サービスを提供します。
  • Alibaba Cobar をベースに開発されたオープンソース ソフトウェア

2.1. 断片化のルール

  • mycat は 10 個のフラグメンテーション ルールをサポートします
  1. 列挙方法 (sharding-by-intfile)
  2. 固定シャーディング (rule1)
  3. 範囲規則 (auto-sharding-long)
  4. モジュロ法 (mod-long)
  5. 日付列のパーティション分割方法 (日付によるシャーディング)
  6. ワイルドカード モジュロ (パターンごとのシャーディング)
  7. ASCII コード モジュロ ワイルドカード (プレフィックスパターンによるシャーディング)
  8. プログラムによる指定 (部分文字列によるシャーディング)
  9. 文字列分割ハッシュ分析 (sharding-by-stringhash)
  10. コンシステント ハッシュ (sharding-by-murmur)

2.2. ワークフロー

  • mycat が SQL コマンドを受け取ったとき
  1. SQL コマンドに含まれるテーブルを解析する
  2. 次に、テーブルの構成を見て、断片化ルールがある場合は、SQL コマンドで断片化フィールドの値を取得し、断片化関数を照合して断片化リストを取得します。
  3. 次に、SQL コマンドを対応するシャード サーバーに送信して実行します。
  4. 最後に、すべてのシャード結果データを収集して処理し、クライアントに返します

3. データ フラグメンテーション サービスを構成する

  • データ シャーディング トポロジ
  • このアーキテクチャを展開するには、少なくとも 3 つのデータベース サーバーが必要であることに注意してください。
    ここに画像の説明を挿入
  • 知財企画
CPU名 役割 データベース IPアドレス
mysql10 クライアント なし 192.168.2.10
mycat20 シャードサーバー なし 192.168.2.20
mysql30 データベース サーバー db1 192.168.2.30
mysql40 データベース サーバー db2 192.168.2.40
mysql50 データベース サーバー db3 192.168.2.50
##修改所有主机的hosts文件
[root@mysql10 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.2.10   mysql10
192.168.2.20   mycat20
192.168.2.30   mysql30
192.168.2.40   mysql40
192.168.2.50   mysql50

3.1. mycat のインストール

##安装软件jdk,因为mycat软件需要jdk编译。
[root@mycat20 ~]# yum -y install java-1.8.0-openjdk
##查看java版本
[root@mycat20 ~]# java -version
openjdk version "1.8.0_362"
OpenJDK Runtime Environment (build 1.8.0_362-b08)
OpenJDK 64-Bit Server VM (build 25.362-b08, mixed mode)
##下载mycat二进制包
[root@mycat20 ~]# wget http://dl.mycat.org.cn/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
##解压指定目录
[root@mycat20 ~]# tar -xf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/
##解压是否成功
[root@mycat20 ~]# cd /usr/local/
[root@mycat20 local]# ls mycat/
bin  catlet  conf  lib  logs  version.txt
配置mycat环境变量:
[root@localhost ~]# echo "export PATH=/usr/local/mycat/bin:$PATH" >/etc/profile.d/mycat.sh
[root@localhost ~]# . /etc/profile.d/mycat.sh 
[root@localhost ~]# echo $PATH
/usr/local/mycat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

3.2. ディレクトリ構造

  • ls /usr/local/mycat
- bin         ----mycat命令
- catlet	  ----扩展功能
- conf   	  ----配置文件
- lib		  ----mycat使用的jar包
- logs		  ----mycat启动日志和运行日志
- wrapper.log ----mycat服务启动日志
- mycat.log   ----记录SQL脚本执行后报错内容

3.3. メイン設定ファイルの変更

  • 構成ファイルに関する重要な注意事項
- server.xml                  ---设置连接账号及逻辑库
- schema.xml				  ---配置数据分片存储的表
- rule.xml					  ---分片规则
- 其他文件					  ---分片规则配置文件

3.3.1. 接続ユーザーの作成 (server.xml)

##备份server.xml文件
[root@mycat20 ~]# cd /usr/local/mycat/conf/
[root@mycat20 conf]# cp -r server.xml{,.bak}
##创建连接用户
.xml文件中<!--     -->代表注释。
[root@mycat20 conf]# vim server.xml
....
修改以下内容
<user name="root">       ---连接mycat服务用户名
                <property name="password">1234</property>   ---用户密码
                <property name="schemas">mycatdb</property>    ---逻辑库

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

        <user name="user">
                <property name="password">1234</property>
                <property name="schemas">mycatdb</property>
                <property name="readOnly">true</property>   ---只读权限
        </user>

3.3.2. フラグメンテーションを定義するテーブル (schema.xml)

##定义分片的表

 <schema> ...... </schema>      --定义分片信息,对什么表做分片
<table> ...... </table>         --定义要分片的表
name         					--逻辑库名或逻辑表名
dataNode      					--指定数据节点名
rule     						--指定使用的分片规则
type=global         			--数据不做分片存储

##定义数据节点

<dataNode 选项=值,... .../>      --定义数据节点
name          					--数据节点名
datahost    					--数据库服务器主机名
database    					--数据库名

##定义数据库服务器IP地址及端口

<datahost 选项=值,... ...>... ...</datahost>        --服务器主机名
name            				--主机名(与datahost对应的主机名)
host              				--主机名(与IP地址对应的主机名)
url                 			--数据库服务器IP地址及端口号
user              				--数据库服务器授权用户
password      					--授权用户密码

##备份schema.xml文件
[root@mycat20 conf]# cp -r schema.xml{,.bak}
[root@mycat20 conf]# vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="mycatdb" checkSQLschema="false" sqlMaxLimit="100">
                <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

                <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
                <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
                <table name="hotnews"  dataNode="dn1,dn2,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>
        </schema>
        <dataNode name="dn1" dataHost="mysql30" database="db1" />
        <dataNode name="dn2" dataHost="mysql40" database="db2" />
        <dataNode name="dn3" dataHost="mysql50" database="db3" />
        <dataHost name="mysql30" 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.2.30:3306" user="mycat"
                                   password="1234">
                </writeHost>
        </dataHost>
<dataHost name="mysql40" 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.2.40:3306" user="mycat"
                                   password="1234">
                </writeHost>
        </dataHost>
        <dataHost name="mysql50" 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.2.50:3306" user="mycat"
                                   password="1234">
                </writeHost>
        </dataHost>
</mycat:schema>	

4. データベース サーバーを構成する

  • シャード構成に応じて対応する設定を行います
  1. 許可ユーザーを追加
  2. データベースを作成する
##创建授权用户
mysql> grant all on *.* to mycat@'%' identified by '1234';   ---在mysql30、mysql40、mysql50执行。
##创建数据库
mysql> create database db1 default chatset=utf8;   ---在mysql30执行
mysql> create database db2 default charset=utf8;   --在mysql40执行
mysql> create database db3 default charset=utf8;  ---在mysql50执行
  • 上記の操作は、mycat 構成ファイル schema.xml の内容に基づいています。
    ここに画像の説明を挿入

5. mycat サービスを開始します

[root@mycat20 conf]# mycat start
Starting Mycat-server...
[root@mycat20 conf]# netstat -nltp | grep 8066
tcp6       0      0 :::8066                 :::*                    LISTEN      9719/java

6.クライアントがシャードサーバーに接続します

[root@mysql10 ~]# mysql -uroot -p1234 -h192.168.2.20 -P8066
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycatdb  |     ---逻辑库
+----------+
mysql> use mycatdb
mysql> show tables;
+-------------------+
| Tables in mycatdb |
+-------------------+
| company           |    ---这些都是逻辑表
| customer          |
| customer_addr     |
| employee          |
| goods             |
| hotnews           |
| orders            |
| order_items       |
| travelrecord      |
+-------------------+
9 rows in set (0.00 sec)

  • シャード サーバーにログインするためのユーザー名とパスワードは、図で定義されています。
    ここに画像の説明を挿入

  • シャードサーバー上の論理ライブラリと論理テーブルは、図で定義されています
    ここに画像の説明を挿入

7. 断片化のルール

7.1. 列挙方法 (sharding-by-intfile)

  • フィールド値は、ルール ファイルで定義された値で選択する必要があります
[root@mycat20 conf]# vim schema.xml
<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
                           rule="sharding-by-intfile" />
##可以看的出来employee这个表格必须有ID这个字段并且约束条件是主键分片规则是枚举法(sharding-by-intfile)
##查看枚举法的详细内容
[root@mycat20 conf]# vim rule.xml
<tableRule name="sharding-by-intfile">
                <rule>
                        <columns>sharding_id</columns>    --指定employee这个表格必须有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>
##查看sharding_id字段名的值范围
[root@mycat20 conf]# vim partition-hash-int.txt
10000=0     ---代表dn1
10010=1     ---代表dn2
10020=2     ---代表dn3

7.1.1. mycat サービスの再起動

[root@mycat20 conf]# mycat stop;mycat start
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...

7.1.2. 従業員テーブルの作成

##登录分片服务器,创建employee表格
[root@mysql10 ~]# mysql -umycat -p1234 -h192.168.2.20 -P8066
mysql> create table employee(
    -> ID int primary key auto_increment,   ---schema.xml指定的字段名
    -> sharding_id int not null,     分片规则指定字段
    -> name char(20) not null,
    -> sex enum('boy','girl') not null,
    -> age int unsigned not null,
    -> homedir char(50) not null);
Query OK, 0 rows affected (0.08 sec)
mysql> desc employee;
+-------------+--------------------+------+-----+---------+----------------+
| Field       | Type               | Null | Key | Default | Extra          |
+-------------+--------------------+------+-----+---------+----------------+
| ID          | int(11)            | NO   | PRI | NULL    | auto_increment |
| sharding_id | int(11)            | NO   |     | NULL    |                |
| name        | char(20)           | NO   |     | NULL    |                |
| sex         | enum('boy','girl') | NO   |     | NULL    |                |
| age         | int(10) unsigned   | NO   |     | NULL    |                |
| homedir     | char(50)           | NO   |     | NULL    |                |
+-------------+--------------------+------+-----+---------+----------------+
6 rows in set (0.09 sec)
##在mycat分片服务器上创建employee这个表格mysql30、mysql40、mysql50都应该有这个表格,这里就不显示出来了。

7.1.3. 検証列挙方法

##往employee表格插入数据,sharding_id赋值为100010代表数据存储在mysql40上。
mysql> insert into employee(sharding_id,name,sex,age,homedir) values(10010,'bob','boy',29,'china');
##进入mysql40验证数据是否在。
mysql> select * from employee;
+----+-------------+------+-----+-----+-----------------------------------------+
| ID | sharding_id | name | sex | age | homedir                                 |
+----+-------------+------+-----+-----+-----------------------------------------+
|  1 |       10010 | bob  | boy |  29 | china			                 |
+----+-------------+------+-----+-----+-----------------------------------------+

1 row in set (0.01 sec)
##还可以验证mysql30、mysql50的employee表格是否有这个数据,这里就不展示了,正确的应该这两台都没有。

7.2. モジュロ法 (mod-long)

  • フィールド値と設定されたデジタル モジュロの結果に従ってデータを格納します。つまり、剰余を取ります。
##查看hotnews表定义的内容:分片规则为求模法。
[root@mycat20 conf]# vim schema.xml
<table name="hotnews"  dataNode="dn1,dn2,dn3"
                           rule="mod-long" />

##查看求模法定义的字段名以及算法范围
[root@mycat20 conf]# vim rule.xml
 <tableRule name="mod-long">
 39                 <rule>
 40                         <columns>mod_id</columns>
 41                         <algorithm>mod-long</algorithm>
 42                 </rule>
 43         </tableRule>
......
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
106                 <!-- how many data nodes -->
107                 <property name="count">3</property>   --定义mod_id值除以3余数为0存储dn1,余数为1存储在dn2,余数为2存储在dn3。
108         </function>

7.2.1. mycat サービスの再起動

[root@mycat20 conf]# mycat stop; mycat start
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...

7.2.2. hotnews テーブルの作成

mysql> create  table hotnews( mod_id int  not null, title char(20) not null, worker char(15) not null);

7.2.3. モジュロ法の検証

##往hotnews表格插入数据
mysql> insert into hotnews(mod_id,title,worker) values(1,'system','bob');
##mod_id的值为1除以3余1所以数据存储在dn2(mysql40)
##在mysql40上查看数据
mysql> select * from hotnews;
+--------+--------+--------+
| mod_id | title  | worker |
+--------+--------+--------+
|      1 | system | bob    |
+--------+--------+--------+
1 row in set (0.00 sec)
##正确情况下mysql30和mysql50的hotnews表是没有数据的,这里不展示了。

8. 非断片化ストレージ (type=global)

##type=global意思是不用分片,存储数据在dn1、dn2、dn3上都存。
 <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />

8.1. テーブルグッズの作成とデータの挿入

mysql> create table goods(
    -> ID int primary key auto_increment,
    -> name char(15)not null,
    -> sex enum('boy','girl')not null,
    -> age int unsigned not null);
Query OK, 0 rows affected (0.02 sec)
##插入数据
mysql> insert into goods(name,sex,age) values('bob','boy',25),('andy','boy',19),('lucy','girl',18);

8.2. 検証:

[root@mysql10 ~]# mysql -umycat -p1234 -h192.168.2.30 -e "select * from db1.goods"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+------+------+-----+
| ID | name | sex  | age |
+----+------+------+-----+
|  1 | bob  | boy  |  25 |
|  2 | andy | boy  |  19 |
|  3 | lucy | girl |  18 |
+----+------+------+-----+
[root@mysql10 ~]# mysql -umycat -p1234 -h192.168.2.40 -e "select * from db2.goods"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+------+------+-----+
| ID | name | sex  | age |
+----+------+------+-----+
|  1 | bob  | boy  |  25 |
|  2 | andy | boy  |  19 |
|  3 | lucy | girl |  18 |
+----+------+------+-----+
[root@mysql10 ~]# mysql -umycat -p1234 -h192.168.2.50 -e "select * from db3.goods"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+------+------+-----+
| ID | name | sex  | age |
+----+------+------+-----+
|  1 | bob  | boy  |  25 |
|  2 | andy | boy  |  19 |
|  3 | lucy | girl |  18 |
+----+------+------+-----+

おすすめ

転載: blog.csdn.net/weixin_45625174/article/details/129120837