2、mycat的安裝及使用
1、mycat的安裝
1、環境准備
本次課程使用的虛擬機環境是centos6.5
首先准備四台虛擬機,安裝好mysql,方便后續做讀寫分離和主從復制。
192.168.85.111 node01
192.168.85.112 node02
192.168.85.113 node03
192.168.85.114 node04
安裝jdk
使用rpm的方式直接安裝jdk,配置好具體的環境變量
2、mycat的安裝
從官網下載需要的安裝包,並且上傳到具體的虛擬機中,我們在使用的時候將包上傳到node01這台虛擬機,由node01充當mycat。
下載地址為:http://dl.mycat.org.cn/1.6.7.5/2020-4-10/
解壓文件到/usr/local文件夾下
tar -zxvf Mycat-server-1.6.7.5-release-20200422133810-linux.tar.gz -C /usr/local
配置環境變量
vi /etc/profile
添加如下配置信息:
export MYCAT_HOME=/usr/local/mycat
export PATH=$MYCAT_HOME/bin:$PATH:$JAVA_HOME/bin
當執行到這步的時候,其實就可以啟動了,但是為了能正確顯示出效果,最好修改下mycat的具體配置,讓我們能夠正常進行訪問。
3、配置mycat
進入到/usr/local/mycat/conf目錄下,修改該文件夾下的配置文件
1、修改server.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="defaultSchema">TESTDB</property>
</user>
</mycat:server>
2、修改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" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="host1" database="msb" />
<dataHost name="host1" 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.85.111:3306" user="root" password="123456">
<readHost host="hostS1" url="192.168.85.112:3306" user="root" password="123456"></readHost>
</writeHost>
</dataHost>
</mycat:schema>
4、啟動mycat
mycat的啟動有兩種方式,一種是控制台啟動,一種是后台啟動,在初學的時候建議大家使用控制台啟動的方式,當配置文件寫錯之后,可以方便的看到錯誤,及時修改,但是在生產環境中,使用后台啟動的方式比較穩妥。
控制台啟動:去mycat/bin目錄下執行 ./mycat console
后台啟動:去mycat/bin目錄下執行 ./mycat start
按照如上配置在安裝的時候應該不會報錯,如果出現錯誤,根據錯誤的提示解決即可。
5、登錄驗證
管理窗口的登錄
從另外的虛擬機去登錄訪問當前mycat,輸入如下命令即可
mysql -uroot -p123456 -P 9066 -h 192.168.85.111
此時訪問的是mycat的管理窗口,可以通過show @@help查看可以執行的命令
數據窗口的登錄
從另外的虛擬機去登錄訪問mycat,輸入命令如下:
mysql -uroot -p123456 -P8066 -h 192.168.85.111
當都能夠成功的時候以為着mycat已經搭建完成。
2、讀寫分離
通過mycat和mysql的主從復制配合搭建數據庫的讀寫分離,可以實現mysql的高可用性,下面我們來搭建mysql的讀寫分離。
1、一主一從(主從復制的原理之前講解過了,需要的同學自行參閱文檔)
1、在node01上修改/etc/my.cnf的文件
#mysql服務唯一id,不同的mysql服務必須擁有全局唯一的id
server-id=1
#啟動二進制日期
log-bin=mysql-bin
#設置不要復制的數據庫
binlog-ignore-db=mysql
binlog-ignore-db=information-schema
#設置需要復制的數據庫
binlog-do-db=msb
#設置binlog的格式
binlog_format=statement
2、在node02上修改/etc/my.cnf文件
#服務器唯一id
server-id=2
#啟動中繼日志
relay-log=mysql-relay
3、重新啟動mysql服務
4、在node01上創建賬戶並授權slave
grant replication slave on *.* to 'root'@'%' identified by '123456';
--在進行授權的時候,如果提示密碼的問題,把密碼驗證取消
set global validate_password_policy=0;
set global validate_password_length=1;
5、查看master的狀態
show master status
6、在node02上配置需要復制的主機
CHANGE MASTER TO MASTER_HOST='192.168.85.111',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=437;
7、啟動從服務器復制功能
start slave;
8、查看從服務器狀態
show slave status\G
當執行完成之后,會看到兩個關鍵的屬性Slave_IO_Running,Slave_SQL_Running,當這兩個屬性都是yes的時候,表示主從復制已經准備好了,可以進行具體的操作了
2、一主一從驗證
下面我們通過實際的操作來驗證主從復制是否完成。
--在node01上創建數據庫
create database msb;
--在node01上創建具體的表
create table mytbl(id int,name varchar(20));
--在node01上插入數據
insert into mytbl values(1,'zhangsan');
--在node02上驗證發現數據已經同步成功,表示主從復制完成
通過mycat實現讀寫分離
在node01上插入如下sql語句,
-- 把主機名插入數據庫中
insert into mytbl values(2,@@hostname);
-- 然后通過mycat進行數據的訪問,這個時候大家發現無論怎么查詢數據,最終返回的都是node01的數據,為什么呢?
select * from mytbl;
在之前的mycat基本配置中,其實我們已經配置了讀寫分離,大家還記得readHost和writeHost兩個標簽嗎?
<writeHost host="hostM1" url="192.168.85.111:3306" user="root" password="123456">
<readHost host="hostS1" url="192.168.85.112:3306" user="root" password="123456"></readHost>
</writeHost>
其實我們已經配置過了這兩個標簽,默認情況下node01是用來完成寫入操作的,node02是用來完成讀取操作的,但是剛剛通過我們的驗證發現所有的讀取都是node01完成的,這是什么原因呢?
原因很簡單,就是因為我們在進行配置的時候在 dataHost 標簽中缺失了一個非常重要的屬性balance,此屬性有四個值,用來做負載均衡的,下面我們來詳細介紹
1、balance=0 :不開啟讀寫分離機制,所有讀操作都發送到當前可用的writehost上
2、balance=1:全部的readhost和stand by writehost參與select 語句的負載均衡,簡單的說,當雙主雙從模式下,其他的節點都參與select語句的負載均衡
3、balance=2:所有讀操作都隨機的在writehost,readhost上分發
4、balance=3:所有讀請求隨機的分發到readhost執行,writehost不負擔讀壓力
當了解了這個參數的含義之后,我們可以將此參數設置為2,就能夠看到在兩個主機上切換執行了。
3、雙主雙從
在上述的一主一從的架構設計中,很容易出現單點的問題,所以我們要想讓生產環境中的配置足夠穩定,可以配置雙主雙從,解決單點的問題。
架構圖如下所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-IDdixBdV-1594697254416)(E:\lian\mycat\image\雙主雙從.png)] 在此架構中,可以讓一台主機用來處理所有寫請求,此時,它的從機和備機,以及備機的從機復制所有讀請求,當主機宕機之后,另一台主機負責寫請求,兩台主機互為備機。
主機分布如下:
編號 | 角色 | ip | 主機名 |
---|---|---|---|
1 | master1 | 192.168.85.111 | node01 |
2 | slave1 | 192.168.85.112 | node02 |
3 | master2 | 192.168.85.113 | node03 |
4 | slave2 | 192.168.85.114 | node04 |
下面開始搭建雙主雙從。
1、修改node01上的/etc/my.cnf文件
#主服務器唯一ID
server-id=1
#啟用二進制日志
log-bin=mysql-bin
# 設置不要復制的數據庫(可設置多個)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#設置需要復制的數據庫
binlog-do-db=msb
#設置logbin格式
binlog_format=STATEMENT
# 在作為從數據庫的時候, 有寫入操作也要更新二進制日志文件
log-slave-updates
#表示自增長字段每次遞增的量,指自增字段的起始值,其默認值是1, 取值范圍是1 .. 65535
auto-increment-increment=2
# 表示自增長字段從哪個數開始,指字段一次遞增多少,他的取值范圍是1 .. 65535
auto-increment-offset=1
2、修改node03上的/etc/my.cnf文件
#主服務器唯一ID
server-id=3
#啟用二進制日志
log-bin=mysql-bin
# 設置不要復制的數據庫(可設置多個)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#設置需要復制的數據庫
binlog-do-db=msb
#設置logbin格式
binlog_format=STATEMENT
# 在作為從數據庫的時候,有寫入操作也要更新二進制日志文件
log-slave-updates
#表示自增長字段每次遞增的量,指自增字段的起始值,其默認值是1,取值范圍是1 .. 65535
auto-increment-increment=2
# 表示自增長字段從哪個數開始,指字段一次遞增多少,他的取值范圍是1 .. 65535
auto-increment-offset=2
3、修改node02上的/etc/my.cnf文件
#從服務器唯一ID
server-id=2
#啟用中繼日志
relay-log=mysql-relay
4、修改node04上的/etc/my.cnf文件
#從服務器唯一ID
server-id=4
#啟用中繼日志
relay-log=mysql-relay
5、所有主機重新啟動mysql服務
6、在兩台主機node01,node03上授權同步命令
GRANT REPLICATION SLAVE ON *.* TO 'root'@'%' IDENTIFIED BY '123456';
7、查看兩台主機的狀態
show master status;
8、在node02上執行要復制的主機
CHANGE MASTER TO MASTER_HOST='192.168.85.111',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
9、在node04上執行要復制的主機
CHANGE MASTER TO MASTER_HOST='192.168.85.113',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
10、啟動兩個從機的slave並且查看狀態,當看到兩個參數都是yes的時候表示成功
start slave;
show slave status;
11、完成node01跟node03的相互復制
--在node01上執行
CHANGE MASTER TO MASTER_HOST='192.168.85.113',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=442;
--開啟slave
start slave
--查看狀態
show slave status\G
--在node03上執行
CHANGE MASTER TO MASTER_HOST='192.168.85.111',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=442;
--開啟slave
start slave
--查看狀態
show slave status\G
4、雙主雙從驗證
在node01上執行如下sql語句:
create database msb;
create table mytbl(id int,name varchar(20));
insert into mytbl values(1,'zhangsan');
--完成上述命令之后可以去其他機器驗證是否同步成功
當上述操作完成之后,我們可以驗證mycat的讀寫分離,此時我們需要進行重新的配置,修改schema.xml文件。
在當前mysql架構中,我們使用的是雙主雙從的架構,因此可以將balance設置為1
除此之外我們需要注意,還需要了解一些參數:
參數writeType,表示寫操作發送到哪台機器,此參數有兩個值可以進行設置:
writeType=0:所有寫操作都發送到配置的第一個writeHost,第一個掛了切換到還生存的第二個
writeType=1:所有寫操作都隨機的發送到配置的writehost中,1.5之后廢棄,
需要注意的是:writehost重新啟動之后以切換后的為准,切換記錄在配置文件dnindex.properties中
參數switchType:表示如何進行切換:
switchType=1:默認值,自動切換
switchType=-1:表示不自動切換
switchType=2:基於mysql主從同步的狀態決定是否切換
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="host1" database="msb" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.85.111:3306" user="root" password="123456">
<readHost host="hostS1" url="192.168.85.112:3306" user="root" password="123456"></readHost>
</writeHost>
<writeHost host="hostM2" url="192.168.85.113:3306" user="root" password="123456">
<readHost host="hostS2" url="192.168.85.114:3306" user="root" password="123456"></readHost>
</writeHost>
</dataHost>
</mycat:schema>
下面開始進行讀寫分離的驗證
--插入以下語句,使數據不一致
insert into mytbl values(2,@@hostname);
--通過查詢mycat表中的數據,發現查詢到的結果在node02,node03,node04之間切換,符合正常情況
select * from mytbl;
--停止node01的mysql服務
service mysqld stop
--重新插入語句
insert into mytbl values(3,@@hostname);
--開啟node01的mysql服務
service mysqld start
--執行相同的查詢語句,此時發現在noede01,node02,node04之間切換,符合情況
通過上述的驗證,我們可以得到一個結論,node01,node03互做備機,負責寫的宕機切換,其他機器充作讀請求的響應。
做到此處,希望大家能夠思考一個問題,在上述我們做的讀寫分離操作,其實都是基於主從復制的,也就是數據同步,但是在生產環境中會存在很多種情況造成主從復制延遲問題,那么我們應該如何解決延遲問題,這是一個值得思考的問題,到底如何解決呢?
3、數據切分
數據切分指的是通過某種特定的條件,將我們存放在同一個數據庫中的數據分散存放到多個數據庫上面,以達到分散單台設備負載的效果。
數據的切分根據其切分規則的類型,可以分為兩種切分模式。一種是按照不同的表來切分到不同的數據庫之上,這種切可以稱之為數據的垂直切分或者縱向切分,另外一種則是根據表中的數據的邏輯關系,將同一個表中的數據按照某種條件拆分到多台數據庫上面,這種切分稱之為數據的水平切分或者橫向切分。
垂直切分的最大特點就是 規則簡單,實施也更為方便,尤其適合各業務之間的耦合度非常低,相互影響很小,業務邏輯非常清晰的系統。在這種系統中,可以很容易做到將不同業務模塊所使用的表分拆到不同的數據庫中。根據不同的表來進行拆分,對應用程序的影響也很小,拆分規則也會比較簡單清晰。
水平切分與垂直切分相比,相對來說稍微復雜一些。因為要將同一個表中的不同數據拆分到不同的數據庫中,對於應用程序來說,拆分規則本身就較根據表明來拆分更為復雜,后期的數據維護也會更為復雜一些。
1、垂直切分
一個數據庫由很多表的構成,每個表對應着不同的業務,垂直切分是指按照業務將表進行分類,分布到不同的數據庫上面,這樣也就將數據或者壓力分擔到不同的庫上面。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7T5PxOMO-1594697254419)(image\垂直切分.png)]
如上圖所示,一個系統被切分成了用戶系統、訂單交易、支付系統等多個庫。
一個架構設計較好的應用系統,其總體功能肯定是又多個功能模塊所組成的。而每一個功能模塊所需要的數據對應到數據庫中就是一個或者多個表。而在架構設計中,各個功能模塊相關質檢的交互點越統一越少,系統的耦合度就越低,系統各個模塊的維護性以及擴展性也就越好。這樣的系統,實現數據的垂直切分也就越容易。
但是往往系統中有些表難以做到完全的獨立,存在着跨庫join的情況,對於這類的表,就需要去做平衡,是數據讓步業務,共用一個數據源還是分成多個庫,業務之間通過接口來做調用。在系統初期,數據量比較少,或者資源有限的情況下,會選擇共用數據源,但是當數據發展到一定規模,負載很大的情況下就必須要做分割。
一般來講業務存在着復雜join的場景是難以切分的,往往業務獨立的易於切分。如何切分,切分到何種程度是考驗技術架構的一個難題。下面來分析下垂直切分的優缺點:
優點:
1、拆分后業務清晰,拆分規則明確
2、系統之間整合或擴展容易
3、數據維護簡單
缺點:
1、部分業務表無法實現join,只能通過接口方式解決,提高了系統復雜度
2、受每種業務不同的限制存在單庫性能瓶頸,不易數據擴展跟性能提高
3、事務處理復雜
2、水平切分
相對於垂直拆分,水平拆分不是將表做分類,而是按照某個字段的某種規則來分散到多個庫中,每個表中包含一部分數據。簡單來說,我們可以將數據的水平切分理解為是按照數據行切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其他的數據庫中,
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Q5nfNsif-1594697254422)(image\水平切分.png)]
拆分數據就需要定義分片規則。關系型數據庫是行列的二維模型,拆分的第一原則是找到拆分維度。比如從會員的角度來分析,商戶訂單交易類系統中查詢會員某天某月某個訂單,那么就需要按照會員結合日期來拆分,不同的數據按照會員id做分組,這樣所有的數據查詢join都會在單庫內解決;如果從商戶的角度來講,要查詢某個商家某天所有的訂單數,就需要按照商戶id做拆分;但是如果系統既想按照會員拆分,又想按照商家數據拆分,就會有一定的困難,需要綜合考慮找到合適的分片。
幾種典型的分片規則包括:
1、按照用戶id取模,將數據分散到不同的數據庫,具有相同數據用戶的數據都被分散到一個庫中;
2、按照日期,將不同月甚至日的數據分散到不同的庫中;
3、按照某個特定的字段求模,或者根據特定范圍段分散到不同的庫中。
如圖,切分原則都是根據業務找到適合的切分規則分散到不同的庫,下圖是用用戶id求模的案例:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hD4WHU1E-1594697254424)(image\數據切分案例.png)]
數據做完了水平拆分之后也是有優缺點的。
優點:
1、拆分規則抽象好,join操作基本可以數據庫做;
2、不存在單庫大數據,高並發的性能瓶頸;
3、應用端改造較少;
4、提高了系統的穩定性跟負載能力
缺點:
1、拆分規則難以抽象
2、分片事務一致性難以解決
3、數據多次擴展跟維護量極大
4、跨庫join性能較差
3、總結
我們剛剛講解了數據切分的兩種方式,會發現每種方式都有自己的缺點,但是他們之間有共同的缺點,分別是:
1、引入了分布式事務的問題
2、跨節點join的問題
3、跨節點合並排序分頁的問題
4、多數據源管理的問題
針對數據源管理,目前主要有兩種思路:
1、客戶端模式,在每個應用程序模塊中配置管理自己需要的一個或多個數據源,直接訪問各個數據庫,在模塊內完成數據的整合
2、通過中間代理層來統一管理所有的數據源,后端數據庫集群對前端應用程序透明;
在實際的生產環境中,我們都會選擇第二種方案來解決問題,尤其是系統不斷變得龐大復雜的時候,其實這是非常正確的,雖然短期內付出的成本可能會比較大,但是對整個系統的擴展性來說,是非常有幫助的。
mycat通過數據切分解決傳統數據庫的缺陷,又有了nosql易於擴展的優點。通過中間代理層規避了多數據源的數據問題,對應用完全透明,同時對數據切分后存在的問題,也做了解決方案。
mycat在做數據切分的時候應該盡可能的遵循以下原則,當然這也是經驗之談,最終的落地實現還是要看具體的應用場景在做具體的分析
第一原則:能不切分盡量不要切分
第二原則:如果要切分一定要選擇合適的切分規則,提前規划好
第三原則:數據切分盡量通過數據冗余或表分組來降低跨庫join的可能
第四原則:由於數據庫中間件對數據join實現的優劣難以把握,而且實現高性能難度極大,業務讀取盡量少使用多表join。
4、mycat的配置文件講解
在之前的操作中,我們已經做了部分文件的配置,但是具體的屬性並沒有講解,下面我們講解下每一個配置文件具體的屬性以及相關的基本配置。
1、搞定schema.xml文件
schema.xml作為mycat中重要地配置文件之一,管理者mycat的邏輯庫、表、分片規則、DataNode以及DataSource。
1、schema標簽
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
schema標簽用於定義mycat實例中的邏輯庫,mycat可以有多個邏輯庫,每個邏輯庫都有自己相關的配置,可以使用schema標簽來划分這些不同的邏輯庫。如果不配置schame,那么所有的表配置都將屬於同一個默認的邏輯庫。
**dataNode:**該屬性用於綁定邏輯庫到某個具體的database上。
**checkSQLschema:**當該值為true時,如果執行select * from TESTDB.user,那么mycat會將語句修改為select * from user,即把表示schema的字符去掉,避免發送到后端數據庫執行時報錯。
**sqlMaxLimit:**當該值設置為某個數值的時候,每次執行的sql語句,如果沒有加上limit語句,mycat也會自動加上對應的值。例如,當設置值為100的時候,那么select * from user的效果跟執行select * from user limit 100相同。如果不設置該值的話,mycat默認會把所有的數據信息都查詢出來,造成過多的輸出,所以,還是建議設置一個具體的值,以減少過多的數據返回。當然sql語句中可以顯式的制定limit的大小,不受該屬性的約束。
2、table標簽
<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" ></table>
table標簽定義了mycat中的邏輯表,所有需要拆分的表都需要在這個標簽中定義。
**name:**定義邏輯表的表名,這個名字就如同創建表的時候指定的表名一樣,同個schema標簽中定義的名字必須唯一。
**dataNode:**定義這個邏輯表所屬的dataNode,該屬性的值需要和dataNode標簽中的name屬性值對應,如果需要定義的dn過多,可以使用如下方法減少配置:
<table name="travelrecord" dataNode="multipleDn$0-99,multipleDn2$100-199" rule="auto-shardinglong" ></table>
<dataNode name="multipleDn$0-99" dataHost="localhost1" database="db$0-99" ></dataNode>
<dataNode name="multipleDn2$100-199" dataHost="localhost1" database=" db$100-199" ></dataNode>
**rule:**該屬性用於指定邏輯表要使用的規則名字,規則名字在rule.xml中定義,必須與tableRule標簽中的name屬性值一一對應
**ruleRequired:**該屬性用於指定表是否綁定分片規則,如果配置為true,但沒有配置具體rule的話,程序會報錯。
**primaryKey:**該邏輯表對應真實表的主鍵,例如:分片的規則是使用非主鍵進行分片的,那么在使用主鍵查詢的時候,就會發送查詢語句到所有配置的DN上,如果使用改屬性配置真實表的主鍵。那么mycat會緩存主鍵與具體DN的信息,那么再次使用非主鍵進行查詢的時候就不會進行廣播式的查詢,就會直接發送語句到具體的DN,但是盡管配置改屬性,如果緩存沒有命中的話,還是會發送語句給具體的DN來獲得數據
**type:**該屬性定義了邏輯表的類型,目前邏輯表只有全局表和普通表兩種類型。對應的配置:
全局表:global
普通表:不指定該值為global的所有表
**autoIncrement:**mysql 對非自增長主鍵,使用 last_insert_id()是不會返回結果的,只會返回 0。所以,只有定義了自增長主鍵的表才可以用 last_insert_id()返回主鍵值。mycat 目前提供了自增長主鍵功能,但是如果對應的 mysql 節點上數據表,沒有定義 auto_increment,那么在 mycat 層調用 last_insert_id()也是不會返回結果的。由於 insert 操作的時候沒有帶入分片鍵, mycat 會先取下這個表對應的全局序列,然后賦值給分片鍵。 這樣才能正常的插入到數據庫中,最后使用 last_insert_id()才會返回插入的分片鍵值。如果要使用這個功能最好配合使用數據庫模式的全局序列。使用 autoIncrement=“true” 指定這個表有使用自增長主鍵,這樣 mycat 才會不拋出分片鍵找不到的異常。使用 autoIncrement=“false” 來禁用這個功能,當然你也可以直接刪除掉這個屬性。默認就是禁用的。
**needAddLimit:**指定表是否需要自動的在每個語句后面加上limit限制。由於使用了分庫分表,數據量有時會特別巨大。這時候執行查詢語句,如果恰巧又忘記了加上數量限制的話,那么查詢所有的數據出來,就會執行很久的時間,所以mycat自動為我們加上了limit 100。當前如果語句中又limit,那么就不會添加了。
3、childTable標簽
childTable標簽用於定義ER分片的子表。通過標簽上的屬性與父表進行關聯。
**name:**定義子表的表名
**joinKey:**插入子表的時候會使用這個列的值查找父表存儲的數據節點
**parentKey:**屬性指定的值一般為與父表建立關聯關系的列名。程序首先獲取joinkey的值,再通過parentKey屬性指定的列名產生查詢語句,通過執行該語句得到父表存儲再哪個分片上,從而確定子表存儲的位置。
**primaryKey:**跟table標簽所描述相同
**needAddLimit:**跟table標簽所描述相同
4、dataNode標簽
<dataNode name="dn1" dataHost="lch3307" database="db1" ></dataNode>
dataNode標簽定義了mycat中的數據節點,也就是我們通常說的數據分片,一個dataNode標簽就是一個獨立的數據分片。
**name:**定義數據節點的名字,這個名字需要是唯一的,我們需要再table標簽上應用這個名字,來建立表與分片對應的關系
**dataHost:**該屬性用於定義該分片屬於哪個數據庫實例,屬性值是引用dataHost標簽上定義的name屬性。
**database:**該屬性用於定義該分片屬性哪個具體數據庫實力上的具體庫,
5、dataHost標簽
該標簽定義了具體的數據庫實例、讀寫分離配置和心跳語句
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="localhost:3306" user="root" password="123456">
<!-- can have multi read hosts -->
<!-- <readHost host="hostS1" url="localhost:3306" user="root" password="123456" /> -->
</writeHost>
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
**name:**唯一標識dataHost標簽,供上層的標簽使用
**maxcon:**指定每個讀寫實例連接池的最大連接
**mincon:**指定每個讀寫實例連接連接池的最小鏈接,初始化連接池的大小
**balance:**負載均衡類型:
0:不開啟讀寫分離機制,所有讀操作都發送到當前可用的writeHost上
1:全部的readHost和stand by writeHost參與select語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1,M2->S2,並且M1與M2互為主備),正常情況下,M2,S1,S2都參與select語句的負載均衡
2:所有讀操作都隨機的再writeHost、readHost上分發
3:所有讀請求隨機的分發到writeHost對應readHost執行,writeHost不負擔讀壓力,在之后的版本中失效。
**writeType:**寫類型
writeType=0:所有的寫操作發送到配置的第一個writeHost,第一個掛了切換到還生存的第二個writeHost,重啟之后以切換后的為准,切換記錄保存在配置文件 dnindex.properties
writeType=1:所有寫操作都隨機的發送到配置的writeHost,1.5以后廢棄不推薦
**dbType:**指定后端連接的數據庫類型,如MySQL,mongodb,oracle
**dbDriver:**指定連接后端數據庫使用的Driver,目前可選的值有native和JDBC。使用native的話,因為這個值執行的是二進制的mysql協議,所以可以使用mysql和maridb,其他類型的數據庫則需要使用JDBC驅動來支持。
**switchType:**是否進行主從切換
-1:表示不自動切換
1:默認值,自動切換
2:基於mysql主從同步的狀態決定是否切換
6、heartbeat標簽
這個標簽指明用於和后端數據庫進行心跳檢測的語句。
2、搞定server.xml文件
server.xml幾乎保存了所有mycat需要的系統配置信息。
<user name="test">
<property name="password">test</property>
<property name="schemas">TESTDB</property>
<property name="schemas">TESTDB</property>
<property name="schemas">TESTDB</property>
<property name="schemas">TESTDB</property>
<privileges check="false">
<schema name="TESTDB" dml="0010" showTables="custome/mysql">
<table name="tbl_user" dml="0110"></table>
<table name="tbl_dynamic" dml="1111"></table>
</schema>
</privileges>
</user>
server.xml中的標簽本就不多,這個標簽主要用於定義登錄mycat的用戶和權限。
property標簽用來聲明具體的屬性值,name用來指定用戶名,password用來修改密碼,readonly用來限制用戶是否是只讀的,schemas用來控制用戶課訪問的schema,如果有多個的話,用逗號分隔
privileges標簽是對用戶的schema及下級的table進行精細化的DML控制,privileges節點的check屬性適用於標識是否開啟DML權限檢查,默認false標識不檢查,當然不配置等同於不檢查
在進行檢查的時候,是通過四個二進制位來標識的,insert,update,select,delete按照順序標識,0表示未檢查,1表示要檢查
system標簽表示系統的相關屬性:
屬性 | 含義 | 備注 |
---|---|---|
charset | 字符集設置 | utf8,utf8mb4 |
defaultSqlParser | 指定的默認解析器 | druidparser,fdbparser(1.4之后作廢) |
processors | 系統可用的線程數, | 默認為機器CPU核心線程數 |
processorBufferChunk | 每次分配socket direct buffer的大小 | 默認是4096個字節 |
processorExecutor | 指定NIOProcessor共享的businessExecutor固定線程池大小,mycat在處理異步邏輯的時候會把任務提交到這個線程池中 | |
sequnceHandlerType | mycat全局序列的類型 | 0為本地文件,1為數據庫方式,2為時間戳方式,3為分布式ZK ID生成器,4為zk遞增id生成 |
3、rule.xml
rule.xml里面就定義了我們對表進行拆分所涉及到的規則定義。我們可以靈活的對表使用不同的分片算法,或者對表使用相同的算法但具體的參數不同,這個文件里面主要有tableRule和function這兩個標簽。
1、tableRule
這個標簽被用來定義表規則,定義的表規則在schema.xml文件中
<tableRule name="rule1">
<rule>
<columns>id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
name屬性指定唯一的名字,用來標識不同的表規則
內嵌的rule標簽則指定對物理表中的哪一列進行拆分和使用什么路由算法
columns內指定要拆分的列的名字
algorithm使用function標簽中的那么屬性,連接表規則和具體路由算法。當然,多個表規則可以連接到同一個路由算法上。
2、function
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
</function>
name指定算法的名字
class指定路由算法具體的類名字
property為具體算法需要用到的一些屬性