前面幾篇文章中,咱們提到了如何擴展資料庫層級服務,讓它可以接更多的客,但是這些擴展方法中,都有提到一個『 中間件 』來使用,接下後本篇文章中,咱們將介紹其中一種比較常見的中間件 :
MyCAT
本篇文章分為以下幾個章節 :
在資料庫中間件中,事實上分為兩種類型 :
它們兩個的基本差別如下圖 1 所示,proxy 是一個外部的服務,所有的應用都會透過這個 proxy 服務來操作資料庫。
而 smart-client 概念就是包在應用層中,當成一個 sdk 概念的程式碼。
圖 1 : proxy vs smart-client
而其中 mycat 就是屬於 proxy 的其中一種應用。
~ 小知識 ~
現在幾個比較可以說的出名字的中間件有 :
proxy : cobar、mycat、mysql-router、atlas、vitess
smart-client : 大部份語言有實現簡單版的,而如果是支援比較多功能的有 sharding-jdbc、tddl。
有興趣的友人可以自已查查來比較看看。
首先咱們先說說 smart-client 的優點 :
Smart-client 缺點 :
總結來說,如果你的資料庫層級只到了『 讀寫分離 』的情境,那建議是只要使用 smart-client 模式,而是是直接使用各語言有提供的套件就好,而如果到了『 分庫分表 』而且公司內有很多人會使用,那就真的要考慮 proxy 了。
mycat 是一個由阿里開發的 cobar 演變來的資料庫的中間件服務,它是屬於『 proxy 類型 』,它基本上有以下的特點 :
首先第一點 mycat 支持讀寫分離、分庫分表,寫讓咱們應用端一樣照常的寫一樣 sql,然後內部會自動幫處理這些事情。
第二點 mycat 他本身是 nio 也就所謂的 non-blocking i/o 機制,就是咱們下面這篇文章中所提到的 reactor 模式,這也代表太可以處理大量的請求。
30-07 之應用層的 I/O 優化 - 非阻塞 I/O 模型 Reactor
第三點支持分散式事務,也就是咱們應用端一樣像往常一樣使用事務,而 mycat 就會自動幫咱們變成分散式事務。
30-28 之資料庫層擴展難題 - MySQL 分散式事務處理
第四點跟庫 join,這可以讓咱們應用端寫 join 和平常一樣,但是注意,它只限兩表。
其中 dataHost 有些參數注意一下。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 1. 定義 mycat 邏輯資料庫 -->
<schema name="masterdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="db1" />
<!-- 2. 定義 mycat 邏輯資料操作節點 -->
<!-- 不過比較特別的是 database 它是指實際要連到的預設資料庫 -->
<dataNode name="db1" dataHost="xxx-db" database="test" />
<!-- 3. 定義 mycat 邏輯 host -->
<dataHost name="xxx-db" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 4. 定義實際使用資料庫位置 -->
<writeHost host="m1" url="192.168.0.10:3306" user="root"
</writeHost>
</dataHost>
</mycat:schema>
這裡簡單畫一下配置的關係圖,如下圖 2 所示。
圖 2 : mycat 配置圖關係
下面為讀寫分離的配置,差別在於 dataHost 的的設定。
當要使用時,你可以下以下的 sql 來取得資料。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="db" checkSQLschema="false" sqlMaxLimit="100" dataNode="db-node" />
<dataNode name="db-node" dataHost="db-host" database="test" />
<!-- 以下有變 -->
<dataHost name="db-host" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- !. 定義實際使用資料庫位置 (寫) -->
<writeHost host="writer" url="192.168.0.10:3306" user="root" password="pass">
<!-- !. 定義實際使用資料庫位置 (讀) -->
<readHost host="reader" url="192.168.0.20:3306" user="root" password="pass" />
</writeHost>
</dataHost>
</mycat:schema>
下圖 3 為 mycat 讀寫分離的配置概念圖。
圖 3 : mycat 讀寫分離的配置概念圖
~ 注意事項 ~
有個東西要注意一下,mysql 的資料同步是要自已實現,mycat 不能會幫你處理喔。
分庫的配置就是什麼都建立兩組,然後用戶端要打時,自已決定去打那一個位置。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="Order" checkSQLschema="false" sqlMaxLimit="100" dataNode="order-node"/>
<schema name="User" checkSQLschema="false" sqlMaxLimit="100" dataNode="user-node"/>
<dataNode name="order-node" dataHost="order-host" database="db1" />
<dataNode name="user-node" dataHost="user-host" database="db2" />
<dataHost name="order-host" maxCon="1000" minCon="10" balance="2"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="host1" url="192.168.1.199:3306" user="root" password="123456"/>
</dataHost>
<dataHost name="user-host" maxCon="1000" minCon="10" balance="2"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="host2" url="192.168.1.166:3306" user="root" password="123456"/>
</dataHost>
</mycat:schema>
圖 4 : 分庫分表 mycat 配置概念圖
請至筆者的 github 抓取這個專案,不過先說一下,這個 docker-compose 是抓了其它 mycat 的配置來修修改改,改改修修,雖然可以動,不過裡面還很亂,閒時會慢慢的用乾淨點。
其中需要注意看的檔案如下 :
移至 mycat-master-slave 這個資料夾裡面,然後在執行以下指令。
docker-compose up
等待一段時間以後,你可以使用以下的指令進行連線,正常應該是可以成功的連進去,其中這個位置是連到 mycat 喔。
mysql -h127.0.0.1 -P8066 -uroot -ppass
host: 127.0.0.1:8066
username: root
password: pass
然後你就可以在裡面下指令了,一開始應該是空的,那你可以使用以下指令建立一下測試資訊。
use db;
create table user(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
age INT NOT NULL,
PRIMARY KEY ( id )
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO user (name, age) VALUES ('A-Mark', 18);
INSERT INTO user (name, age) VALUES ('B-Jack', 10);
INSERT INTO user (name, age) VALUES ('C-Ian', 36);
INSERT INTO user (name, age) VALUES ('E-Jiro', 30);
INSERT INTO user (name, age) VALUES ('D-Fucc', 27);
INSERT INTO user (name, age) VALUES ('C-Mark', 46);
然後你就可以正常的執行 sql 操作囉。
SELECT * FROM user;
這裡使用 docker-compose 來配置一個模擬的 mycat 讀寫分離情境,其中有三個服務 :
有幾個重點說一下。
首先讀與寫的 mysql 服務都是使用 bitnami/mysql:5.7 ,是因為它可以很簡單的讓我可以使用兩台資料庫資料同步的功能,不然用原生的很配置要寫很常。
然後這裡還有設置 db 的 docker network,不知道為什麼嘗試的時後直接使用 link 會失敗,詳細原因就待查,反正這只是淺淺的範例。
version: '3'
services:
mysql_write:
image: 'bitnami/mysql:5.7'
ports:
- 33061:3306
networks:
db:
ipv4_address: 192.168.0.10
environment:
- MYSQL_REPLICATION_MODE=master
- MYSQL_REPLICATION_USER=repl_user
- MYSQL_USER=mark
- MYSQL_DATABASE=test
- ALLOW_EMPTY_PASSWORD=yes
- MYSQL_ROOT_PASSWORD=pass
volumes:
- ./mysql/write/:/etc/mysql/conf.d
- ./config/hosts:/etc/hosts:ro
mysql_read:
image: 'bitnami/mysql:5.7'
ports:
- 33062:3306
networks:
db:
ipv4_address: 192.168.0.20
environment:
- MYSQL_REPLICATION_MODE=slave
- MYSQL_REPLICATION_USER=repl_user
- MYSQL_USER=mark
- MYSQL_DATABASE=test
- MYSQL_MASTER_HOST=192.168.0.10
- MYSQL_MASTER_PORT_NUMBER=3306
- MYSQL_MASTER_ROOT_PASSWORD=pass
- ALLOW_EMPTY_PASSWORD=yes
volumes:
- ./mysql/read/:/etc/mysql/conf.d
- ./config/hosts:/etc/hosts:ro
mycat:
image: 'qiyue/mycat:1.6.5'
volumes:
- ./config/mycat/:/usr/local/mycat/conf/
- ./log/mycat-logs/:/mycat/logs/:rw
ports:
- "8066:8066"
- "9066:9066"
networks:
db:
ipv4_address: 192.168.0.5
ulimits:
nproc: 65535
hostname: mycat
restart: always
networks:
db:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.0.0/24
然後還有這三個服務都配置在 db 這個 network 內網中,然後這裡比較特別的是,會將這三台服務配置 config/hosts 也就是讓人在內網中打 writer 就會對應到 192.168.0.10 這個位置,概念就像是 localhost 指向。
原本想嘗試在 mycat 中直接配置 ip,但嘗試了一下不太行,原因還是待查,難怪看起他人的配置都是要配置 config/hosts。
127.0.0.1 localhost
192.168.0.10 writer
192.168.0.20 reader
192.168.0.5 mycat
這裡就淺淡到這囉。詳細的內容自已去 github 看 code 吧,因為嚴格來說算最後的一天,我疲勞了。
本篇文章咱們介紹了其中一種資料庫中件間『 MyCAT 』。然後咱們非常淺的理解一下它的使用範例,與使用 docker 來實際上將它建立出來。
那為啥會選他來介紹,只因為它資料比較多…… 到了今天已經沒有多餘的體力可以更深入的調查與研究了,未來如果有機會在開篇來真的詳細談談這東西。
雖然才 29 天,但基本上就和最後一天沒差多少了,雖然參加過不少次,但是真的最後寫到很疲勞,終於要結束了……