一、快速啟動
mysql主從搭建請點擊這里
下載安裝包:http://dl.mycat.io/1.6.7.4/,我這里下載的是1.6.7.4(目前最新發(fā)布版),運行bin目錄下:
#linux環(huán)境下
./mycat start 啟動
./mycat stop 停止
./mycat console 前臺運行
./mycat restart 重啟服務(wù)
./mycat pause 暫停
./mycat status 查看啟動狀態(tài)
#windows環(huán)境
直接運行startup_nowrap.bat,如果出現(xiàn)閃退,在cmd 命令行運行,查看出錯原因。
二、配置
配置文件存放在conf目錄下:
- schema.xml 是邏輯庫定義和表以及分片定義的配置文件。
- rule.xml 是分片規(guī)則的配置文件,分片規(guī)則的具體一些參數(shù)信息單獨存放為文件,也在這個目錄下,配置文件修改需要重啟MyCAT
- server.xml 是Mycat服務(wù)器參數(shù)調(diào)整和用戶授權(quán)的配置文件。
- log4j.xml: 日志存放在logs/log中,每天一個文件,日志的配置是在conf/log4j.xml中,根據(jù)自己的需要可以調(diào)整輸出級別為debug,debug級別下,會輸出更多的信息,方便排查問題。
- autopartition-long.txt,partition-hash-int.txt,sequence_conf.properties,sequence_db_conf.properties 分片相關(guān)的id分片規(guī)則配置文件
lib MyCAT自身的jar包或依賴的jar包的存放目錄。
logs MyCAT日志的存放目錄。日志存放在logs/log中,每天一個文件
2.1 server.xml(Mycat環(huán)境參數(shù)配置)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
<mycat:server xmlns:mycat="http://org.opencloudb/">
<system>
<property name="defaultSqlParser">druidparser</property>
</system>
</mycat:server>
如例子中配置的所有的Mycat參數(shù)變量都是配置在server.xml 文件中,system標簽下配置所有的參數(shù),如果需要配置某個變量添加相應(yīng)的配置即可,例如添加啟動端口8066,默認為8066:<property name="serverPort">8066</property>
配置Mycat邏輯庫與用戶:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
<user name="mycat">
<property name="password">mycat</property>
<property name="schemas">TESTDB</property>
</user>
</mycat:server>
如例子中配置的所有的Mycat連接的用戶與邏輯庫映射都是配置在server.xml 文件中,user標簽下配置所有的參數(shù),例如例子中配置了一個mycat用戶供應(yīng)用連接到mycat,同時mycat 在schema.xml中配置后了一個邏輯庫TESTDB,配置好邏輯庫與用戶的映射關(guān)系。
2.2schema.xml(邏輯庫配置)
Mycat作為一個中間件,實現(xiàn)mysql協(xié)議那么對前端應(yīng)用連接來說就是一個數(shù)據(jù)庫,也就有數(shù)據(jù)庫的配置,mycat的數(shù)據(jù)庫配置是在schema.xml中配置,配置好后映射到server.xml里面的用戶就可以了。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
<table name="t_user" dataNode="dn1,dn2" rule="sharding-by-mod2"/>
<table name="ht_jy_login_log" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-date_jylog"/>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="mycat_node1"/>
<dataNode name="dn2" dataHost="localhost1" database="mycat_node2"/>
<dataHost name="localhost1" writeType="0" switchType="1" slaveThreshold="100" balance="1" dbType="mysql" maxCon="10" minCon="1" dbDriver="native">
<heartbeat>show status like 'wsrep%'</heartbeat>
<writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="root" >
</writeHost>
</dataHost>
</mycat:schema >
上面例子配置了一個邏輯庫TESTDB,同時配置了t_user,ht_jy_login_log兩個分片表。
邏輯表配置:
<table name="t_user" dataNode="dn1,dn2" rule="sharding-by-mod2"/>
table 標簽 是邏輯表的配置其中
name代表表名,
dataNode代表表對應(yīng)的分片,
Mycat默認采用分庫方式,也就是一個表映射到不同的庫上,
rule代表表要采用的數(shù)據(jù)切分方式,名稱對應(yīng)到rule.xml中的對應(yīng)配置,如果要分片必須配置。
配置分片(dataNode):
<dataNode name="dn1" dataHost="localhost1" database="mycat_node1"/>
<dataNode name="dn2" dataHost="localhost1" database="mycat_node2"/>
表切分后需要配置映射到哪幾個數(shù)據(jù)庫中,Mycat的分片實際上就是庫的別名,例如上面例子配置了兩個分片dn1,dn2 分別對應(yīng)到物理機映射dataHost localhost1 的兩個庫上。
配置物理庫分片映射(dataHost):
<dataHost name="localhost1" writeType="0" switchType="1" slaveThreshold="100" balance="1" dbType="mysql" maxCon="10" minCon="1" dbDriver="native">
<heartbeat>show status like 'wsrep%'</heartbeat>
<writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="root" >
</writeHost>
</dataHost>
Mycat作為數(shù)據(jù)庫代理需要邏輯庫,邏輯用戶,表切分后需要配置分片,分片也就需要映射到真實的物理主機上,至于是映射到一臺還是一臺的多個實例上,Mycat并不關(guān)心,只需要配置好映射即可,例如例子中:
配置了一個名為localhost1的物理主機(dataHost)映射。
heartbeat 標簽代表Mycat需要對物理庫心跳檢測的語句,正常情況下生產(chǎn)案例可能配置主從,或者多寫 或者單庫,無論哪種情況Mycat都需要維持到數(shù)據(jù)庫的數(shù)據(jù)源連接,因此需要定時檢查后端連接可以性,心跳語句就是來作為心跳檢測。
writeHost 此標簽代表 一個邏輯主機(dataHost)對應(yīng)的后端的物理主機映射,例如例子中寫庫hostM1 映射到127.0.0.1:3306。如果后端需要做讀寫分離或者多寫 或者主從則通過配置 多個writeHost 或者readHost即可。
dataHost 標簽中的 writeType balance 等標簽則是不同的策略
主從配置:
<dataHost name="localhost1" maxCon="10" minCon="5" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="192.168.126.128:3306" user="root"
password="123456">
<readHost host="hostS1" url="192.168.126.129:3306" user="root" password="123456" />
</writeHost>
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
balance 屬性
負載均衡類型,目前的取值有 3 種:
1.balance="0", 不開啟讀寫分離機制,所有讀操作都發(fā)送到當前可用的 writeHost 上。
2.balance="1",全部的 readHost 與 stand by writeHost 參與 select 語句的負載均衡,簡單的說,當雙
主雙從模式(M1->S1,M2->S2,并且 M1 與 M2 互為主備),正常情況下,M2,S1,S2 都參與 select 語句的負載
均衡。
3.balance="2",所有讀操作都隨機的在 writeHost、readhost 上分發(fā)。
4.balance="3",所有讀請求隨機的分發(fā)到 wiriterHost 對應(yīng)的 readhost 執(zhí)行,writerHost 不負擔讀壓力,
注意 balance=3 只在 1.4 及其以后版本有,1.3 沒有
writeType 屬性
負載均衡類型,目前的取值有 3 種:
1. writeType="0", 所有寫操作發(fā)送到配置的第一個 writeHost,第一個掛了切到還生存的第二個 writeHost,
重新啟動后已切換后的為準,切換記錄在配置文件中:dnindex.properties .
2. writeType="1",所有寫操作都隨機的發(fā)送到配置的 writeHost,1.5 以后廢棄不推薦。
switchType 屬性
-1 表示不自動切換
1 默認值,自動切換
2 基于 MySQL 主從同步的狀態(tài)決定是否切換
心跳語句為 show slave status
3 基于 MySQL galary cluster 的切換機制(適合集群)(1.4.1)
心跳語句為 show status like 'wsrep%'
2.3 rule.xml(表切分規(guī)則配置)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://org.opencloudb/">
<tableRule name="sharding-by-hour">
<rule>
<columns>createTime</columns>
<algorithm>sharding-by-hour</algorithm>
</rule>
</tableRule>
<function name="sharding-by-hour" class="org.opencloudb.route.function.LatestMonthPartion">
<property name="splitOneDay">24</property>
</function>
</mycat:rule >
數(shù)據(jù)切分中作為表切分規(guī)則中最重要的配置,表的切分方式?jīng)Q定了數(shù)據(jù)切分后的性能好壞,因此也是最重要的配置。
如上面例子配置了一個切分規(guī)則,名為sharding-by-hour 對應(yīng)的切分方式(function )是按日期切分,該配置中:
tableRule 表分片規(guī)則
- name 為schema.xml 中table 標簽中對應(yīng)的 rule="sharding-by-hour" ,也就是配置表的分片規(guī)則
- columns 是表的切分字段: createTime 創(chuàng)建日期。
- algorithm 是規(guī)則對應(yīng)的切分規(guī)則:映射到function 的name。
function 分片規(guī)則函數(shù)
- name 為切分規(guī)則的名稱,名字任意取,但是需要與tableRule 中匹配。
- class 是切分規(guī)則對應(yīng)的切分類,寫死,需要哪種規(guī)則則配置哪種,例如本例子是按小時分片:org.opencloudb.route.function.LatestMonthPartion
- property 標簽是切分規(guī)則對應(yīng)的不同屬性,不同的切分規(guī)則配置不同。
常見的分片策略
分片枚舉
通過在配置文件中配置可能的枚舉 id,自己配置分片,本規(guī)則適用于特定的場景,比如有些業(yè)務(wù)需要按照省 份或區(qū)縣來做保存,而全國省份區(qū)縣固定的,這類業(yè)務(wù)使用本條規(guī)則固定分片 hash 算法
本條規(guī)則類似于十進制的求模運算,區(qū)別在于是二進制的操作,是取 id 的二進制低 10 位,即 id 二進制 &1111111111。 此算法的優(yōu)點在于如果按照 10 進制取模運算,在連續(xù)插入 1-10 時候 1-10 會被分到 1-10 個分片,增 大了插入的事務(wù)控制難度,而此算法根據(jù)二進制則可能會分到連續(xù)的分片,減少插入事務(wù)事務(wù)控制難度。
id=1
0000000001&1111111111=0000000001
<tableRule name="rule1">
<rule>
<columns>user_id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<function name="func1" class="io.mycat.route.function.PartitionByLong">
<property name="partitionCount">2,1</property>
<property name="partitionLength">256,512</property>
</function>
配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函數(shù), partitionCount 分片個數(shù)列表,partitionLength 分片范圍列表 分區(qū)長度:默認為最大 2^n=1024 ,即最大支持 1024 分區(qū)
約束: count,length 兩個數(shù)組的長度必須是一致的。 1024 = sum((count[i]*length[i])). count 和 length 兩個向量的點積恒等于 1024
用法例子: 本例的分區(qū)策略:希望將數(shù)據(jù)水平分成 3 份,前兩份各占 25%,第三份占 50%。(故本例非均勻分區(qū)) // |<-------1024----------->|
-
范圍約定
此分片適用于,提前規(guī)劃好分片字段某個范圍屬于哪個分片
<tableRule name="auto-sharding-long">
<rule>
<columns>user_id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
<property name="defaultNode">0</property>
</function>
配置說明:
上面 columns 標識將要分片的表字段,
algorithm 分片函數(shù),
rang-long 函數(shù)中
mapFile 代表配置文件路徑
defaultNode 超過范圍后的默認節(jié)點。
所有的節(jié)點配置都是從 0 開始,及 0 代表節(jié)點 1,此配置非常簡單
在配置文件autopartition-long.txt中即預(yù)先制定可能的 id 范圍到某個分片
0-500M=0
500M-1000M=1
1000M-1500M=2
或
0-10000000=0
10000001-20000000=1
注意:K=1000,M=10000
-
取模
此規(guī)則為對分片字段求摸運算
<tableRule name="mod-long">
<rule>
<columns>user_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">3</property>
</function>
配置說明: 上面 columns 標識將要分片的表字段,algorithm 分片函數(shù), 此種配置非常明確即根據(jù) id 進行十進制求模預(yù)算,相比固定分片 hash,此種在批量插入時可能存在批量插入單 事務(wù)插入多數(shù)據(jù)分片,增大事務(wù)一致性難度。
-
按日期(天)分片
此規(guī)則為按天分片
<tableRule name="sharding-by-date">
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-date</algorithm>
</rule>
</tableRule>
<function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2014-01-01</property>
<property name="sEndDate">2014-01-02</property>
<property name="sPartionDay">10</property>
</function>
-
冷熱數(shù)據(jù)分片
根據(jù)日期查詢?nèi)罩緮?shù)據(jù) 冷熱數(shù)據(jù)分布 ,最近 n 個月的到實時交易庫查詢,超過 n 個月的按照 m 天分片。
<function name="sharding-by-hotdate" class="io.mycat.route.function.PartitionByHotDate">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sLastDay">10</property>
<property name="sPartionDay">10</property>
</function>
2.4全局自增序列號
1. 本地文件方式
原理:此方式 MyCAT 將 sequence 配置到文件中,當使用到 sequence 中的配置后,MyCAT 會更下classpath 中的 sequence_conf.properties 文件中 sequence 當前的值。
配置方式:
在 sequence_conf.properties 文件中做如下配置:
GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=1001
GLOBAL_SEQ.MAXID=1000000000
GLOBAL_SEQ.CURID=1000
其中 HISIDS 表示使用過的歷史分段(一般無特殊需要可不配置),MINID 表示最小 ID 值,MAXID 表示最大
ID 值,CURID 表示當前 ID 值。
server.xml 中配置:
<system><property name="sequnceHandlerType">0</property></system>
注:sequnceHandlerType 需要配置為 0,表示使用本地文件方式。
使用示例:
insert into table1(id,name) values(next value for MYCATSEQ_GLOBAL,'test');
缺點:當 MyCAT 重新發(fā)布后,配置文件中的 sequence 會恢復(fù)到初始值。
優(yōu)點:本地加載,讀取速度較快。
2. 數(shù)據(jù)庫方式
原理:在數(shù)據(jù)庫中建立一張表,存放 sequence 名稱(name),sequence 當前值(current_value),步長(increment int類型每次讀取多少個sequence,假設(shè)為 K)等信息;
Sequence 獲取步驟:
- 當初次使用該 sequence 時,根據(jù)傳入的 sequence 名稱,從數(shù)據(jù)庫這張表中讀取 current_value和increment 到 MyCat 中,并將數(shù)據(jù)庫中的 current_value 設(shè)置為原 current_value 值+increment 值。
- MyCat 將讀取到 current_value+increment 作為本次要使用的 sequence 值,下次使用時,自動加 1,當使用 increment 次后,執(zhí)行步驟1相同的操作。MyCat 負責維護這張表,用到哪些 sequence,只需要在這張表中插入一條記錄即可。若某次讀取的sequence 沒有用完,系統(tǒng)就停掉了,則這次讀取的 sequence 剩余值不會再使用。
server.xml 配置:
<system><property name="sequnceHandlerType">1</property></system>
注:sequnceHandlerType 需要配置為 1,表示使用數(shù)據(jù)庫方式生成sequence。
數(shù)據(jù)庫配置:
-- 創(chuàng)建 MYCAT_SEQUENCE 表
DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (
NAME VARCHAR (50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 1,
PRIMARY KEY (NAME)
) ENGINE = INNODB;
-- 插入一條 sequence
INSERT INTO MYCAT_SEQUENCE(NAME,current_value,increment) VALUES ('GLOBAL', 0, 1);
-- 獲取當前 sequence 的值 (返回當前值,增量)
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50))
RETURNS VARCHAR(64) CHARSET utf8
DETERMINISTIC
BEGIN DECLARE retval VARCHAR(64);
SET retval="-999999999,null";
SELECT CONCAT(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval
FROM MYCAT_SEQUENCE WHERE NAME = seq_name;
RETURN retval ;
END
;;
DELIMITER ;
-- 獲取下一個 sequence 值
DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS VARCHAR(64)
CHARSET utf8
DETERMINISTIC
BEGIN UPDATE MYCAT_SEQUENCE
SET current_value = current_value + increment
WHERE NAME = seq_name;
RETURN mycat_seq_currval(seq_name);
END
;;
DELIMITER ;
-- 設(shè)置 sequence 值
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), VALUE INTEGER)
RETURNS VARCHAR(64) CHARSET utf8
DETERMINISTIC
BEGIN UPDATE MYCAT_SEQUENCE
SET current_value = VALUE
WHERE NAME = seq_name;
RETURN mycat_seq_currval(seq_name);
END
;;
DELIMITER ;
sequence_db_conf.properties 相關(guān)配置
例如:USER_SEQ=test_dn1
注意:MYCAT_SEQUENCE 表和以上的 3 個 function,需要放在同一個節(jié)點上。function 請直接在具體節(jié)點的數(shù)據(jù)庫上執(zhí)行,如果執(zhí)行的時候報:
you might want to use the less safe log_bin_trust_function_creators variable
需要對數(shù)據(jù)庫做如下設(shè)置:
/etc/my.cnf
[mysqld]
log_bin_trust_function_creators=1
修改完后,即可在 mysql 數(shù)據(jù)庫中執(zhí)行上面的函數(shù)。
使用示例:
insert into table1(id,name) values(next value for MYCATSEQ_GLOBAL,'test');
mycat 定義主鍵自增insert into table1(id,name) values(next value for MYCATSEQ_GLOBAL,'test');
上面語句需要向id字段插入'next value for MYCATSEQ_GLOBAL'標識字段。像mysql自增主鍵一樣的效果insert into table1(id,name) values(null,'test');后自動插入自增主鍵
說明:
MyCAT 目前提供了自增長主鍵功能,對應(yīng)的 mysql節(jié)點上數(shù)據(jù)表主鍵必須要是定義為 auto_increment
schema.xml配置表的primaryKey="id"和autoIncrement="true"
2.4 jvm配置
啟動前,一般需要修改JVM配置參數(shù),打開conf/wrapper.conf文件,如下行的內(nèi)容為2G和2048,可根據(jù)本機配置情況修改為512M或其它值。 以下配置跟jvm參數(shù)完全一致,可以根據(jù)自己的jvm參數(shù)調(diào)整。
Java Additional Parameters
wrapper.java.additional.1=
wrapper.java.additional.1=-DMYCAT_HOME=.
wrapper.java.additional.2=-server
wrapper.java.additional.3=-XX:MaxPermSize=64M
wrapper.java.additional.4=-XX:+AggressiveOpts
wrapper.java.additional.5=-XX:MaxDirectMemorySize=100m
wrapper.java.additional.6=-Dcom.sun.management.jmxremote
wrapper.java.additional.7=-Dcom.sun.management.jmxremote.port=1984
wrapper.java.additional.8=-Dcom.sun.management.jmxremote.authenticate=false
wrapper.java.additional.9=-Dcom.sun.management.jmxremote.ssl=false
wrapper.java.additional.10=-Xmx100m
wrapper.java.additional.11=-Xms100m
wrapper.java.additional.12=-XX:+UseParNewGC
wrapper.java.additional.13=-XX:+UseConcMarkSweepGC
wrapper.java.additional.14=-XX:+UseCMSCompactAtFullCollection
wrapper.java.additional.15=-XX:CMSFullGCsBeforeCompaction=0
wrapper.java.additional.16=-XX:CMSInitiatingOccupancyFraction=70