傳統關係型數據庫的分佈式開發一般須要本身作,不只耗時耗力並且效果不是很理想,當想快速搭建時,最初想到的是看有沒有第三方,網上牛人仍是不少的,作得比較好的其中之一Mycat,它是開源的分佈式數據庫系統,解決數據庫的負載均衡,主備複製,讀寫分離,簡單來講就是你只管直接與mycat通信,至於分離什麼的交給它裏面本身作,其它啥都不用操心。前端
至於什麼是MyCat有什麼優點,能夠看看官網介紹 Mycat 數據庫分庫分表中間件 。java
上圖是MyCat架構圖。node
MyCat能夠與HAProxy使用實現高可用數據庫集羣,更深刻的內容本身去查,本章只詳講從0開始使用MyCat 基礎篇,至少能先跑起來。mysql
本次運行環境爲windows,Linux下更好吧,而後數據庫用mysql,須要java環境,下載jdk8sql
jdk安裝配置
1. 首先去oracle官網下載並安裝jdk8,添加環境變量,JAVA_HOME設置爲D:\Java\jdk1.8
2. CLASSPATH設置爲.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
3. path系統變量追加%JAVA_HOME%\bin;數據庫
安裝Mysql,須要注意的是數據庫,表,字段的編碼都採用utf8吧,不然插入的中文顯示爲亂碼,具體解決方法網上查一查,去試一試。express
下載MyCat,http://dl.mycat.io/ 選擇最新的版本下載。(下圖能夠看到還有其它前面須要的資源均可以從這裏下載)apache
下載解壓後就要先配置MyCat了,(這裏不是exe文件,沒有安裝,配置好後直接運行startup_nowrap.bat)windows
打開mycat\conf裏面的startup_nowrap.bat 爲了下降資源佔用,mycat的jvm設置在startup_nowrap.bat 能夠清楚看到以下配置:
「%JAVA_CMD%」 -server -Xms1G -Xmx2G -XX:MaxPermSize=64M -XX:+AggressiveOpts -XX:MaxDirectMemorySize=1G -DMYCAT_HOME=%MYCAT_HOME% -cp 「..\conf;..\lib*」 io.mycat.MycatStartup
這裏將-Xms1G改爲-Xms512M,-Xmx2G改爲-Xmx1024M,保存後從新啓動便可。後端
添加Windows環境變量,MYCAT_HOME設置爲安裝目錄D:\MycatServer1.5
修改wrapper.conf文件裏的改爲wrapper.java.command=D:\jdk1.8\bin\java.exe
Mycat綁定MySQL 啓動的配置
conf 配置文件存放配置文件:
--server.xml:是Mycat服務器參數調整和用戶受權的配置文件。 --schema.xml:是邏輯庫定義和表以及分片定義的配置文件。 --rule.xml: 是分片規則的配置文件,分片規則的具體一些參數信息單獨存放爲文件,也在這個目錄下,配置文件修改須要重啓MyCAT。 --log4j.xml: 日誌存放在logs/log中,天天一個文件,日誌的配置是在conf/log4j.xml中,根據本身的須要能夠調整輸出級別爲debug debug級別下,會輸出更多的信息,方便排查問題。 --autopartition-long.txt,partition-hash-int.txt,sequence_conf.properties, sequence_db_conf.properties 分片相關的id分片規則配置文件 --lib MyCAT自身的jar包或依賴的jar包的存放目錄。 --logs MyCAT日誌的存放目錄。日誌存放在logs/log中,天天一個文件
具體什麼意思後面慢慢看。
先解決主配置,server.xml配置文件配置訪問用戶及權限, 修改高亮處信息,其中mycat、user爲訪問mycat的用戶,TESTDB爲mycat虛擬的數據庫,供上層應用訪問。
<user name="mycat"> <property name="password">123456</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">123456</property> <property name="schemas">TESTDB</property> <property name="readOnly">true</property> </user>
mycat的數據庫配置是在schema.xml中配置,這部分不太好理解,精簡了一下,主要分schema、dataNode、dataHost三個主要配置。
<scheme>節點定義了mycat的虛擬數據庫爲TESTDB,下面借用園友的說明:
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://org.opencloudb/" > <!--在這一行參數裏面,schema name定義了能夠在MyCAT前端顯示的邏輯數據庫的名字,checkSQLschema這個參數爲False的時候,代表MyCAT會自動忽略掉表名前的數據庫名,好比說mydatabase1.test1,會被當作test1;sqlMaxLimit指定了SQL語句返回的行數限制--> <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"> <!-- 主鍵範圍規則 --> <!-- 這一行表明在MyCAT前端會顯示哪些表名,相似幾行都表明同樣的意思,這裏強調的是表,而MyCAT並不會在配置文件裏面定義表結構,若是在前端使用show create table ,MyCAT會顯示正常的表結構信息,觀察Debug日誌,能夠看到,MyCAT把命令分發給了dn1表明的數據庫,而後把dn1的查詢結果返回給了前端 能夠判斷,相似的數據庫級別的一些查詢指令,有多是單獨分發給某個節點,而後再把某個節點的信息返回給前端。 dataNode的意義很簡單,這個邏輯表的數據存儲在後端的哪幾個數據庫裏面rule表明的是這個邏輯表students的具體切分策略,目前MyCAT只支持按照某一個特殊列,遵循一些特殊的規則來切分,如取模,枚舉等,具體的留給以後細說 --> <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> <table name="company" primaryKey="ID" dataNode="dn3,dn2,dn1" rule="mod-long"/> <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" /> <!--求模分片隨機規則 --> <table name="hotnews" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="mod-long" /> <table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" /> <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"> <!-- childtable我在測試中並無實際用起來不過在MyCAT的設計文檔裏面有提到,childtable是一種依賴於父表的結構, 這意味着,childtable的joinkey會按照父表的parentKey的策略一塊兒切分,當父表與子表進行鏈接, 且鏈接條件是childtable.joinKey=parenttable.parentKey時,不會進行跨庫的鏈接. --> <childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id"> <childTable name="order_items" joinKey="order_id" parentKey="id" /> </childTable> <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" /> </table> <!-- 全局表是自動克隆到全部定義的數據節點,這樣能夠與拆分節點的任何錶鏈接查詢,是在同一個數據節點--> <table name="news_table" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /> </schema> <dataNode name="dn1" dataHost="localhost1" database="TESTDB1" /> <dataNode name="dn2" dataHost="localhost1" database="TESTDB2" /> <dataNode name="dn3" dataHost="localhost1" database="TESTDB3" /> <!-- dataHost配置的是實際的後端數據庫集羣,大部分參數簡單易懂,這裏就不一個個介紹了,只介紹比較重要的兩個參數,writeType和balance. --> <!-- writeType和balance是用來控制後端集羣的讀寫分離的關鍵參數,這裏我用了雙主雙從的集羣配置 這裏的測試過程比較麻煩,因此直接貼結論: 1.balance=0時,讀操做都在localhost上(localhost失敗時,後端直接失敗) 2.balance=1時,讀操做會隨機分散在localhost1和兩個readhost上面(localhost失敗時,寫操做會在localhost1,若是localhost1再失敗,則沒法進行寫操做) 3.balance=2時,寫操做會在localhost上,讀操做會隨機分散在localhost1,localhost1和兩個readhost上面(同上) 4.writeType=0時,寫操做會在localhost上,若是localhost失敗,會自動切換到localhost1,localhost恢復之後並不會切換回localhost進行寫操做 5.writeType=1時,寫操做會隨機分佈在localhost和localhost1上,單點失敗並不會影響集羣的寫操做,可是後端的從庫會沒法從掛掉的主庫獲取更新,會在讀數據的時候出現數據不一致 舉例:localhost失敗了,寫操做會在localhost1上面進行,localhost1的主從正常運行,可是localhost的從庫沒法從localhost獲取更新,localhost的從庫於其餘庫出現數據不一致 --> <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <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="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />--> </writeHost> </dataHost> </mycat:schema>
以上配置注意高亮部分,配置的是每一個dn對應哪一個實體服務器裏面哪一個實體庫(此處只有本機,因此都綁定到本機localhost,再添加3個不一樣的數據庫TESTDB1\TESTDB2\TESTDB3,手動都添加要測試的表,如有多餘的服務器能夠將ip替換掉測試),詳細的內容參考文中的註釋。
通過實驗 goods表:在mycat的TESTDB的虛擬表goods中添加一行記錄會在 TESTDB1和TESTDB2中的表goods同步添加一行記錄。
hotnews表:在mycat的TESTDB的虛擬表hotnews中添加的一行記錄會隨機插入 TESTDB一、TESTDB二、TESTDB3的其中一個庫中的hotnews表。
其它表的測試大家本身試試。
這就是分片,靠的是分片規則,下面就來看rule。
(每一個數據庫中相同的表要手工提早生成表結構,不然會提示找不到此表,操做mycat時它並不能自動同步實體數據庫生成,可能有方法,如今還沒深刻了解)
rule.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:rule SYSTEM "rule.dtd"> <mycat:rule xmlns:mycat="http://org.opencloudb/"> <tableRule name="rule1"> <rule> <columns>id</columns> <algorithm>func1</algorithm> </rule> </tableRule> <tableRule name="rule2"> <rule> <columns>user_id</columns> <algorithm>func1</algorithm> </rule> </tableRule> <tableRule name="sharding-by-intfile"> <rule> <columns>sharding_id</columns> <algorithm>hash-int</algorithm> </rule> </tableRule> <tableRule name="auto-sharding-long"> <rule> <columns>id</columns> <algorithm>rang-long</algorithm> </rule> </tableRule> <tableRule name="mod-long"> <rule> <columns>id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <tableRule name="sharding-by-murmur"> <rule> <columns>id</columns> <algorithm>murmur</algorithm> </rule> </tableRule> <tableRule name="sharding-by-month"> <rule> <columns>create_date</columns> <algorithm>partbymonth</algorithm> </rule> </tableRule> <tableRule name="latest-month-calldate"> <rule> <columns>calldate</columns> <algorithm>latestMonth</algorithm> </rule> </tableRule> <tableRule name="auto-sharding-rang-mod"> <rule> <columns>id</columns> <algorithm>rang-mod</algorithm> </rule> </tableRule> <tableRule name="jch"> <rule> <columns>id</columns> <algorithm>jump-consistent-hash</algorithm> </rule> </tableRule> <function name="murmur" class="org.opencloudb.route.function.PartitionByMurmurHash"> <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> <function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> </function> <function name="rang-long" class="org.opencloudb.route.function.AutoPartitionByLong"> <property name="mapFile">autopartition-long.txt</property> </function> <function name="mod-long" class="org.opencloudb.route.function.PartitionByMod"> <!-- how many data nodes --> <property name="count">3</property> </function> <function name="func1" class="org.opencloudb.route.function.PartitionByLong"> <property name="partitionCount">8</property> <property name="partitionLength">128</property> </function> <function name="latestMonth" class="org.opencloudb.route.function.LatestMonthPartion"> <property name="splitOneDay">24</property> </function> <function name="partbymonth" class="org.opencloudb.route.function.PartitionByMonth"> <property name="dateFormat">yyyy-MM-dd</property> <property name="sBeginDate">2015-01-01</property> </function> <function name="rang-mod" class="org.opencloudb.route.function.PartitionByRangeMod"> <property name="mapFile">partition-range-mod.txt</property> </function> <function name="jump-consistent-hash" class="org.opencloudb.route.function.PartitionByJumpConsistentHash"> <property name="totalBuckets">3</property> </function> </mycat:rule>
用管理員權限運行startup_nowrap.bat啓動MyCat。
若出現上面的問題,檢查java的環境是否正確和mycat的環境配置。
啓動成功後會出現:
#若是啓動失敗,請修改D:\mycat\bin\startup_nowrap.bat文件中的如下參數。默認佔用內存爲2G
D:\dev-bin\mycat\bin>"C:\Program Files (x86)\Java\jdk1.7.0_13/bin/java" -server -Xms512m -Xmx512m -XX:MaxPermSize=64M -XX:+AggressiveOpts -XX:MaxDirectMemorySize=768m -DMYCAT_HOME=D:\
p "..\conf;..\lib\*" io.mycat.MycatStartup
而後dos中會不停的出現心跳檢測,有錯誤信息可去mycat\logs中查看日誌。
注意:如日誌中出現192.168.xxx not connected 等信息,請容許對應的mysql遠程訪問,且先提早獨自檢查mysql都能正確訪問。
使用navicat鏈接mycat,操做方式和鏈接物理mysql庫一致,用戶mycat,密碼123456,端口8066
鏈接成功後,將看到TESTDB數據庫和hotnews等數據表
在hotnews表中添加一些數據,保存
執行select * from hotnews 查看操做,而後去TESTDB一、TESTDB二、TESTDB3中查詢hotnews表
MyCat中TESTDB是中間件邏輯數據庫,MySQL中的testdb、testdb二、testdb3是真實的數據庫。
在mycat中添加數據時若提示testdb2.hotnews不存在,則要手動在testdb2中添加相同表結構。
添加完後,能夠看到hotnews記錄在三個testdb、testdb二、testdb3中是均衡隨機插入的。
而goods在testdb、testdb2中是同樣的。