【Mycat】Mycat核心開發者帶你看盡Mycat三大核心配置檔案

冰河團隊發表於2020-11-12

寫在前面

在分散式資料庫中介軟體領域,Mycat和ShardingSphere可以說是在開源界有著相當重要的位置,不少小夥伴也在問我:Mycat和sharding-jdbc哪個好呀!其實,就我本身而言,我作為Mycat的開發者,也深度分析過ShardingSphere的原始碼。可以這麼說:各有各的優勢吧!其實,針對ShardingSphere,我也跟ShardingSphere的創始人亮哥聊過,從他那裡確實學到了不少有價值的東西。後續我也可能會寫一部關於分散式資料庫的書籍,也說不定會將Mycat和ShardingSphere寫進去呢。到時肯定是要請亮哥幫我寫推薦序呀!哈哈哈。。。

好了,說了這麼多,今天給大家分享下Mycat的三大核心配置檔案:server.xml、schema.xml和rule.xml。

server.xml

server.xml幾乎儲存了所有mycat需要的系統配置資訊。其在程式碼內直接的對映類為SystemConfig類。現在就對這個檔案中的配置進行相關的介紹

user標籤

<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的話使用 , 隔開,例如:

<property name="schemas">TESTDB,db1,db2</property>

system標籤

這個標籤內巢狀的所有property標籤都與系統配置有關,請注意,下面我會省去標籤property直接使用這個標籤的name屬性內的值來介紹這個屬性的作用。

defaultSqlParser屬性

由於mycat最初是時候Foundation DB的sql解析器,而後才新增的Druid的解析器。所以這個屬性用來指定預設的解析器。目前的可用的取值有:druidparser和 fdbparser。使用的時候可以選擇其中的一種,目前一般都使用druidparser。

processors屬性

這個屬性主要用於指定系統可用的執行緒數,預設值為Runtime.getRuntime().availableProcessors()方法返回的值。主要影響processorBufferPool、processorBufferLocalPercent、processorExecutor屬性。NIOProcessor的個數也是由這個屬性定義的,所以調優的時候可以適當的調高這個屬性。

processorBufferChunk屬性

這個屬性指定每次分配Socket Direct Buffer的大小,預設是4096個位元組。這個屬性也影響buffer pool的長度。

processorBufferPool屬性

這個屬性指定bufferPool計算 比例值。由於每次執行NIO讀、寫操作都需要使用到buffer,系統初始化的時候會建立一定長度的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

以上這三個屬性,分別由:

  • frontSocketSoRcvbuf 預設值: 1024 * 1024
  • frontSocketSoSndbuf 預設值: 4 * 1024 * 1024
  • frontSocketNoDelay 預設值: 1
  • backSocketSoRcvbuf 預設值: 4 * 1024 * 1024
  • backSocketSoSndbuf 預設值: 1024 * 1024
  • backSocketNoDelay 預設值: 1

各自設定前後端TCP連線引數。Mycat在每次建立前、後端連線的時候都會使用這些引數初始化連線。可以按系統要求適當的調整這些buffer的大小。TCP連線引數的定義,可以檢視Javadoc。
MySQL連線相關屬性初始化mysql前後端連線所涉及到的一些屬性:

  • packetHeaderSize : 指定Mysql協議中的報文頭長度。預設4。
  • maxPacketSize : 指定Mysql協議可以攜帶的資料最大長度。預設16M。
  • idleTimeout : 指定連線的空閒超時時間。某連線在發起空閒檢查下,發現距離上次使用超過了空閒時間,那麼這個連線會被回收,就是被直接的關閉掉。預設30分鐘。
  • charset : 連線的初始化字符集。預設為utf8。
  • txIsolation : 前端連線的初始化事務隔離級別,只在初始化的時候使用,後續會根據客戶端傳遞過來的屬性對後端資料庫連線進行同步。預設為REPEATED_READ。
  • sqlExecuteTimeout:SQL執行超時的時間,Mycat會檢查連線上最後一次執行SQL的時間,若超過這個時間則會直接關閉這連線。預設時間為300秒。

週期間隔相關屬性

mycat中有幾個週期性的任務來非同步的處理一些我需要的工作。這些屬性就在系統調優的過程中也是比不可少的。

  • processorCheckPeriod : 清理NIOProcessor上前後端空閒、超時和關閉連線的間隔時間。預設是1秒。
  • dataNodeIdleCheckPeriod : 對後端連線進行空閒、超時檢查的時間間隔,預設是60秒。
  • dataNodeHeartbeatPeriod : 對後端所有讀、寫庫發起心跳的間隔時間,預設是10秒。

服務相關屬性

