什麼是Mycat
mysql二層: server層 存儲層
mycat相當於mysql server層
mysql相當於mycat 的存儲層
mycat中不存儲數據,所有數據存儲在mysql中
mycat是一個數據庫中間層
mycat可以實現對後端數據庫的分庫分表和讀寫分離
垂直拆分
水平拆分
好處: mycat對前端應用隱藏了後端數據庫的存儲邏輯
mycat的基本元素
邏輯庫:
對應用來說相當於mysql中的數據庫
邏輯庫可端多個物理數據庫
邏輯庫並不保存數據
實際保存在後端的數據庫中存儲層中
邏輯表:
比對於後端有 表01 表02 邏輯表可展示成一個表 主表
對應用來說相當於mysql中的數據表
邏輯表可對應後端多個物理數據庫中的表
邏輯表並不保存數據
邏輯表的類別
分表片: 進行水平切分的表,居有相同表結構但是數據存儲在不同數據庫的表, 只有把數據表中的數據彙總起來纔是這個表的完整數據
全局表: 字典表,這些表通常會存儲在後端所有分片的數據庫中
ER關係表: 按ER關係進行分片的表, 實體關係
把子表的記錄與所關連的父表記錄存放在同一個數據分片上,子表依賴於父表來進行存儲,
通過ER關係的策略可以保證相同的一組表是不會跨庫的。
安裝
mycat是基於jdk 1.7開發,需要先安裝jdk包 直接官網下載
# 安裝 jdk
rpm -vih jdk-7u80-linux-x64.rpm
# 安裝 mycat
wget http://dl.mycat.io/1.6.6.1/Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz
tar xf Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz
mv mycat /usr/local
# 創建用戶
useradd mycat
# 授權mycat
chown mycat.mycat /usr/local/mycat -R
# 環境變量配置
[root@c7 conf]# cat /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/default
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$CLASSPATH:$PATH
[root@c7 conf]# cat /etc/profile.d/mycat.sh
export MYCAT_HOME=/usr/local/mycat
export PATH=$MYCAT_HOME/bin:$PATH
# 配置mycat內存,以實際服務器內存大小爲主
vim /usr/local/mycat/conf/wrapper.conf
wrapper.java.additional.5=-XX:MaxDirectMemorySize=500M <-- 配置啓動服務的內存大小 -->
# 啓動服務
mycat start
# 查看日誌
[root@c7 conf]# tail -f /usr/local/mycat/logs/wrapper.log
MyCAT Server startup successfully. see logs in logs/mycat.log # 看到這行說明mycat啓動成功
# 安裝Mysql
下載地址: https://cdn.mysql.com//Downloads/MySQL-5.6/mysql-5.6.42-linux-glibc2.12-x86_64.tar.gz
[root@c7 tmp]# tar xf mysql-5.6.42-linux-glibc2.12-x86_64.tar.gz
[root@c7 tmp]# mv mysql-5.6.42-linux-glibc2.12-x86_64 /usr/local/
[root@c7 tmp]# cd /usr/local/
[root@c7 local]# ln -sv mysql-5.6.42-linux-glibc2.12-x86_64/ mysql
"mysql" -> "mysql-5.6.42-linux-glibc2.12-x86_64/"
[root@c7 local]# groupadd -g 3000 mysql
[root@c7 local]# useradd -g 3000 -u 3001 mysql -s /sbin/nologin
[root@c7 local]# chown mysql.mysql mysql* -R
[root@c7 local]# cd mysql
[root@c7 mysql]# ./scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql
[root@c7 mysql]# cp support-files/mysql.server /etc/init.d/mysqld
[root@c7 mysql]# vim /etc/profile.d/mysql.sh
export PATH=/usr/local/mysql/bin:$PATH
# /etc/my.cnf 數據目錄跟basedir記得修改
[mysqld]
datadir=/usr/local/mysql
socket=/usr/local/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
最後啓動它
配置文件
xml文件 格式爲 <xxx> </xxx> 類似於html標籤
註釋格式爲 <-- 代碼 -->
server.xml
1、system
<system> # 常規的系統參數配置
<property name="serverPort">8066</property> # 連接端口
${key} ${value}
<property name="managerPort">9066</property> # 管理端口
<property name="nonePasswordLogin">0</property> <!-- 0爲需要密碼登陸、1爲不需要密碼登陸 ,默認爲0,設置爲1則需要指定默認賬戶-->
<property name="bindIp">0.0.0.0</property> # 連接的ip地址
<property name="frontWriteQueueSize">4096</property> # 前端寫隊列的大小
<property name="charset">utf8</property> # 這個字符串要跟後端的mysql一樣
<property name="txIoslation">2</property> # 事務級別 2:讀已提交 3: 可重複讀
<property name="processors">8</property> # mycat的進程數量 = CPU的核數
<property name="idleTimeout">1800000</property> # 多久沒連接之後斷開連接單位(ms)
<property name="sqlExecuteTimeout">300</property> # 也是斷開時間 單位爲秒
<property name="userSqlStat">0</property> # mycat數據集的大小
<property name="defaultMaxLimit">100</property> # 限制返回值爲100行
<property name="maxPacketSize">104857600</property> # mysql最大包的大小
<property name="userGlobalTableCheck">0</property> # 用戶表全局檢查
<property name="sequnceHandlerType">2</property> #
</system>
2、user段
<user> #配置mycat的訪問用戶及權限
<user name="root" > # 定義用戶名稱
<property name="password">123456</property> # 密碼
<property name="schemas">TESTDB</property> # root訪問的邏輯庫就是TESTDB
<property name="readOnly">true</property> # 只讀用戶
<!-- <property name="schemas">TESTDB,db1,db2</property> # root訪問的邏輯庫就是TESTDB,db1,db2 -->
</user>
# 完整的示例
<user name="root">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<!-- 表級 DML 權限設置 -->
<!-- <privileges check="false"> # false表示表級DML沒開
<schema name="TESTDB" dml="0110" > # 邏輯庫定義 dml 用戶權限
<table name="tb01" dml="0000"></table> # 表的權限
<table name="tb02" dml="1111"></table>
權限說明: insert,update,select,delete
1: 說明有權限, 0: 表示沒有
</schema>
</privileges> -->
</user>
3、用戶密碼加密
[root@c7 lib] [pwd] /usr/local/mycat/lib
# 如果不使用這個,那麼在配置文件中查看的是明文密碼
[root@c7 lib]# java -cp Mycat-server-1.6.6.1-release.jar io.mycat.util.DecryptUtil 0:root:123456
GO0bnFVWrAuFgr1JMuMZkvfDNyTpoiGU7n/Wlsa151CirHQnANVk3NzE3FErx8v6pAcO0ctX3xFecmSr+976QA==
參數說明:
0:root:123456
前端應用:用戶名:密碼
將原先的
<property name="password">123456</property>
修改爲:
<property name="usingDecrypt">1</property> # 表示啓用加密的密碼
<property name="password">GO0bnFVWrAuFgr1JMuMZkvfDNyTpoiGU7n/Wlsa151CirHQnANVk3NzE3FErx8v6pAcO0ctX3xFecmSr+976QA==</property>
最後貼出完整的server.xml文件,然後啓動並連接
[root@c7 conf]# cat 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/">
<system>
<property name="serverPort">8066</property>
<property name="managerPort">9066</property>
<property name="nonePasswordLogin">0</property>
<property name="bindIp">0.0.0.0</property>
<property name="frontWriteQueueSize">4096</property>
<property name="charset">utf8</property>
<property name="txIoslation">2</property>
<property name="processors">8</property>
<property name="idleTimeout">1800000</property>
<property name="sqlExecuteTimeout">300</property>
<property name="userSqlStat">0</property>
<property name="defaultMaxLimit">100</property>
<property name="maxPacketSize">104857600</property>
<property name="userGlobalTableCheck">0</property>
<property name="sequnceHandlerType">2</property>
</system>
<user name="root" defaultAccount="true">
<property name="usingDecrypt">1</property>
<property name="password">GO0bnFVWrAuFgr1JMuMZkvfDNyTpoiGU7n/Wlsa151CirHQnANVk3NzE3FErx8v6pAcO0ctX3xFecmSr+976QA==</property>
<property name="schemas">TESTDB</property>
<!-- 表級 DML 權限設置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>
</mycat:server>
密碼: 爲定義的123456
log4j2.xml
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] (%l) - %m%n</Pattern> # 日誌時間格式 SSS表示毫秒
</PatternLayout>
%d: 日誌輸出的時間格式 {}
%p: 日誌級別 %5p: 至少有五個字符
%t: 產生日誌線程
%m: 輸出代碼中提定的消息
%n: windows平臺 "/r/n", linux平臺"/n"
<asyncRoot level="info" includeLocation="true"> # 日誌級別 從低到高 首字母大寫
ALL < Trace < Debug < info < warn < error < fatal < OFF
輸出的日誌, 我這裏還沒有配置mysql連接,所以報錯
2018-12-03 10:04:05.730 INFO [$_NIOConnector] (io.mycat.net.AbstractConnection.close(AbstractConnection.java:520)) - close connection,reason:java.net.ConnectException: 拒絕連接 ,MySQLConnection [id=0, lastTime=1543802645728, user=root, schema=db1, old shema=db1, borrowed=false, fromSlaveDB=false, threadId=0, charset=utf8, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=localhost, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
rule.xml
水平算法規則
文件用途 配置水平分片的分片規則 配置分片規則所對應的分片函數
<tableRule name="rule1"> # name必須唯一, 命名要有象徵性的意義
<rule>
<columns>id</columns> # 所使用的分片列, 必須是在表中所存在的列
<algorithm>func1</algorithm> # 指定表的分片算法,取<function>的name屬性
</rule>
</tableRule>
function 配置表的分片算法
<function name="murmur"> # name 屬性定義分片算法的名字
class="io.mycat.route.function.PartitionByMurmurHash"> # java類的路徑名字
<property name="seed">0</property> <!-- 默認是0 -->
<property name="count">2</property> <!-- 要分片的數據庫節點數量,必須指定,否則沒法分片 -->
<property name="virtualBucketTimes">160</property><!-- 一個實際的數據庫節點被映射爲這麼多虛擬節點,默認是160倍,也就是虛擬節點數是物理節點數的160倍 -->
<!-- <property name="weightMapFile">weightMapFile</property> 節點的權重,沒有指定權重的節點默認是1。以properties文件的格式填寫,以從0開始到count-1的整數值也就是節點索引爲key,以節點權重值爲值。所有權重值必須是正整數,否則以1代替 -->
<!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
用於測試時觀察各物理節點與虛擬節點的分佈情況,如果指定了這個屬性,會把虛擬節點的murmur hash值與物理節點的映射按行輸出到這個文件,沒有默認值,如果不指定,就不會輸出任何東西 -->
</function>
**常用的分片算法 **
1、簡單取模 - PartitionByMod
分片列簡單取模, 以確定分片數據是存儲在每一個分片上
可以用於分片列爲[整數類型]的表
分片列 mod 分片基數 <property name="count"> 分片的數量就是分片的基數
類全名: io.mycat.route.function.PartitionByMod
2、哈希取模 - PartitionByHashMod
分片列先進行哈希, 然後在進行取模
可以用於多種數據類型,如字符串,日期等
hash(分片列) mod分片基數
類全名: io.mycat.route.function.PartitionByHashMod
3、枚舉分片 - PartitionByFileMod
可以根據可能的枚舉值指定數據存儲的位置
$MYCAT/conf目錄下增加MapFile配置枚舉值同節點的對應關係 如10000=0 第一個節點爲0
類全名: io.mycat.route.function.PartitionByFileMod
<function name="hash-int" # 節點從0開始
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property> # 文件放置到mycat/conf/目錄下
10000=0 如10000就放到第1個節點, 10010就放到第2個節點, 其它就放到1號節點
10010=1
DEFAULT_NODE=0
<property name="type">0</property> # 0: inter ×××, 其它爲非整型
<property name="defalutNode">0</property> # 是否啓用默認節點
</function>
4、字符串範圍取模分片 - PartitionByPrefixPattern
可以根據指定字符串的前N個字符確定存儲位置
$MYCAT/conf 增加MapFile配置取模範圍同節點的對應關係 mapFile定義的文件 上線之後就不能改變
類全名 io.mycat.route.function.PartitionByPrefixPattern
<function name="這裏定義名稱" # 節點從0開始
class="io.mycat.route.function.PartitionByPrefixPattern">
<property name="patternValue">128</property> # 字符串hash值取模
<property name="prefixLength">2</property> # 字符串取出的頭兩個字符串的值如XIONG 那就是取XI(ascii值)之和/patternValue 取模
<property name="mapFile">prefix-partition-pattern.txt</property>
如 0-63=0
64-127=1
</function>
最常見的使用最多的還是簡單取模算法