傳統關系型數據庫的分布式開發通常需要自己做,不僅耗時耗力而且效果不是很理想,當想快速搭建時,最初想到的是看有沒有第三方,網上牛人還是很多的,做得比較好的其中之一Mycat,它是開源的分布式數據庫系統,解決數據庫的負載均衡,主備復制,讀寫分離,簡單來說就是你只管直接與mycat通訊,至於分離什么的交給它里面自己做,其它啥都不用操心。
至於什么是MyCat有什么優勢,可以看看官網介紹 Mycat 數據庫分庫分表中間件 。
上圖是MyCat架構圖。
MyCat可以與HAProxy使用實現高可用數據庫集群,更深入的內容自己去查,本章只詳講從0開始使用MyCat 基礎篇,至少能先跑起來。
一、下載
本次運行環境為windows,Linux下更好吧,然后數據庫用mysql,需要java環境,下載jdk8
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吧,否則插入的中文顯示為亂碼,具體解決方法網上查一查,去試一試。
下載MyCat,http://dl.mycat.io/ 選擇最新的版本下載。(下圖可以看到還有其它前面需要的資源都可以從這里下載)
二、配置
下載解壓后就要先配置MyCat了,(這里不是exe文件,沒有安裝,配置好后直接運行startup_nowrap.bat)
打開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
三、連接MySQL
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中添加的一行記錄會隨機插入 TESTDB1、TESTDB2、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 查看操作,然后去TESTDB1、TESTDB2、TESTDB3中查詢hotnews表
MyCat中TESTDB是中間件邏輯數據庫,MySQL中的testdb、testdb2、testdb3是真實的數據庫。
在mycat中添加數據時若提示testdb2.hotnews不存在,則要手動在testdb2中添加相同表結構。
添加完后,可以看到hotnews記錄在三個testdb、testdb2、testdb3中是均衡隨機插入的。
而goods在testdb、testdb2中是一樣的。
至此可以配置出MyCat了,敬請期待下篇 net下如何使用。