在分佈式數據庫中間件領域,Mycat和ShardingSphere能夠說是在開源界有着至關重要的位置,很多小夥伴也在問我:Mycat和sharding-jdbc哪一個好呀!其實,就我自己而言,我做爲Mycat的開發者,也深度分析過ShardingSphere的源碼。能夠這麼說:各有各的優點吧!其實,針對ShardingSphere,我也跟ShardingSphere的創始人亮哥聊過,從他那裏確實學到了很多有價值的東西。後續我也可能會寫一部關於分佈式數據庫的書籍,也說不定會將Mycat和ShardingSphere寫進去呢。到時確定是要請亮哥幫我寫推薦序呀!哈哈哈。。。前端
好了,說了這麼多,今天給你們分享下Mycat的三大核心配置文件:server.xml、schema.xml和rule.xml。java
server.xml幾乎保存了全部mycat須要的系統配置信息。其在代碼內直接的映射類爲SystemConfig類。如今就對這個文件中的配置進行相關的介紹node
<user name="test"> <property name="password">test</property> <property name="schemas">TESTDB</property> <property name="readOnly">true</property> </user>
server.xml中的標籤本就很少,這個標籤主要用於定義登陸mycat的用戶和權限。例如上面的例子中,我定義了一個用戶,用戶名爲test、密碼也爲test,可訪問的schema也只有TESTDB一個。若是我在schema.xml中定義了多個schema,那麼這個用戶是沒法訪問其餘的schema。在mysql客戶端看來則是沒法使用use切換到這個其餘的數據庫。若是使用了use命令,則mycat會報出這樣的錯誤提示:ERROR 1044 (HY000): Access denied for user 'test' to database 'xxx'這個標籤嵌套的property標籤則是具體聲明的屬性值,正如上面的例子。咱們能夠修改user標籤的name屬性來指定用戶名;修改password內的文原本修改密碼;修改readOnly爲true 或false來限制用戶是否只是可讀的;修改schemas內的文原本控制用戶可放問的schema;修改schemas內的文原本控制用戶可訪問的schema,同時訪問多個schema的話使用 , 隔開,例如:mysql
<property name="schemas">TESTDB,db1,db2</property>
這個標籤內嵌套的全部property標籤都與系統配置有關,請注意,下面我會省去標籤property直接使用這個標籤的name屬性內的值來介紹這個屬性的做用。程序員
defaultSqlParser屬性面試
因爲mycat最初是時候Foundation DB的sql解析器,然後才添加的Druid的解析器。因此這個屬性用來指定默認的解析器。目前的可用的取值有:druidparser和 fdbparser。使用的時候能夠選擇其中的一種,目前通常都使用druidparser。算法
processors屬性sql
這個屬性主要用於指定系統可用的線程數,默認值爲Runtime.getRuntime().availableProcessors()方法返回的值。主要影響processorBufferPool、processorBufferLocalPercent、processorExecutor屬性。NIOProcessor的個數也是由這個屬性定義的,因此調優的時候能夠適當的調高這個屬性。mongodb
processorBufferChunk屬性數據庫
這個屬性指定每次分配Socket Direct Buffer的大小,默認是4096個字節。這個屬性也影響buffer pool的長度。
processorBufferPool屬性
這個屬性指定bufferPool計算 比例值。因爲每次執行NIO讀、寫操做都須要使用到buffer,系統初始化的時候會創建必定長度的buffer池來加快讀、寫的效率,減小創建buffer的時間。
BufferPool和ThreadLocalPool
BufferPool由ThreadLocalPool組合而成,每次從BufferPool中獲取buffer都會優先獲取ThreadLocalPool中的buffer,未命中以後纔會去獲取BufferPool中的buffer。也就是說ThreadLocalPool是做爲BufferPool的二級緩存,每一個線程內部本身使用的。固然,這其中還有一些限制條件須要線程的名字是由$_開頭。然而,BufferPool上的buffer則是每一個NIOProcessor都共享的。默認這個屬性的值爲:
默認bufferChunkSize(4096) * processors屬性 * 1000 BufferPool的總長度 = bufferPool / bufferChunk。
若bufferPool不是bufferChunk的整數倍,則總長度爲前面計算得出的商 + 1 假設系統線程數爲4,其餘都爲屬性的默認值,則:
bufferPool = 4096 * 4 * 1000 BufferPool的總長度 : 4000 = 16384000 / 4096
processorBufferLocalPercent屬性
前面提到了ThreadLocalPool。這個屬性就是用來控制分配這個pool的大小用的,但其也並非一個準確的值,也是一個比例值。這個屬性默認值爲100。
線程緩存百分比 = bufferLocalPercent / processors屬性。
例如,系統能夠同時運行4個線程,使用默認值,則根據公式每一個線程的百分比爲25。最後根據這個百分比來計算出具體的。
ThreadLocalPool的長度公式以下:
ThreadLocalPool的長度 = 線程緩存百分比 * BufferPool長度 / 100
假設BufferPool的長度爲 4000,其餘保持默認值。
那麼最後每一個線程創建上的ThreadLocalPool的長度爲: 1000 = 25 * 4000 / 100
processorExecutor屬性
這個屬性主要用於指定NIOProcessor上共享的businessExecutor固定線程池大小。mycat在須要處理一些異步邏輯的時候會把任務提交到這個線程池中。新版本中這個鏈接池的使用頻率不是很大了,能夠設置一個較小的值。
sequnceHandlerType屬性
指定使用Mycat全局序列的類型。0爲本地文件方式,1爲數據庫方式。默認是使用本地文件方式,文件方式主要只是用於測試使用。
TCP鏈接相關屬性
StandardSocketOptions.SO_RCVBUF StandardSocketOptions.SO_SNDBUF StandardSocketOptions.TCP_NODELAY
以上這三個屬性,分別由:
各自設置先後端TCP鏈接參數。Mycat在每次創建前、後端鏈接的時候都會使用這些參數初始化鏈接。能夠按系統要求適當的調整這些buffer的大小。TCP鏈接參數的定義,能夠查看Javadoc。
MySQL鏈接相關屬性初始化mysql先後端鏈接所涉及到的一些屬性:
週期間隔相關屬性
mycat中有幾個週期性的任務來異步的處理一些我須要的工做。這些屬性就在系統調優的過程當中也是比不可少的。
服務相關屬性
這裏介紹一個與服務相關的屬性,主要會影響外部系統對myact的感知。
schema.xml做爲MyCat中重要的配置文件之一,管理着MyCat的邏輯庫、表、分片規則、DataNode以及DataSource。弄懂這些配置,是正確使用MyCat的前提。這裏就一層層對該文件進行解析。
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://org.opencloudb/"> <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"> <table name="user" dataNode="dn1,dn2" rule="auto-sharding-long" /> <table name="stat_tcp_stream" dataNode="dn2,dn3" rule="auto-sharding-long" /> </schema> <dataNode name="dn1" dataHost="localhost1" database="mpos_tshark_miner_2014" /> <dataNode name="dn2" dataHost="localhost2" database="mpos_tshark_miner2014" /> <dataNode name="dn3" dataHost="localhost3" database="mpos_tshark_hrtel" /> <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" dbType="mysql" dbDriver="jdbc" writeType="0" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="jdbc:mysql://192.168.1.150:5029" user="root" password="root"></writeHost> </dataHost> <dataHost name="localhost2" maxCon="1000" minCon="1" balance="0" dbType="mysql" dbDriver="jdbc"> <heartbeat> </heartbeat> <writeHost host="hostM2" url="jdbc:mysql://192.168.1.150:5029" user="root" password="root"></writeHost> </dataHost> <dataHost name="localhost3" maxCon="1000" minCon="1" balance="0" dbType="mysql" dbDriver="jdbc"> <heartbeat> </heartbeat> <writeHost host="hostM3" url="jdbc:mysql://192.168.1.150:5029" user="root" password="root"></writeHost> </dataHost> </mycat:schema>
dataNode
該屬性用於綁定邏輯庫到某個具體的database上,若是定義了這個屬性,那麼這個邏輯庫就不能工做在分庫分表模式下了。也就是說對這個邏輯庫的全部操做會直接做用到綁定的dataNode上,這個schema就能夠用做讀寫分離和主從切換,具體以下配置:
<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> <!—這裏不能配置任何邏輯表信息--> </schema>
那麼如今USERDB就綁定到dn1所配置的具體database上,能夠直接訪問這個database。固然該屬性只能配置綁定到一個database上,不能綁定多個dn。
checkSQLschema
當該值設置爲 true 時,若是咱們執行語句 select * from TESTDB.travelrecord; 則MyCat會把語句修改成 select * from travelrecord; 。即把表示schema的字符去掉,避免發送到後端數據庫執行時報 (ERROR 1146 (42S02): Table ‘testdb.travelrecord’ doesn’t exist)。 不過,即便設置該值爲 true ,若是語句所帶的是並不是是schema指定的名字,例如: select * from db1.travelrecord; 那麼MyCat並不會刪除db1這個字段,若是沒有定義該庫的話則會報錯,因此在提供SQL語句的最好是不帶這個字段。
sqlMaxLimit
當該值設置爲某個數值時。每條執行的SQL語句,若是沒有加上limit語句,MyCat也會自動的加上所對應的值。例如設置值爲100,執行 select * from TESTDB.travelrecord; 的效果爲和執行 select * from TESTDB.travelrecord limit 100; 相同。不設置該值的話,MyCat默認會把查詢到的信息所有都展現出來,形成過多的輸出。因此,在正常使用中,仍是建議加上一個值,用於減小過多的數據返回。固然SQL語句中也顯式的指定limit的大小,不受該屬性的約束。
<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" ></table>
Table 標籤訂義了MyCat中的邏輯表,全部須要拆分的表都須要在這個標籤中定義。
name屬性
定義邏輯表的表名,這個名字就如同我在數據庫中執行create table命令指定的名字同樣,同個schema標籤中定義的名字必須惟一。
dataNode屬性
定義這個邏輯表所屬的dataNode, 該屬性的值須要和dataNode標籤中name屬性的值相互對應。若是須要定義的dn過多可使用以下的方法減小配置:
<table name="travelrecord" dataNode="multipleDn$0-99,multipleDn2$100-199" rule="auto-sharding-long" ></table> <dataNode name="multipleDn" dataHost="localhost1" database="db$0-99" ></dataNode> <dataNode name="multipleDn2" dataHost="localhost1" database=" db$0-99" ></dataNode>
這裏須要注意的是database屬性所指定的真實database name須要在後面添加一個,例如上面的例子中,我須要在真實的mysql上創建名稱爲dbs0到dbs99的database。
rule屬性
該屬性用於指定邏輯表要使用的規則名字,規則名字在rule.xml中定義,必須與tableRule標籤中name屬性屬性值一一對應。
primaryKey屬性
該邏輯表對應真實表的主鍵,例如:分片的規則是使用非主鍵進行分片的,那麼在使用主鍵查詢的時候,就會發送查詢語句到全部配置的DN上,若是使用該屬性配置真實表的主鍵。難麼MyCat會緩存主鍵與具體DN的信息,那麼再次使用非主鍵進行查詢的時候就不會進行廣播式的查詢,就會直接發送語句給具體的DN,可是儘管配置該屬性,若是緩存並無命中的話,仍是會發送語句給具體的DN,來得到數據。
type屬性
該屬性定義了邏輯表的類型,目前邏輯表只有「全局表」和」普通表」兩種類型。對應的配置:全局表:global。普通表:不指定該值爲globla的全部表。
autoIncrement屬性
MySQL對非自增加主鍵,使用last_insert_id()是不會返回結果的,只會返回0。因此,只有定義了自增加主鍵的表才能夠用last_insert_id()返回主鍵值。mycat目前提供了自增加主鍵功能,可是若是對應的mysql節點上數據表,沒有定義auto_increment,那麼在mycat層調用last_insert_id()也是不會返回結果的。因爲insert操做的時候沒有帶入分片鍵,mycat會先取下這個表對應的全局序列,而後賦值給分片鍵。這樣才能正常的插入到數據庫中,最後使用last_insert_id()纔會返回插入的分片鍵值。若是要使用這個功能最好配合使用數據庫模式的全局序列。使用autoIncrement=「true」 指定這個表有使用自增加主鍵,這樣mycat纔會不拋出分片鍵找不到的異常。使用autoIncrement=「false」 來禁用這個功能,固然你也能夠直接刪除掉這個屬性。默認就是禁用的。
needAddLimit屬性
指定表是否須要自動的在每一個語句後面加上limit限制。因爲使用了分庫分表,數據量有時會特別巨大。這時候執行查詢語句,若是恰巧又忘記了加上數量限制的話。那麼查詢全部的數據出來,也夠等上一小會兒的。因此,mycat就自動的爲咱們加上LIMIT 100。固然,若是語句中有limit,就不會在次添加了。這個屬性默認爲true,你也能夠設置成false`禁用掉默認行爲。
childTable標籤用於定義E-R分片的子表。經過標籤上的屬性與父表進行關聯
<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" /> </childTable> <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" /> </table>
name屬性
定義子表的表名。
joinKey屬性
插入子表的時候會使用這個列的值查找父表存儲的數據節點。
parentKey屬性
屬性指定的值通常爲與父表創建關聯關係的列名。程序首先獲取joinkey的值,再經過 parentKey 屬性指定的列名產生查詢語句,經過執行該語句獲得父表存儲在哪一個分片上。從而肯定子表存儲的位置。
primaryKey屬性
同table標籤所描述的。
needAddLimit屬性
同table標籤所描述的。
<dataNode name="dn1" dataHost="lch3307" database="db1" ></dataNode>
dataNode 標籤訂義了MyCat中的數據節點,也就是咱們一般說所的數據分片。一個dataNode 標籤就是一個獨立的數據分片。例子中所表述的意思爲:使用名字爲lch3307數據庫實例上的db1物理數據庫,這就組成一個數據分片,最後,咱們使用名字dn1標識這個分片。
name屬性
定義數據節點的名字,這個名字須要是惟一的,咱們須要在table標籤上應用這個名字,來創建表與分片對應的關係。
dataHost屬性
該屬性用於定義該分片屬於哪一個數據庫實例的,屬性值是引用dataHost標籤上定義的name屬性。
database屬性
該屬性用於定義該分片屬性哪一個具體數據庫實例上的具體庫,由於這裏使用兩個緯度來定義分片,就是:實例+具體的庫。由於每一個庫上創建的表和表結構是同樣的。因此這樣作就能夠輕鬆的對錶進行水平拆分。
做爲Schema.xml中最後的一個標籤,該標籤在mycat邏輯庫中也是做爲最底層的標籤存在,直接定義了具體的數據庫實例、讀寫分離配置和心跳語句。如今咱們就解析下這個標籤。
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" 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"> <!-- can have multi read hosts --> <!-- <readHost host="hostS1" url="localhost:3306" user="root" password="123456" /> --> </writeHost> <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> --> </dataHost>
name屬性
惟一標識dataHost標籤,供上層的標籤使用。
maxCon屬性
指定每一個讀寫實例鏈接池的最大鏈接。也就是說,標籤內嵌套的writeHost、readHost標籤都會使用這個屬性的值來實例化出鏈接池的最大鏈接數。
minCon屬性
指定每一個讀寫實例鏈接池的最小鏈接,初始化鏈接池的大小。
balance屬性
writeType屬性
負載均衡類型,目前的取值有3種:
dbType屬性
指定後端鏈接的數據庫類型,目前支持二進制的mysql協議,還有其餘使用JDBC鏈接的數據庫。例如:mongodb、oracle、spark等。
dbDriver屬性
指定鏈接後端數據庫使用的Driver,目前可選的值有native和JDBC。使用native的話,由於這個值執行的是二進制的mysql協議,因此可使用mysql和maridb。其餘類型的數據庫則須要使用JDBC驅動來支持。若是使用JDBC的話須要將符合JDBC 4標準的驅動JAR包放到MYCAT\lib目錄下,並檢查驅動JAR包中包括以下目錄結構的文件:META-INF\services\java.sql.Driver。在這個文件內寫上具體的Driver類名,例如:com.mysql.jdbc.Driver。
這個標籤內指明用於和後端數據庫進行心跳檢查的語句。例如,MYSQL可使用select user(),Oracle可使用select 1 from dual等。這個標籤還有一個connectionInitSql屬性,主要是當使用Oracla數據庫時,須要執行的初始化SQL語句就這個放到這裏面來。例如:alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'
這兩個標籤都指定後端數據庫的相關配置給mycat,用於實例化後端鏈接池。惟一不一樣的是,writeHost指定寫實例、readHost指定讀實例,組着這些讀寫實例來知足系統的要求。在一個dataHost內能夠定義多個writeHost和readHost。可是,若是writeHost指定的後端數據庫宕機,那麼這個writeHost綁定的全部readHost都將不可用。另外一方面,因爲這個writeHost宕機系統會自動的檢測到,並切換到備用的writeHost上去。這兩個標籤的屬性相同,這裏就一塊兒介紹。
host屬性
用於標識不一樣實例,通常writeHost咱們使用M1,readHost咱們用S1。
url屬性
後端實例鏈接地址,若是是使用native的dbDriver,則通常爲address:port這種形式。用JDBC或其餘的dbDriver,則須要特殊指定。當使用JDBC時則能夠這麼寫:jdbc:mysql://localhost:3306/。
user屬性
後端存儲實例須要的用戶名字
password屬性
後端存儲實例須要的密碼
rule.xml裏面就定義了咱們對錶進行拆分所涉及到的規則定義。咱們能夠靈活的對錶使用不一樣的分片算法,或者對錶使用相同的算法但具體的參數不一樣。這個文件裏面主要有tableRule和function這兩個標籤。在具體使用過程當中能夠按照需求添加tableRule和function。
這個標籤訂義表規則。定義的表規則,在rule.xml:
<tableRule name="rule1"> <rule> <columns>id</columns> <algorithm>func1</algorithm> </rule> </tableRule>
name 屬性指定惟一的名字,用於標識不一樣的表規則。內嵌的rule標籤則指定對物理表中的哪一列進行拆分和使用什麼路由算法。columns 內指定要拆分的列名字。algorithm 使用function標籤中的name屬性。鏈接表規則和具體路由算法。固然,多個表規則能夠鏈接到同一個路由算法上。標籤內使用。讓邏輯表使用這個規則進行分片。
<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> </function>
其中,各屬性以下所示。
好了,今天就到這兒吧,我是冰河,咱們下期見!!
冰河寫的原創PDF都在這兒了:涵蓋高併發編程、併發編程源碼解析、限流、設計模式、Java8新特性、分佈式存儲、Nginx技術、互聯網工程技術等,每一部PDF都是超硬核的技術乾貨。現都免費開源,詳情參見《肝了三天三夜整理出這份36萬字全網最牛的開源高併發編程PDF!!》文末附各PDF下載方式。
微信搜一搜【冰河技術】微信公衆號,關注這個有深度的程序員,天天閱讀超硬核技術乾貨,公衆號內回覆【PDF】有我準備的一線大廠面試資料和我原創的超硬核PDF技術文檔,以及我爲你們精心準備的多套簡歷模板(不斷更新中),但願你們都能找到心儀的工做,學習是一條時而鬱鬱寡歡,時而開懷大笑的路,加油。若是你經過努力成功進入到了心儀的公司,必定不要懈怠放鬆,職場成長和新技術學習同樣,不進則退。若是有幸咱們江湖再見!
另外,我開源的各個PDF,後續我都會持續更新和維護,感謝你們長期以來對冰河的支持!!