這裡介紹一個與服務相關的屬性,主要會影響外部系統對myact的感知。

  • bindIp : mycat服務監聽的IP地址,預設值為0.0.0.0。
  • serverPort : 定義mycat的使用埠,預設值為8066。
  • managerPort : 定義mycat的管理埠,預設值為9066。

schema.xml

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>

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標籤

<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標籤

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標籤

<dataNode name="dn1" dataHost="lch3307" database="db1" ></dataNode>

dataNode 標籤定義了MyCat中的資料節點,也就是我們通常說所的資料分片。一個dataNode 標籤就是一個獨立的資料分片。例子中所表述的意思為:使用名字為lch3307資料庫例項上的db1物理資料庫,這就組成一個資料分片,最後,我們使用名字dn1標識這個分片。

name屬性

定義資料節點的名字,這個名字需要是唯一的,我們需要在table標籤上應用這個名字,來建立表與分片對應的關係。

dataHost屬性

該屬性用於定義該分片屬於哪個資料庫例項的,屬性值是引用dataHost標籤上定義的name屬性。

database屬性

該屬性用於定義該分片屬性哪個具體資料庫例項上的具體庫,因為這裡使用兩個緯度來定義分片,就是:例項+具體的庫。因為每個庫上建立的表和表結構是一樣的。所以這樣做就可以輕鬆的對錶進行水平拆分。

dataHost標籤

作為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屬性

  • balance=“0”, 所有讀操作都傳送到當前可用的writeHost上。
  • balance=“1”,所有讀操作都隨機的傳送到readHost。
  • balance=“2”,所有讀操作都隨機的在writeHost、readhost上分發。

writeType屬性

負載均衡型別,目前的取值有3種:

  • writeType=“0”, 所有寫操作都傳送到可用的writeHost上。
  • writeType=“1”,所有寫操作都隨機的傳送到readHost。
  • writeType=“2”,所有寫操作都隨機的在writeHost、readhost分上發。

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。

heartbeat標籤

這個標籤內指明用於和後端資料庫進行心跳檢查的語句。例如,MYSQL可以使用select user(),Oracle可以使用select 1 from dual等。這個標籤還有一個connectionInitSql屬性,主要是當使用Oracla資料庫時,需要執行的初始化SQL語句就這個放到這裡面來。例如:alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'

writeHost標籤、readHost標籤

這兩個標籤都指定後端資料庫的相關配置給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

rule.xml裡面就定義了我們對錶進行拆分所涉及到的規則定義。我們可以靈活的對錶使用不同的分片演算法,或者對錶使用相同的演算法但具體的引數不同。這個檔案裡面主要有tableRule和function這兩個標籤。在具體使用過程中可以按照需求新增tableRule和function。

tableRule標籤

這個標籤定義表規則。定義的表規則,在rule.xml:

<tableRule name="rule1">
	<rule>
		<columns>id</columns>
		<algorithm>func1</algorithm>
	</rule>
</tableRule>

name 屬性指定唯一的名字,用於標識不同的表規則。內嵌的rule標籤則指定對物理表中的哪一列進行拆分和使用什麼路由演算法。columns 內指定要拆分的列名字。algorithm 使用function標籤中的name屬性。連線表規則和具體路由演算法。當然,多個表規則可以連線到同一個路由演算法上。標籤內使用。讓邏輯表使用這個規則進行分片。

function標籤

<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap">
	<property name="mapFile">partition-hash-int.txt</property>
</function>

其中,各屬性如下所示。

  • name 指定演算法的名字。
  • class 制定路由演算法具體的類名字。
  • property 為具體演算法需要用到的一些屬性。

好了,今天就到這兒吧,我是冰河,我們下期見!!

原創PDF

冰河寫的原創PDF都在這兒了:涵蓋高併發程式設計、併發程式設計原始碼解析、限流、設計模式、Java8新特性、分散式儲存、Nginx技術、網際網路工程技術等,每一部PDF都是超硬核的技術乾貨。現都免費開源,詳情參見《肝了三天三夜整理出這份36萬字全網最牛的開源高併發程式設計PDF!!》文末附各PDF下載方式。

重磅福利

微信搜一搜【冰河技術】微信公眾號,關注這個有深度的程式設計師,每天閱讀超硬核技術乾貨,公眾號內回覆【PDF】有我準備的一線大廠面試資料和我原創的超硬核PDF技術文件,以及我為大家精心準備的多套簡歷模板(不斷更新中),希望大家都能找到心儀的工作,學習是一條時而鬱鬱寡歡,時而開懷大笑的路,加油。如果你通過努力成功進入到了心儀的公司,一定不要懈怠放鬆,職場成長和新技術學習一樣,不進則退。如果有幸我們江湖再見!

另外,我開源的各個PDF,後續我都會持續更新和維護,感謝大家長期以來對冰河的支援!!

相關文章