1. データ シャーディングの概念:
1.1. サブデータベースとサブテーブル
- サブデータベース サブテーブルとは:
- データベースサーバーに格納されたデータは、特定の方法(プログラム開発のアルゴリズムを参照)に従って分割され、単一のサーバーの負荷を分散する効果を得るために、複数のデータベースサーバーに格納されます。
1.2. スプリット ホライズン
- 水平分割:
- テーブル内の指定されたフィールドのスライス ルールに従って、テーブル レコードは行に分割され、複数のデータベースに格納されます。
1.3. 垂直分割
- 縦割り
- 1 つのデータベースの複数のテーブルは、業種別に分類され、異なるデータベースに格納されます。
2. Mycat ソフトウェアの紹介:
- mycat は、Java ベースの分散データベース システム ミドルウェアであり、同時実行性の高い環境での分散ストレージのソリューションを提供します。
- 大量のデータ書き込みのストレージ要件には適していますが、大量のデータクエリの要求には適していません。
- MySQL、Oracle、SQL サーバー、Mongodb などをサポートします。
- データの読み取りと書き込みの分離およびデータの断片化サービスを提供します。
- Alibaba Cobar をベースに開発されたオープンソース ソフトウェア
2.1. 断片化のルール
- mycat は 10 個のフラグメンテーション ルールをサポートします
- 列挙方法 (sharding-by-intfile)
- 固定シャーディング (rule1)
- 範囲規則 (auto-sharding-long)
- モジュロ法 (mod-long)
- 日付列のパーティション分割方法 (日付によるシャーディング)
- ワイルドカード モジュロ (パターンごとのシャーディング)
- ASCII コード モジュロ ワイルドカード (プレフィックスパターンによるシャーディング)
- プログラムによる指定 (部分文字列によるシャーディング)
- 文字列分割ハッシュ分析 (sharding-by-stringhash)
- コンシステント ハッシュ (sharding-by-murmur)
2.2. ワークフロー
- mycat が SQL コマンドを受け取ったとき
- SQL コマンドに含まれるテーブルを解析する
- 次に、テーブルの構成を見て、断片化ルールがある場合は、SQL コマンドで断片化フィールドの値を取得し、断片化関数を照合して断片化リストを取得します。
- 次に、SQL コマンドを対応するシャード サーバーに送信して実行します。
- 最後に、すべてのシャード結果データを収集して処理し、クライアントに返します
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 |
- ここでは mysql のインストールについては説明しません。mysql のインストール を参照してください。
- すべてのサーバーのホスト名を変更するには、IP 計画の表を参照してください。
##修改所有主机的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. データベース サーバーを構成する
- シャード構成に応じて対応する設定を行います
- 許可ユーザーを追加
- データベースを作成する
##创建授权用户
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 |
+----+------+------+-----+