server.xml配置css
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mycat:server SYSTEM "server.dtd">
3 <mycat:server xmlns:mycat="http://org.opencloudb/">
4 <system>
5 <property name="defaultSqlParser">druidparser</property>
6 <property name="useCompression">1</property>
<property name="processorBufferPool">204800000</property> #BufferPool的大小
7 <property name="processorBufferChunk">40960</property> #每個Buffer塊的大小,processorBufferPool/processorBufferChun能夠獲得buffer塊的數量
10 <property name="maxStringLiteralLength">65535</property>
11 <property name="sequnceHandlerType">0</property>
12 <property name="backSocketNoDelay">1</property>
13 <property name="frontSocketNoDelay">1</property>
15 <property name="mutiNodeLimitType">1</property>
16 <property name="mutiNodePatchSize">100</property>
17 <property name="processors">32</property> #可用線程數,實際上因爲如今的多核CPU和超線程技術 酌情調高4-8倍
18 <property name="processorExecutor">32</property> #線程池是用來作異步處理邏輯的時候用的,對併發能力的影響相對較小
19 <property name="serverPort">3306</property> #定義訪問端口
20 <property name="managerPort">9066</property> #定義管理端口
21 <property name="idleTimeout">300000</property> #超時時間
22 <property name="bindIp">0.0.0.0</property> #安全綁定IP
23 <property name="frontWriteQueueSize">4096</property>
24 <property name="processors">32</property>
25 </system>
26 <user name="root"> #訪問帳號
27 <property name="password">123456</property> #訪問密碼
28 <property name="schemas">chshop</property> #庫文件名
29 </user>
<user name="root_read"> #只讀帳號
<property name="password">654321</property>
<property name="schemas">chshop</property>
<property name="readOnly">true</property> #只讀模式
</user>
30 <quarantine>
31 <whitehost>
32 <host host="127.0.0.1" user="root"></host> #白名單
33 <host host="172.16.1.45" user="root"></host> #白名單容許那些IP能經過root訪問
34 </whitehost>
35 <blacklist check="false"></blacklist> #黑名單
36 </quarantine>
37 </mycat:server>
server調整總結:
processors+processorExecutor會影響到MyCAT可用的線程數,雖然調高點會比較好,可是調的過高會致使頻繁的上下文切換和軟中斷,在實際調整中,用top觀察sys和si的百分比,若是服務器/虛擬機並無什麼不乾淨的後臺程序和其餘的服務在運行,sys在10%-15%以內,si在5%以內是比較理想的狀態;
processorBufferPool+processorBufferChunk影響的server緩存,保持processorBufferChunk大小合理的狀況下,增長buffer塊的數量纔是關鍵;前端
cacheservice配置-是SQL的緩存服務node
#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,10000,1800 #sql路由緩存,經過緩存SQL語句的路由信息,下次查詢,不用再路由了,直接從緩存中獲取路由信息,而後發到各個節點執行;
pool.ER_SQL2PARENTID=encache,1000,1800 #ER關係的緩存目前只是在Insert語句中才使用緩存,子表插入數據的時候根據joinKey值,判斷父表所在分片,從而定位子表分片,分片信息put緩存layedpool.TableID2DataNodeCache=encache,10000,18000#表主鍵ID的路由緩存,爲每個表建一個緩存池,命名爲TableID2DataNodeCache.TESTDB_表名,緩存key是id的值,value是節點名
layedpool.TableID2DataNodeCache.TESTDB_ORDERS=50000,18000
Cacheservice調整總結mysql
SQLRouteCache的大小對具體的QPS有比較大的影響 參考: pool.SQLRouteCache=encache,1500000,60sql
rule.xml 配置mongodb
hash-int---在這一條切分規則的下面,有一個mapfile,這表明着,這個切分規則是根據partition-hash-int的內容來決定的,那麼看一下這個文本文件
很簡單的內容,這表明着切分使用的基準列裏面,值爲10000的時候,放在第一個DN裏面(dn1),值爲10010的時候,放在第二個DN裏面(dn2) 能夠看一下實際效果
看一下MyCAT的Debug日誌,這兩條語句被分配到了dn1和dn2上面,數據庫裏面也插入了相對應的數據
那麼~問題來了(挖掘機滾粗~),若是插入的數據中,基準列的取值不是這個文件裏面寫明的值,會是什麼效果?
直截了當的報錯了~
好了,hash-int的這種切分規則,大致上能夠理解爲枚舉分區,會比較適合於取值固定的場合,好比說性別(0,1),省份(固定值,短期不會收復日本省吧~),渠道商 or 各類平臺的ID
並且,用逗號分隔能夠把多個值放在一個分區裏面,因此能夠根據實際的數據量/流量/訪問量來綜合制定切分策略;
缺點:畢竟不是全能戰士數據庫
range-long ----仔細一看的話,和hash-int是比較像的,也是由特定的文件來決定切分策略,因此仍是去看一下文件的內容
從文件內容能夠看出,這是一種範圍切分的方式,制定基準列的取值範圍,而後把這一範圍的全部數據都放到一個DN上面,這種方式和hash-int基本一致,就不截圖了(懶癌晚期,時間不夠了!)
這種切分策略,我的感受在業務數據庫裏面的使用場景會少一些,由於這種切分方式須要預約好總體的數量,這就決定了那種無限增加的數據不能用這個,畢竟要改動這個切分策略會很麻煩
真要用起來,感受也就對自增主鍵用,而後按照必定的數量來均勻切分,好比那種一天固定X條數據的業務(溫度採集?數據採集?之類的狀況),而後提早建好多個DN(庫)。
固然,也存在一種潛在的問題,若是在短期發生海量的順序插入操做,而每個DN(分庫)設定的數量比較高(好比說一個DN設定的放1000W條數據),那麼在這個時候,會出現某一個DN(分庫)IO壓力很是高,而其餘幾個DN(分庫)徹底沒有IO操做,就會出現相似於DB中常見的熱塊/熱盤的現象,而MySQL常常用自增主鍵,因此使得MySQL的表出現大量「順序」插入的機會會多不少。後端
mod-long--從mod來看這應該是一種取餘數的方法,來看一下具體配置的信息
count=4,這是表明着總共把數據切分紅四份,通常是和具體的DN數量對應,從而達到把數據均勻的分佈在四個DN上(固然,count<dn數量也沒什麼問題) 看一下實際的效果
看一下MyCAT的Debug日誌,看看MyCAT是如何處理的
採用這種取餘數的方式時,這四條數據分別插入了四個DN(庫),並且能夠看到,順序插入時,數據是被均勻的分散在多個DN(庫)上面
相比較於上面的range的方法,這種切分策略會更好的分散數據庫寫的壓力,可是問題也很明顯,一旦出現了範圍查詢,就須要MyCAT去合併結果,當數據量偏高的時候,這種跨庫查詢+合併結果消耗的時間有可能會增長不少,尤爲是還出現了order by的時候。
因此這種切分策略會比較適合於單點查詢的情景,好比說.....我也不知道......真的不知道,也許在銀行,查詢我的帳戶信息的時候,一些和用戶信息的表能夠作好冗餘,而後利用這種方式來提供更爲高效的查詢(畢竟銀行的用戶數量多,恩恩~)緩存
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的分庫分表的重點,基本所有在這個rule裏面體現了,表要不要分,表的數據怎麼切分,都是須要根據實際業務來決定,充分根據業務的特色去決定最合適的劃分策略
------------------------------------------------------------------------------------------
schema.xml 配置
- <?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自己的邏輯結構裏面,就包含了分庫分表的這種特性(能夠指定不一樣的表存在於不一樣的數據庫中,而沒必要分到所有數據庫)