Mycat簡介
Mycat是一個實現了MySQL協議的Server,前端用戶可以把它看作是一個數據庫代理,用MySQL客戶端工具和命令行訪問,而後端可以用MySQL原生協議或JDBC協議與多個MySQL服務器通信,其核心功能是分庫分表和讀寫分離,即將一個大表水平分割爲N個小表,存儲在後端MySQL服務器裏或其他數據庫裏。
官網:http://www.mycat.org.cn/mycat1.html
Mycat核心概念
- 邏輯庫
對數據進行分片處理之後,從原來的一個庫,被切分爲多個分片數據庫,所有的分片數據庫集羣構成了整個完整的數據庫存儲。Mycat在操作時,使用邏輯庫來代表數據庫集羣,便於對整個集羣操作。
- 邏輯表
類似邏輯庫
- 分片表
分片表,是指那些數據量很大,需要切分到多個數據庫的表。每個分片都有一部分數據。如下mycat配置中的t_node就屬於分片表,數據按照規則被分到dn1,dn2兩個分片節點上。
<table name="t_node" primaryKey="vid" autoIncrement="true" dataNode="dn1,dn2"
rule="rule1" />
- 非分片表
就是那些不需要進行數據切分的表。如下配置t_node,只存在dn1分片節點上。
<table name="t_node" primaryKey="vid" autoIncrement="true" dataNode="dn1" />
- ER表
Mycat提出了基於E-R關係的數據分片策略,子表的記錄與所關聯的父表記錄存放在同一個數據分片上,即子表依賴於父表,通過表分組保證數據join不會跨庫操作。
- 全局表
一個真實的業務系統中,往往存在大量的類似字典表的表,這些表基本上很少變動,字典表具有下面幾個特性:
- 變動不頻繁
- 數據量總體變化不大
- 數據規模不大,很少超過數十萬條記錄
業務表與這些字典表之間的關聯查詢,會比較麻煩。所以Mycat通過數據冗餘來解決,即所有分片都有一份字典表的拷貝,所有字典表或者符合字典表特性的一些表定義爲全局表。
- 分片節點
數據分片後,一個大表被分到不同的分片數據庫上面,每個表分片所在的數據庫就是分片節點dataNode。
- 節點主機
數據切分後,每個分片節點不一定都會獨佔一臺機器,同一個機器上面可以有多個分片數據庫,這樣一個或多個分片節點所在的機器就是節點主機,爲了規避單節點主機併發數限制,儘量將讀寫壓力高的分片節點均衡的放在不同的節點主機dataHost。
- 分片規則
數據在進行切分的時候需要一定的規則,這種按照業務規則把數據分到某個分片的規則就是分片規則。
配置文件解析
1. server.xml配置
server.xml主要是系統配置信息
1.1 user標籤
這個標籤主要定義登錄mycat的用戶和權限。例如下面的例子中,我們定義了一個用戶,用戶名爲user,密碼也爲user,可訪問的schema爲lg_edu_order。
<user name="user">
<property name="password">user</property>
<property name="schemas">lg_edu_order</property>
<property name="readOnly">true</property>
<property name="defaultSchema">lg_edu_order</property>
</user>
1.2 firewall標籤
<firewall>
<!-- ip白名單 用戶對應的可以訪問的 ip 地址 -->
<whitehost>
<host host="127.0.0.*" user="root"/>
<host host="127.0.*" user="root"/>
<host host="127.*" user="root"/>
<host host="1*7.*" user="root"/>
</whitehost>
<!-- 黑名單允許的 權限 後面爲默認 -->
<blacklist check="true">
<property name="selelctAllow">false</property>
<property name="selelctIntoAllow">false</property>
<property name="updateAllow">false</property>
<property name="insertAllow">false</property>
<property name="deletetAllow">false</property>
<property name="dropAllow">false</property>
</blacklist>
</firewall>
1.3 全局序列號
在實現了分庫分表的情況下,數據庫自增主鍵無法保證主鍵的全局唯一。爲此Mycat提供了全局sequence,並提供了包含本地配置和數據庫配置等多種實現方式。
<system>
<property name="sequnceHandlerType">0</property>
</system>
0表示使用本地文件方式;1表示使用數據庫方式生成;2表示使用本地時間戳方式;3表示基於ZK與本地配置的分佈式ID生成器;4表示使用zookeeper遞增方式生成
1.3.1 本地文件
此種方式Mycat將sequence配置到文件中,當使用到sequence中的配置後,Mycat會更新文件中的當前值。
#default global sequence
GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=20000
GLOBAL.CURID=10000
# self define sequence
COMPANY.HISIDS=
COMPANY.MINID=1001
COMPANY.MAXID=2000
COMPANY.CURID=1000
ORDER.HISIDS=
ORDER.MINID=1001
ORDER.MAXID=2000
ORDER.CURID=1000
1.3.2 數據庫方式
在數據庫中建立一張表,存放sequence名稱(name),sequence當前值(current_value),步長(increment) 等信息。
CREATE TABLE MYCAT_SEQUENCE
(
name VARCHAR(64) NOT NULL,
current_value BIGINT(20) NOT NULL,
increment INT NOT NULL DEFAULT 1,
PRIMARY KEY (name)
) ENGINE = InnoDB;
1.3.3 本地時間戳
ID爲64位二進制,42(毫秒)+5(機器ID)+5(業務編碼)+12(重複累加)換算成十進制爲18位數的long類型,每毫秒可以併發12位二進制的累加。
在Mycat下配置sequence_time_conf.properties文件
WORKID=0-31 任意整數
DATAACENTERID=0-31 任意整數
每個Mycat配置的WORKID、DATAACENTERID不同,組成唯一標識,總共支持32*32=1024種組合。
1.3.4 分佈式ZK ID生成器
ZK的連接信息統一在myid.properties的zkURL屬性中配置。基於ZK與本地配置的分佈式ID生成器,InstanceID可以通過ZK自動獲取,也可以通過配置文件配置。在sequence_distributed_conf.properties,只要配置INSTANCEID=ZK就表示從ZK上獲取 InstanceID。
ID 最大爲63位二進制,可以承受單機房單機器單線程 1000*(2^6)=640000 的併發。結構如下
- current time millis(微秒時間戳 38 位,可以使用 17 年)
- clusterId(機房或者 ZKid,通過配置文件配置,5 位)
- instanceId(實例 ID,可以通過 ZK 或者配置文件獲取,5 位)
- threadId(線程 ID,9 位)
- increment(自增,6 位)
1.3.5 ZK遞增方式
ZK的連接信息統一在myid.properties的zkURL屬性中配置。需要配置sequence_conf.properties文件
- TABLE.MINID 某線程當前區間內最小值
- TABLE.MAXID 某線程當前區間內最大值
- TABLE.CURID 某線程當前區間內當前值
2. schema.xml配置
schema.xml作爲Mycat中重要的配置文件之一,管理着Mycat的邏輯庫、表、分片節點、主機等信息。
2.1 schema標籤
schema標籤用於定義Mycat實例中的邏輯庫,Mycat可以有多個邏輯庫,每個邏輯庫都有自己相關配置。可以使用schema標籤來劃分這些不同的邏輯庫。
<!-- 邏輯庫 -->
<schema name="lg_edu_order" checkSQLschema="true" sqlMaxLimit="100"
dataNode="dn1"></schema>
屬性名 | 類型 | 說明 |
---|---|---|
dataNode | String | 分片節點 |
sqlMaxLimit | Integer | 查詢返回記錄數限制 |
checkSQLschema | boolean | 是否去表庫名 |
2.2 table標籤
table標籤定義了Mycat中的邏輯表,所有需要拆分的表都需要在這個標籤中定義
<table name="b_order" dataNode="dn1,dn2" rule="b_order_rule" primaryKey="ID"
autoIncrement="true"/>
屬性名 | 類型 | 說明 |
---|---|---|
name | String | 邏輯表名 |
dataNode | String | 分片節點 |
rule | String | 分片規則 |
ruleRequired | boolean | 是否強制綁定分片規則 |
primaryKey | String | 主鍵 |
type | String | 邏輯表類型,全局表、普通表 |
autoIncrement | boolean | 自增長主鍵 |
subTables | String | 分表 |
needAddLimit | boolean | 是否爲查詢SQL自動加limit限制 |
2.3 dataNode標籤
dataNode標籤定義了Mycat中的分片節點,也就是我們通常所說的數據分片。
<!-- 數據節點 -->
<dataNode name="dn1" dataHost="lg_edu_order_1" database="lg_edu_order_1" />
屬性名 | 類型 | 說明 |
---|---|---|
name | String | 數據節點名稱,這個名稱需要是唯一的 |
dataHost | String | 用於定義分片屬於哪個分片主機,屬性值是引用 dataHost標籤上定義的name屬性。 |
database | String | 用於定義該分片節點屬於哪個具體的庫 |
2.4 dataHost標籤
dataHost標籤在Mycat邏輯庫中也是作爲最底層的標籤存在,直接定義了具體的數據庫實例、讀寫分離配置和心跳語句。
<dataHost name="lg_edu_order_1" maxCon="100" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1"
slaveThreshold="100">
</dataHost>
屬性名 | 類型 | 說明 |
---|---|---|
name | String | 節點主機名 |
maxCon | Integer | 最大連接數 |
minCon | Integer | 最小連接數 |
balance | Integer | 讀操作負載均衡類型,0:所有讀操作發送到當前可用的writeHost;1:所有讀操作發送到readHost和stand by writeHost;2:所有讀操作發送到writeHost和readHost;3:所有讀操作發送到writeHost對應的readHost上,但是writeHost不參與讀 |
writeType | Integer | 寫操作負載均衡類型,0:所有寫操作發送到writeHost;1:所有寫操作發送到readHost;2:所有寫操作發送到readHost和writeHost |
dbType | String | 數據庫類型 |
dbDriver | String | 數據庫驅動 |
switchType | String | 主從切換類型,-1:表示不自動切換;1:表示自動切換;2:基於mysql主從同步狀態決定是否切換;3:基於Mysql cluster集羣切換機制 |
2.5 heartbeat標籤
指明心跳檢查的語句
<dataHost>
<heartbeat>select user()</heartbeat>
</dataHost>
2.6 writeHost和readHost標籤
writeHost和readHost標籤都指定後端數據庫的相關配置給Mycat,用於實例化後端連接池。唯一不同的是,writeHost指定寫實例、readHos指定讀實例。在一個dataHost內可以定義多個writeHost和readHost。但是,如果writeHost指定的後端數據庫宕機,那麼這個writeHost綁定的所有readHost都將不可用。另一方面,由於這個writeHost宕機系統會自動的檢測到,並切換到備用的writeHost上去。
<writeHost host="M1" url="192.168.95.133:3306" user="root" password="1234">
</writeHost>
屬性名 | 類型 | 說明 |
---|---|---|
host | String | 主機名 |
url | String | 連接字符串 |
password | String | 密碼 |
user | String | 用戶名 |
weight | String | 權重 |
usingDecrypt | String | 是否對密碼加密,默認0 |
3. rule.xml配置
rule.xml用於定義分片規則
3.1 tableRule標籤
<tableRule name="c_order_rule">
<rule>
<columns>user_id</columns>
<algorithm>partitionByOrderFunc</algorithm>
</rule>
</tableRule>
屬性名 | 類型 | 說明 |
---|---|---|
name | String | 表規則名稱 |
columns | String | 要拆分的列名 |
algorithm | String | 使用function標籤中的name屬性,連接表規則和具體路由算法 |
3.2 function標籤
<function name="partitionByOrderFunc"
class="io.mycat.route.function.PartitionByMod">
<property name="count">2</property>
</function>
屬性名 | 類型 | 說明 |
---|---|---|
name | String | 算法的名稱 |
class | String | 指定路由算法具體的類名字 |
property | String | 具體算法中需要用到的一些屬性 |