MyCAT 能夠視爲「MySQL」集羣的企業級數據庫,用來替代昂貴的Oracle集羣,其背後是阿里曾經開源的知名產品Cobar。MyCAT的目標是:低成本的將現有的單機數據庫和應用平滑遷移到「雲」端,解決數據存儲和業務規模迅速增加狀況下的數據瓶頸問題。java
(2) 修改配置my.cnf新增如下語句, 通常會放在/etc/my.cnf 或 /etc/mysql/my.cnf,設置爲Mysql表名大小寫不敏感,不然可能會發生表找不到的問題。
Cobar自誕生之日起, 就受到廣大程序員的追捧,可是自2013年後,幾乎沒有後續更新。在此狀況下,MyCAT應運而生,它基於阿里開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能,以及衆多成熟的使用案例使得MyCAT一開始就擁有一個很好的起點,站在巨人的肩膀上,MyCAT能看到更遠。
---------------------------------------------------------MyCAT的下載方式--------------------------------------------------------------------
MyCAT的SVN地址爲:http://code.taobao.org/svn/openclouddb/
---------------------------------------------------------MyCAT的重要特性--------------------------------------------------------------------
支持 SQL 92標準;
支持MySQL集羣,能夠做爲Proxy使用;
支持JDBC鏈接ORACLE、DB二、SQL Server,將其模擬爲MySQL Server使用;
支持galera for mysql集羣,percona-cluster或者mariadb cluster,提供高可用性數據分片集羣;
自動故障切換,高可用性;
支持讀寫分離,支持MySQL雙主多從,以及一主多從的模式;
支持全局表,數據自動分片到多個節點,用於高效表關聯查詢;
支持獨有的基於E-R 關係的分片策略,實現了高效的表關聯查詢;
多平臺支持,部署和實施簡單。
------------------------------------------------------------MyCAT的體系結構----------------------------------------------------------------
![](http://static.javashuo.com/static/loading.gif)
整體上分紅三個部分,最前端的是鏈接器,線程管理使用了資源池,而且默認採用了AIO的方式(這些基本信息能夠再啓動日誌裏面看到);
中間層在圖中已經描述的很清楚了,SQL解析器+SQL路由,SQL Executor須要具體看源碼才能瞭解,由於經過這段時間對MyCAT的測試,沒有感受到SQL Executor的存在,更多的感受是一個SQL process的東西,DataNode和心跳檢測算是中間層實現的兩個組件,一個是和MySQL的庫(注意,不是實例)相關,一個是常見的監測機制的功能模塊;
最下層的存儲就是是MySQL的集羣了~怎麼玩MySQL的集羣,由咱們本身決定╰(?? ▽ ??)╯。
--------------------------------------------------------------怎麼使用MyCAT----------------------------------------------------------
MyCAT目前經過配置文件的方式來定義邏輯庫和相關配置,主要是包括三個文件:
MYCAT_HOME/conf/schema.xml中定義邏輯庫,表、分片節點等內容;
MYCAT_HOME/conf/rule.xml中定義分片規則;
MYCAT_HOME/conf/server.xml中定義用戶以及系統相關變量,如端口等。
不着急,這一篇簡單介紹這幾個配置文件的做用和一些參數的意義。
一個一個來,先看schema.xml,這是從網上摘抄的一個示例模板
- <?xml version="1.0"?>
- <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
- <mycat:schema xmlns:mycat="http://org.opencloudb/">
- <schema name="weixin" checkSQLschema="false" sqlMaxLimit="100" dataNode="weixin" >
-
-
- <schema name="yixin" checkSQLschema="false" sqlMaxLimit="100" dataNode="yixin" />
-
-
- <dataNode name="dn1" dataHost="localhost0" database="weixin" />
- <dataNode name="dn2" dataHost="localhost0" database="yixin" />
- <dataHost name="localhost0" maxCon="450" minCon="10" balance="1"
- writeType="0" dbType="mysql" dbDriver="native">
- <heartbeat>select user()</heartbeat>
- <!-- can have multi write hosts -->
- <writeHost host="hostM1" url="localhost:3306" user="root" password="123456" />
- <readHost host="hostS1" url="localhost:3307" user="test" password="123456" />
- </dataHost>
- </mycat:schema>
首先是schema name = "weixin",這一項配置之後的效果就是,當MySQL客戶端鏈接MyCAT時,經過Show DATABASE命令,能看到的數據庫的,名字,
好比在這個配置文件裏面,就配置了兩個數據庫,weixin和yixin,這兩個庫各自包含一張user表。
注意:MyCAT對外端顯示出來的數據庫,和數據庫裏面的表,所有在schema裏面配置,沒有寫在這個裏面的表或者庫,即便後端的MySQL裏面存在,也沒法經過MyCAT去訪問,不過MyCAT不會去定義具體表的結構。
而後是datanode,這個屬性指定了schema的表,具體存放在哪一個數據庫,好比這個配置裏面,指定了dn1的數據節點位於localhost0,這個數據庫實例的名爲weixin的數據庫,dn2同理。
datahost列出了實際的後端MySQL集羣的具體信息,writehost是負責寫入數據的MySQL實例,writehost是負責讀的MySQL實例,若是兩個實例的具體信息寫成同樣,那就意味着後端使用單實例,若是配置成不一樣的實例,那麼就在兩個實例之間配置主從同步,而後經過MyCAT實現讀寫分離
對數據庫進行垂直切分,主要由schema.xml來完成,這個之後再詳細介紹。
rule.xml如示例
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE mycat:rule SYSTEM "rule.dtd">
- <mycat:rule xmlns:mycat="http://org.opencloudb/">
- <tableRule name="rule">
- <rule>
- <columns>user_id</columns>
- <algorithm>func1</algorithm>
- </rule>
- </tableRule>
- <function name="func1" class="org.opencloudb.route.function.PartitionByLong">
- <property name="partitionCount">2</property>
- <property name="partitionLength">512</property>
- </function>
- </mycat:rule>
rule.xml裏面的配置主要用於對錶的水平切分,MyCAt自己提供了不少種水平切分的策略,這個示例顯示的是取模分片,總共分紅四片,user_id對1024取模,而後分紅兩片,每一片512個。
其餘的切分策略之後再詳細介紹
server.xml如示例
- <!DOCTYPE mycat:server SYSTEM "server.dtd">
- <mycat:server xmlns:mycat="http://org.opencloudb/">
- <system>
- <property name="sequnceHandlerType">0</property>
- </system>
- <user name="test">
- <property name="password">test</property>
- <property name="schemas">weixin,yixin</property>
- </user>
- </mycat:server>
server.xml裏面配置MyCAT的邏輯庫參數,如示例,配置的就是邏輯庫weixin和yixin的登陸用戶名和密碼
這個XML裏面其實還有一些有關於MyCAT性能調整的參數,不過略去了,東西太多,之後再詳細介紹
----------------------------------------------------------------------華麗的分割線-------------------------------------------------------------
簡單的MyCAT搭建大體上就包括這些內容,如今講講使用一段時間之後,對MyCAT的一些總結;
1.MyCAT的性能表現仍是不錯的,這幾天一直對MyCAT的各方面進行測試,發現MyCAT做爲一個代理,雖然是在JAVA虛擬機上面運行,可是面對接近9K的QPS的峯值的時候,自己並無出現無響應或者丟失鏈接的問題;
2.MyCAT對前端顯示的全部的庫,表,所有由schema來配置,可是自己不定義表結構,這使得後端的表結構若是出現不一致,MyCAT前端是察覺不到的,不太方便吧;
3.第二點的不方便,也反映了一點,沒有配置到schema的表,徹底沒法經過MyCAT去操做,這也算是安全性良好的一個表現吧;
4.以前說SQL Executor沒感受到,也是由於在一些測試中,發現MyCAT更像一個提供轉發和結果合併功能的代理,只是對SQL和結果進行了process,不過這個須要去看源代碼才知曉細節了。
此次只打算寫這麼多,關於MyCAT的一些細節介紹,留給下一章~
在第一部分,有簡單的介紹MyCAT的搭建和配置文件的基本狀況,這一篇詳細介紹schema的一些具體參數,以及實際做用
首先貼上本身測試用的schema文件,雙引號以前的反斜槓不會消除,姑且當成不存在吧...
- <?xml version=\"1.0\"?>
- <!DOCTYPE mycat:schema SYSTEM \"schema.dtd\">
- <mycat:schema xmlns:mycat=\"http://org.opencloudb/\">
- <schema name=\"mycat\" checkSQLschema=\"false\" sqlMaxLimit=\"100\">
- <!-- auto sharding by id (long) -->
- <table name=\"students\" dataNode=\"dn1,dn2,dn3,dn4\" rule=\"rule1\" />
- <table name=\"log_test\" dataNode=\"dn1,dn2,dn3,dn4\" rule=\"rule2\" />
- <!-- global table is auto cloned to all defined data nodes ,so can join
- with any table whose sharding node is in the same data node -->
- <!--<table name=\"company\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2,dn3\" />
- <table name=\"goods\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2\" />
- -->
- <table name=\"item_test\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2,dn3,dn4\" />
- <!-- random sharding using mod sharind rule -->
- <!-- <table name=\"hotnews\" primaryKey=\"ID\" dataNode=\"dn1,dn2,dn3\"
- rule=\"mod-long\" /> -->
- <!--
- <table name=\"worker\" primaryKey=\"ID\" dataNode=\"jdbc_dn1,jdbc_dn2,jdbc_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 name=\"orders\" primaryKey=\"ID\" joinKey=\"customer_id\"
- parentKey=\"id\">
- <childTable name=\"order_items\" joinKey=\"order_id\"
- parentKey=\"id\" />
- <ildTable>
- <childTable name=\"customer_addr\" primaryKey=\"ID\" joinKey=\"customer_id\"
- parentKey=\"id\" /> -->
- </schema>
- <!-- <dataNode name=\"dn\" dataHost=\"localhost\" database=\"test\" /> -->
- <dataNode name=\"dn1\" dataHost=\"localhost\" database=\"test1\" />
- <dataNode name=\"dn2\" dataHost=\"localhost\" database=\"test2\" />
- <dataNode name=\"dn3\" dataHost=\"localhost\" database=\"test3\" />
- <dataNode name=\"dn4\" dataHost=\"localhost\" database=\"test4\" />
- <!--
- <dataNode name=\"jdbc_dn1\" dataHost=\"jdbchost\" database=\"db1\" />
- <dataNode name=\"jdbc_dn2\" dataHost=\"jdbchost\" database=\"db2\" />
- <dataNode name=\"jdbc_dn3\" dataHost=\"jdbchost\" database=\"db3\" />
- -->
- <dataHost name=\"localhost\" maxCon=\"100\" minCon=\"10\" balance=\"1\"
- writeType=\"1\" dbType=\"mysql\" dbDriver=\"native\">
- <heartbeat>select user()<beat>
- <!-- can have multi write hosts -->
- <writeHost host=\"localhost\" url=\"localhost:3306\" user=\"root\" password=\"wangwenan\">
- <!-- can have multi read hosts -->
- <readHost host=\"hostS1\" url=\"localhost:3307\" user=\"root\" password=\"wangwenan\"/>
- </writeHost>
- <writeHost host=\"localhost1\" url=\"localhost:3308\" user=\"root\" password=\"wangwenan\">
- <!-- can have multi read hosts -->
- <readHost host=\"hostS11\" url=\"localhost:3309\" user=\"root\" password=\"wangwenan\"/>
- </writeHost>
- </dataHost>
- <!-- <writeHost host=\"hostM2\" url=\"localhost:3316\" user=\"root\" password=\"123456\"/> -->
- <!--
- <dataHost name=\"jdbchost\" maxCon=\"1000\" minCon=\"1\" balance=\"0\" writeType=\"0\" dbType=\"mongodb\" dbDriver=\"jdbc\">
- <heartbeat>select user()<beat>
- <writeHost host=\"hostM\" url=\"mongodb://192.168.0.99/test\" user=\"admin\" password=\"123456\" ></writeHost>
- </dataHost>
- -->
- <!--
- <dataHost name=\"jdbchost\" maxCon=\"1000\" minCon=\"10\" balance=\"0\"
- dbType=\"mysql\" dbDriver=\"jdbc\">
- <heartbeat>select user()<beat>
- <writeHost host=\"hostM1\" url=\"jdbc:mysql://localhost:3306\"
- user=\"root\" password=\"123456\">
- </writeHost>
- </dataHost>
- -->
- </mycat:schema>
第一行參數<schema name="mycat" checkSQLschema="false" sqlMaxLimit="100"/>
在這一行參數裏面,schema name定義了能夠在MyCAT前端顯示的邏輯數據庫的名字,
checkSQLschema這個參數爲False的時候,代表MyCAT會自動忽略掉表名前的數據庫名,好比說mydatabase1.test1,會被當作test1;
sqlMaxLimit指定了SQL語句返回的行數限制;
如截圖,這個limit會讓MyCAT在分發SQL語句的時候,自動加上一個limit,限制從分庫得到的結果的行數,另外,截圖右上角能夠看到,MyCAT自己也是有緩存的;
那麼,若是咱們執行的語句要返回較多的數據行,在不修改這個limit的狀況下,MyCAT會怎麼作?
能夠從截圖看到,MyCAT徹底就沒搭理前端的實際需求,
老老實實返回100條數據
,因此若是實際應用裏面須要返回大量數據,可能就得手動改邏輯了
MyCAT的1.4版本里面,用戶的Limit參數會覆蓋掉默認的MyCAT設置
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
<table name="students" dataNode="dn1,dn2,dn3,dn4" rule="rule1" />
這一行表明在MyCAT前端會顯示哪些表名,相似幾行都表明同樣的意思,這裏強調的是表,而MyCAT並不會在配置文件裏面定義表結構
若是在前端使用show create table ,MyCAT會顯示正常的表結構信息,觀察Debug日誌,
能夠看到,MyCAT把命令分發給了dn1表明的數據庫,而後把dn1的查詢結果返回給了前端
能夠判斷,相似的數據庫級別的一些查詢指令,有多是單獨分發給某個節點,而後再把某個節點的信息返回給前端;
dataNode的意義很簡單,這個邏輯表的數據存儲在後端的哪幾個數據庫裏面
rule表明的是這個邏輯表students的具體切分策略,目前MyCAT只支持按照某一個特殊列,遵循一些特殊的規則來切分,如取模,枚舉等,具體的留給以後細說
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
<table name="item_test" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3,dn4" />
這一行表明的是全局表,這意味着,item_test這張表會在四個dataNode裏面都保存有完整的數據副本,那麼查詢的時候還會分發到全部的數據庫麼?
結果如截圖,MyCAT依然是規規矩矩的返回了100條數據(╮(╯_╰)╭),而針對全局表的查詢,只會分發到某一個節點上
配置的primaryKey沒發現做用在哪裏,姑且忽略吧,之後發現了再補上
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
childtable我在測試中並無實際用起來不過在MyCAT的設計文檔裏面有提到,childtable是一種依賴於父表的結構,
這意味着,childtable的joinkey會按照父表的parentKey的策略一塊兒切分,當父表與子表進行鏈接,且鏈接條件是childtable.joinKey=parenttable.parentKey時,不會進行跨庫的鏈接.
PS:具體測試之後再補
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
dataNode的參數在以前的篇章介紹過,這裏直接跳過~
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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的從庫於其餘庫出現數據不一致
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
實際上,MyCAT自己的讀寫分離是基於後端集羣的同步來實現的,而MyCAT自己則提供語句的分發功能,固然,那個sqlLimit的限制也使得MyCAT會對前端應用層的邏輯形成一些影響
由schema到table的配置,則顯示出MyCAT自己的邏輯結構裏面,就包含了分庫分表的這種特性(能夠指定不一樣的表存在於不一樣的數據庫中,而沒必要分到所有數據庫)
下一章將會介紹server和rule的一些細節
首先寫在最前面,MyCAT1.4的alpha版本已經發布了,這裏面修復了很多的bug,也完善了一細節,以前兩篇博客已經作了一些修改
---------------------------------------------------------------------------------這纔是本體~----------------------------------------------------------------------------------
以前已經介紹過了schema的做用了,這一篇會把rule和server一塊兒介紹~
首先是rule,在這個文件裏面會詳細的制定多種分片的規則,此次只抽出一些使用率比較高的方法,先上配置文件的內容
能夠簡單看一下,在截圖的上半部分描述的是rule的定義,在下半部分,是rule對應的實際切分規則,這裏總工介紹下面四種切分方式~murmur已坑~
-------------------------------------------------------------------------------------------Hash-int---------------------------------------------------------------------------------
先看hash-int,在這一條切分規則的下面,有一個mapfile,這表明着,這個切分規則是根據partition-hash-int的內容來決定的,那麼看一下這個文本文件
很簡單的內容,這表明着切分使用的基準列裏面,值爲10000的時候,放在第一個DN裏面(dn1),值爲10010的時候,放在第二個DN裏面(dn2)
能夠看一下實際效果
看一下MyCAT的Debug日誌,這兩條語句被分配到了dn1和dn2上面,數據庫裏面也插入了相對應的數據
那麼~問題來了(挖掘機滾粗~),若是插入的數據中,基準列的取值不是這個文件裏面寫明的值,會是什麼效果?
直截了當的報錯了~
好了,hash-int的這種切分規則,大致上能夠理解爲枚舉分區,會比較適合於取值固定的場合,好比說性別(0,1),省份(固定值,短期不會收復日本省吧~),渠道商 or 各類平臺的ID
並且,用逗號分隔能夠把多個值放在一個分區裏面,因此能夠根據實際的數據量/流量/訪問量來綜合制定切分策略;
缺點:畢竟不是全能戰士╮(╯_╰)╭
-------------------------------------------------------------------------------------------range-long---------------------------------------------------------------------------------
第二種切分方式,range-long,仔細一看的話,和hash-int是比較像的,也是由特定的文件來決定切分策略,因此仍是去看一下文件的內容
從文件內容能夠看出,這是一種範圍切分的方式,制定基準列的取值範圍,而後把這一範圍的全部數據都放到一個DN上面,這種方式和hash-int基本一致,就不截圖了(懶癌晚期,時間不夠了!)
這種切分策略,我的感受在業務數據庫裏面的使用場景會少一些,由於這種切分方式須要預約好總體的數量,這就決定了那種無限增加的數據不能用這個,畢竟要改動這個切分策略會很麻煩
真要用起來,感受也就對自增主鍵用,而後按照必定的數量來均勻切分,好比那種一天固定X條數據的業務(溫度採集?數據採集?之類的狀況),而後提早建好多個DN(庫)。
固然,也存在一種潛在的問題,若是在短期發生海量的順序插入操做,而每個DN(分庫)設定的數量比較高(好比說一個DN設定的放1000W條數據),那麼在這個時候,會出現某一個DN(分庫)IO壓力很是高,而其餘幾個DN(分庫)徹底沒有IO操做,就會出現相似於DB中常見的熱塊/熱盤的現象,而MySQL常常用自增主鍵,因此使得MySQL的表出現大量「順序」插入的機會會多不少。
--------------------------------------------------------------------------------------------mod-long-----------------------------------------------------------------------------------
mod-long,從mod來看這應該是一種取餘數的方法,來看一下具體配置的信息
count=4,這是表明着總共把數據切分紅四份,通常是和具體的DN數量對應,從而達到把數據均勻的分佈在四個DN上(固然,count<dn數量也沒什麼問題)
看一下實際的效果
看一下MyCAT的Debug日誌,看看MyCAT是如何處理的
採用這種取餘數的方式時,這四條數據分別插入了四個DN(庫),並且能夠看到,順序插入時,數據是被均勻的分散在多個DN(庫)上面
相比較於上面的range的方法,這種切分策略會更好的分散數據庫寫的壓力,可是問題也很明顯,一旦出現了範圍查詢,就須要MyCAT去合併結果,當數據量偏高的時候,這種跨庫查詢+合併結果消耗的時間有可能會增長不少,尤爲是還出現了order by的時候。
因此這種切分策略會比較適合於單點查詢的情景,好比說.....我也不知道......真的不知道,也許在銀行,查詢我的帳戶信息的時候,一些和用戶信息的表能夠作好冗餘,而後利用這種方式來提供更爲高效的查詢(畢竟銀行的用戶數量多,恩恩~)
--------------------------------------------------------------------------------partition-by-long----------------------------------------------------------------------------------
partition-by-long,處於range-long和mod-long之間的一個略微折中的劃分策略,具體切分形勢依照以下描述:
以1024爲一個單位,每一個DN存放partitionLength數量的數據,且,partitionCount x partitionLength=1024
看起來有點難以理解,形象點描述的話,以partitionCount(4) x partitionLength(256)爲例,sid%1024=0-255的放在DN1,256-511的放在DN2,以此類推
試着以128爲偏移值插入了八條數據,直接看MyCAT的日誌
能夠看到,八條數據均勻的分佈在這四個DN裏面~
值得一提的是,這種切分策略也支持非均勻分佈~實在是測不動了,盜圖兩張~
這兩張圖基本上也說明白了這種非均勻分佈的劃分策略,重點仍是在2x256+1x512=1024上面~
這種劃分策略在range-long和mod-long之間取了一個折中點,同時,也還算是比較靈活,能夠根據不一樣的狀況進行非均勻劃分,實際上能應用的場景會稍微多一點吧,或者說,很多場景都能用一用,相對減小了跨DN的情形,又把數據比較均勻的切分開來了,單點查詢也不會太慢。
-----------------------------------------------------------------------------------寫在最後-------------------------------------------------------------------------------------
其實MyCAT支持的切分方式還有很多,好比說按照時間的切分策略,能夠按月,按天切分等,在這裏也沒辦法把全部的策略都放上來,見諒了o( ̄ヘ ̄o#)
實際上從我的的觀點來看,時間的切分依照數據庫自己的分區策略來分也沒什麼問題,半年度,季度的數據也仍是會須要查詢的....PS: _(:з」∠)_真不是懶...
能夠說,MyCAT的分庫分表的重點,基本所有在這個rule裏面體現了,表要不要分,表的數據怎麼切分,都是須要根據實際業務來決定,充分根據業務的特色去決定最合適的劃分策略~
背景:接本應接在基準測試以後就整理,不過有別的事情耽擱了
環境:與基準測試時保持一致,4核32G,MyCAT-1.4-RC,6月17號發佈的版本,目前最新發布的版本應該是在7.29,七月底的樣子。
相關配置文件:server.xml與cacheservice.properties
文件簡介:
server.xml:保存了有關MyCAT的配置信息,包括MyCAT對外暴露的schema(包含這個schema對應的帳戶名和密碼),MyCAT server的鏈接池等參數配置
cacheservice.properties:緩存區的配置
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://org.opencloudb/">
- <system>
- <property name="processors">32</property>
- <property name="processorExecutor">256</property>
- <property name="processorBufferPool">204800000</property>
- <property name="processorBufferChunk">40960</property>
- <!--默認是65535 64K 用於sql解析時最大文本長度 -->
- <property name="maxStringLiteralLength">65535</property>
- <!--<property name="sequnceHandlerType">0</property>-->
- <!--<property name="backSocketNoDelay">1</property>-->
- <!--<property name="frontSocketNoDelay">1</property>-->
- <!--<property name="processorExecutor">16</property>-->
- <!--
- <property name="mutiNodeLimitType">1</property> 0:開啓小數量級(默認) ;1:開啓億級數據排序
- <property name="mutiNodePatchSize">100</property> 億級數量排序批量
- <property name="processors">32</property> <property name="processorExecutor">32</property>
- <property name="serverPort">8066</property> <property name="managerPort">9066</property>
- <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property>
- <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
- <property name="defaultSqlParser">druidparser</property>
- </system>
- <!--
- <user name="root">
- <property name="password">root</property>
- <property name="schemas">test</property>
- </user>
- <user name="root_read">
- <property name="password">root_read</property>
- <property name="schemas">test</property>
- <property name="readOnly">true</property>
- </user>
- -->
- <user name="test">
- <property name="password">test</property>
- <property name="schemas">test</property>
- </user>
- <!-- <cluster> <node name="cobar1"> <property name="host">127.0.0.1</property>
- <property name="weight">1</property> </node> </cluster> -->
- <!-- <quarantine> <host name="1.2.3.4"> <property name="user">test</property>
- </host> </quarantine> -->
- </mycat:server>
PS:MyCAT對外暴露的schema,是可使用readonly模式的,如上面配置文件中的加紅部分;
processors:用於指定可用線程數,實際上因爲如今的多核CPU和超線程技術,這個值能夠酌情調高,這裏調到了虛擬機核數的
八倍,感受稍稍有點高了,實際上
四倍or
五倍就差很少了
processorExecutor:相似於線程池大小的參數,酌情修改便可,在1.4以後,這個線程池是用來作異步處理邏輯的時候用的,對併發能力的影響相對較小了
processorBufferPool:BufferPool的大小,原則上來講,調高一些會比較好
processorBufferChunk:每個Buffer塊的大小,processorBufferPool/processorBufferChun能夠獲得buffer塊的數量
server調整總結:
processors+processorExecutor會影響到MyCAT可用的線程數,雖然調高點會比較好,可是調的過高會致使頻繁的上下文切換和軟中斷,在實際調整中,用top觀察sys和si的百分比,若是服務器/虛擬機並無什麼不乾淨的後臺程序和其餘的服務在運行,
sys在10%-15%以內,si在5%以內是比較理想的狀態;
processorBufferPool+processorBufferChunk影響的server緩存,保持processorBufferChunk大小合理的狀況下,
增長buffer塊的數量纔是關鍵;
cacheservice.properties示例:
- #used for mycat cache service conf
- factory.encache=org.opencloudb.cache.impl.EnchachePooFactory
- #key is pool name ,value is type,max size, expire seconds
- pool.SQLRouteCache=encache,1500000,60
- pool.ER_SQL2PARENTID=encache,2000,180
- layedpool.TableID2DataNodeCache=encache,3000,18000
- layedpool.TableID2DataNodeCache.TESTDB_ORDERS=10000,18000
cacheservice是SQL的緩存服務,
SQLRouteCache:sql路由緩存,經過緩存SQL語句的路由信息,下次查詢,不用再路由了,直接從緩存中獲取路由信息,而後發到各個節點執行;
TableID2DataNodeCache :表主鍵ID的路由緩存,爲每個表建一個緩存池,命名爲TableID2DataNodeCache.TESTDB_表名,緩存的key是id的值,value是節點名;
ER_SQL2PARENTID : ER關係的緩存目前只是在Insert語句中才會使用緩存,子表插入數據的時候,根據joinKey的值,判斷父表所在分片,從而定位子表分片,分片信息put緩存,以便下次直接獲取
因爲在測試的時候並無對測試表是簡單的區域劃分,因此在測試中對後兩個緩存是沒有利用到的,具體對緩存大小的調整能夠參考SQLRouteCache;
首先貼出結論:SQLRouteCache的大小對具體的QPS有比較大的影響(廢話......._(:з」∠)_),在實際的測試過程當中,保持線程併發不變的狀況下,從100W-300W都有調整過,大概每增長50W,有約15%的增長,直觀來看的話,從100W-300W的增長過程當中,128線程,5張表x5000W行/表的狀況下,QPS範圍從1W5-2W5,
然而有一個問題很重要,當這個值增長到比較高後,會頻繁出現極高的sys佔用率,同時vmstat命令下,proc列會有很是高的r和b,直接後果就是
MyCAT server自己會出現劇烈的性能波動
,在基準測試中,QPS的低谷會降到3000-4000;可是free查看內存使用的時候,並無出現內存不足的狀況,推斷爲MyCAT自己的緩存設計中存在不完善的地方;
具體的設置值,在不斷的測試中,
以以前的虛擬機的配置(4核,32G
)爲參考
,當
SQLRouteCache
的值設置到180W以上的時候,就會不定時的出現性能波動,爲了保證穩定運行,在基準測試時採用了較低的150W
PS:因爲基準測試的時候,SQL語句模板裏面的參數都是
採用隨機值,因此緩存的命中率是偏低的(150W的設置下,大約只有
25%的命中率),生產環境下,
這個命中率會高不少,同時QPS也會有必定程度的上升
PPS:這個routeCache和MySQL的queryCache比較像,緩存的都是具體的SQL語句,而不是框架裏面的帶?佔位符的語句,queryCache的信息能夠參考http://blog.itpub.net/29510932/viewspace-1694922/
來源:http://blog.itpub.net/29510932/