目錄
?一.分庫(kù)分表概述及Mycat的概述
1.數(shù)據(jù)切分方式
2.MyCAT概述
二.部署MyCAT服務(wù)
1.環(huán)境準(zhǔn)備
2.配置MyCat服務(wù)器
3.分片規(guī)則
1)枚舉法
2)求模法
3)全局表
?一.分庫(kù)分表概述及Mycat的概述
關(guān)系型數(shù)據(jù)庫(kù)本身比較容易成為系統(tǒng)瓶頸,單機(jī)存儲(chǔ)容量、連接數(shù)、處理能力都有限。
當(dāng)單表的數(shù)據(jù)量達(dá)到1000W或100G以后,由于查詢維度較多,即使添加從庫(kù)、優(yōu)化索引,做很多操作時(shí)性能仍下降嚴(yán)重。此時(shí)就要考慮對(duì)其進(jìn)行切分了,切分的目的就在于減少數(shù)據(jù)庫(kù)的負(fù)擔(dān),縮短查詢時(shí)間。
數(shù)據(jù)庫(kù)分布式核心內(nèi)容無(wú)非就是數(shù)據(jù)切分(Sharding),以及切分后對(duì)數(shù)據(jù)的定位、整合。
數(shù)據(jù)切分就是將數(shù)據(jù)分散存儲(chǔ)到多個(gè)數(shù)據(jù)庫(kù)中,使得單一數(shù)據(jù)庫(kù)中的數(shù)據(jù)量變小,通過(guò)擴(kuò)充主機(jī)的數(shù)量緩解單一數(shù)據(jù)庫(kù)的性能問(wèn)題,從而達(dá)到提升數(shù)據(jù)庫(kù)操作性能的目的。
1.數(shù)據(jù)切分方式
垂直(縱向)切分
垂直切分常見(jiàn)有垂直分庫(kù)和垂直分表兩種。
垂直分庫(kù)就是根據(jù)業(yè)務(wù)耦合性,將關(guān)聯(lián)度低的不同表存儲(chǔ)在不同的數(shù)據(jù)庫(kù)。做法與大系統(tǒng)拆分為多個(gè)小系統(tǒng)類(lèi)似,按業(yè)務(wù)分類(lèi)進(jìn)行獨(dú)立劃分。
垂直分表是基于數(shù)據(jù)庫(kù)中的"列"進(jìn)行,某個(gè)表字段較多,可以新建一張擴(kuò)展表,將不經(jīng)常用或字段長(zhǎng)度較大的字段拆分出去到擴(kuò)展表中。
垂直切分的優(yōu)點(diǎn):
解決業(yè)務(wù)系統(tǒng)層面的耦合,業(yè)務(wù)清晰
對(duì)不同業(yè)務(wù)的數(shù)據(jù)進(jìn)行分級(jí)管理、維護(hù)、監(jiān)控、擴(kuò)展等
高并發(fā)場(chǎng)景下,垂直切分一定程度的提升IO、數(shù)據(jù)庫(kù)連接數(shù)、單機(jī)硬件資源的瓶頸
垂直切分的缺點(diǎn):
水平(橫向)切分
當(dāng)一個(gè)應(yīng)用難以再細(xì)粒度的垂直切分,或切分后數(shù)據(jù)量行數(shù)巨大,存在單庫(kù)讀寫(xiě)、存儲(chǔ)性能瓶頸,這時(shí)候就需要進(jìn)行水平切分了。
水平切分分為庫(kù)內(nèi)分表和分庫(kù)分表,是根據(jù)表內(nèi)數(shù)據(jù)內(nèi)在的邏輯關(guān)系,將同一個(gè)表按不同的條件分散到多個(gè)數(shù)據(jù)庫(kù)或多個(gè)表中,每個(gè)表中只包含一部分?jǐn)?shù)據(jù),從而使得單個(gè)表的數(shù)據(jù)量變小,達(dá)到分布式的效果。
庫(kù)內(nèi)分表只解決了單一表數(shù)據(jù)量過(guò)大的問(wèn)題,但沒(méi)有將表分布到不同機(jī)器的庫(kù)上,因此對(duì)于減輕MySQL數(shù)據(jù)庫(kù)的壓力來(lái)說(shuō),幫助不是很大,大家還是競(jìng)爭(zhēng)同一個(gè)物理機(jī)的CPU、內(nèi)存、網(wǎng)絡(luò)IO,最好通過(guò)分庫(kù)分表來(lái)解決。
水平切分后同一張表會(huì)出現(xiàn)在多個(gè)數(shù)據(jù)庫(kù)/表中,每個(gè)庫(kù)/表的內(nèi)容不同。
水平切分的優(yōu)點(diǎn):
水平切分的缺點(diǎn):
2.MyCAT概述
mycat是基于Java的分布式數(shù)據(jù)庫(kù)系統(tǒng)中間件,為高并發(fā)環(huán)境的分布式存儲(chǔ)提供解決方案
適合數(shù)據(jù)大量寫(xiě)入的存儲(chǔ)需求
支持MySQL、Oracle、Sqlserver、Mongodb等
提供數(shù)據(jù)讀寫(xiě)分離服務(wù)
提供數(shù)據(jù)分片服務(wù)
基于阿里巴巴Cobar進(jìn)行研發(fā)的開(kāi)源軟件
分片規(guī)則
枚舉法 sharding-by-intfile
固定分片 rule
范圍約定 auto-sharding-long
求模法 mod-long
日期列分區(qū)法 sharding-by-date
通配取模 sharding-by-pattern
ASCII碼求模通配 sharding-by-prefixpattern
編程指定 sharding-by-substring
字符串拆分hash解析 sharding-by-stringhash
一致性hash sharding-by-murmur
工作過(guò)程
????????解析SQL命令涉及到的表
????????然后看對(duì)表的配置,如果有分片規(guī)則,則獲取SQL命令里分片字段的值,并匹配分片函數(shù),獲得分片列表
????????然后將SQL命令發(fā)往對(duì)應(yīng)的數(shù)據(jù)庫(kù)服務(wù)器去執(zhí)行
????????最后收集和處理所有分片結(jié)果數(shù)據(jù),并返回到客戶端
二.部署MyCAT服務(wù)
1.環(huán)境準(zhǔn)備
client:192.168.1.10
mycat:192.168.1.15
db1:192.168.1.11
db2:192.168.1.12
db3:192.168.1.13
2.配置MyCat服務(wù)器
[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/ # 設(shè)置PATH環(huán)境變量
[root@mycat1 ~]# vim /etc/profile.d/mycat.sh
export PATH=$PATH:/usr/local/mycat/bin
[root@mycat1 ~]# source /etc/profile.d/mycat.sh
# 保持默認(rèn)配置即可
[root@mycat1 ~]# vim /usr/local/mycat/conf/server.xml
# 該文件中用戶及邏輯庫(kù)的說(shuō)明如下:
<user name="root"> <!--連接mycat服務(wù)時(shí)使用的用戶名--><property name="password">123456</property> <!--用戶連接mycat用戶時(shí)使用的密碼--><property name="schemas">TESTDB</property> <!--邏輯庫(kù)名-->
</user>
<user name="user"><property name="password">user</property><property name="schemas">TESTDB</property><property name="readOnly">true</property> <!--只讀權(quán)限,連接mycat服務(wù)后只有讀記錄的權(quán)限,不寫(xiě)這一行則是可讀可寫(xiě) -->
</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"> <!--對(duì)TESTDB庫(kù)下的表做分片存儲(chǔ) --><!-- auto sharding by id (long) --><table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> <!-- 對(duì)travelrecord表做分片存儲(chǔ) -->
?<!-- global table is auto cloned to all defined data nodes ,so can joinwith 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"/> --><!-- 定義數(shù)據(jù)庫(kù)主機(jī)名及存儲(chǔ)數(shù)據(jù)的庫(kù) --><dataNode name="dn1" dataHost="mysql1" database="db1" /><dataNode name="dn2" dataHost="mysql2" database="db2" /><dataNode name="dn3" dataHost="mysql3" database="db3" />
?<!-- 定義mysql1主機(jī)名對(duì)應(yīng)的數(shù)據(jù)庫(kù)服務(wù)器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>
配置數(shù)據(jù)庫(kù)服務(wù)器 [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';
啟動(dòng)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)
3.分片規(guī)則
1)枚舉法 概述
配置
[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> <!-- 數(shù)據(jù)分片字段名 --><algorithm>hash-int</algorithm> <!-- 使用的函數(shù)名 --></rule>
</tableRule><function name="hash-int"class="io.mycat.route.function.PartitionByFileMap"><property name="mapFile">partition-hash-int.txt</property> <!-- 函數(shù)調(diào)用的配置文件 -->
</function>
[root@mycat1 ~]# vim /usr/local/mycat/conf/partition-hash-int.txt
10000=0 //當(dāng)sharding_id字段的值是10000時(shí),數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)節(jié)點(diǎn)dn1里
10010=1 //當(dāng)sharding_id字段的值是10010時(shí),數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)節(jié)點(diǎn)dn2里
10020=2 //當(dāng)sharding_id字段的值是10020時(shí),數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)節(jié)點(diǎn)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);# 存儲(chǔ)數(shù)據(jù)時(shí)必須指定字段名列表
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臺(tái)服務(wù)器上查看記錄
[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)
2)求模法 概述
使用mod-long規(guī)則
切分規(guī)則根據(jù)配置中輸入的數(shù)值n
分片規(guī)則將數(shù)據(jù)分成n份(通常dn節(jié)點(diǎn)也為n),從而將數(shù)據(jù)均勻的分布于各節(jié)點(diǎn)上
這種策略可以很好的分散數(shù)據(jù)庫(kù)寫(xiě)的壓力。比較適合于單點(diǎn)查詢的情景
配置
[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> <!-- 數(shù)據(jù)分片字段 --><algorithm>mod-long</algorithm> <!-- 函數(shù)名 --></rule></tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod"><!-- how many data nodes --><property name="count">3</property> <!-- 指定求模數(shù)字 -->
</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語(yǔ)法'),-> (4, 'mysql', '基礎(chǔ)');
Query OK, 4 rows affected (0.14 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> select * from hotnews;
+----+--------------------+-----------------------+
| id | title | content |
+----+--------------------+-----------------------+
| 1 | python | 講python了 |
| 4 | mysql | mysql |
| 2 | mysql | 基礎(chǔ) |
| 3 | mysql更新 | 增加全部sql語(yǔ)法 |
+----+--------------------+-----------------------+
4 rows in set (0.07 sec)# 分別到3臺(tái)服務(wù)器上查看記錄
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> use db1;
mysql> select * from hotnews;
+----+-------------------+-----------------------+
| id | title | content |
+----+-------------------+-----------------------+
| 3 | mysql更新 | 增加全部sql語(yǔ)法 |
+----+-------------------+-----------------------+
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 | mysql |
+----+--------------------+-----------------------+
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 | 基礎(chǔ) |
+----+-------------------+-------------------+
1 row in set (0.00 sec)
3)全局表 概述
配置
[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: 0mysql> select * from goods;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 奶茶 |
| 2 | 礦泉水 |
| 3 | 花生 |
| 4 | 瓜子 |
+----+-----------+
4 rows in set (0.01 sec) # 分別到3臺(tái)服務(wù)器上查看記錄
[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)
總結(jié)
以上是生活随笔 為你收集整理的Mysql分库分表(Mycat) 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。