mysql性能優化系列9-分庫分表mycat

1. 分庫分表

如果在數據庫中表的數量達到了一定的量級, 則需要進行分表, 分解單表的大數據量對索引査詢帶來的壓力,方便對索引和表結構的變更 。
如果數據庫的吞吐量達到了瓶頸,就需要增加數據庫實例,利用多個數據庫實例來分解大量的數據庫請求帶來的系統壓力。
分庫分表就是將一個表分爲多個表, 這些表可以放在同一個庫裏, 也可以放到不同的庫裏, 甚至可以放在不同的數據庫實例上。
(1)單實例單庫
單庫單表是最常見的數據庫設計,目前大部分的系統都是單庫單表。
(2)多實例單庫
多實例單庫常用於讀寫分離和主備。多個實例之間啓用了複製功能。
(3)多庫(單實例/多實例)
這裏的多庫是將原來單庫的部分表放在一個數據庫,另外一部分放在另外一個數據庫。這些數據庫可以在一個實例,也可以在多個實例上。
(4)多庫多表
多庫多表就是在將不同數據表分部在不同的數據庫基礎上,對同一個表的數據也會拆分放在不同的數據庫。

2. 分庫分表的數據訪問

2.1 客戶端分片

客戶端分片有三種:應用層直接實現、定製JDBC協議實現、定製ORM框架實現。
(1)應用層直接實現
應用層直接決定每次操作應該使用哪個數據庫實例、數據庫及哪個數據庫的表等。這種實現方式會讓數據庫保持的連接比較多。
(2)定製JDBC協議
通過定製JDBC協議來實現,也就是對業務層提供統一的JDBC接口,JDBC內部實現分庫分表。這種需要開發人員理解JDBC協議,Sharding JDBC便採用了這種方案。
(3)定製ORM框架
把分片規則實現放到ORM框架中。

2.2 代理分片

代理分片就是在應用層和數據庫層之間增加一個代理層。代理層對外提供與JDBC兼容的接口,實現JDBC協議的解析,並通過分片的路由規則來路由請求。不過增加了代理層增加了一層網絡傳輸,對性能是有影響的。
代理分片實現的主要框架有Cobar、Mycat、ShardingSphere等。

3. 數據切分方式

3.1 垂直切分

直切分是將單一庫中的表按業務拆分到多個庫或者多個表,甚至分散到不同的實例上。垂直切分除了可以分解單庫單表的壓力, 也可以實現冷熱分離, 因爲對擁有不同活躍度的數據的處理方式不同。對於冷數據査詢較多, 更新較少,這種可以用MyISAM引擎。對於冷數據可以構建多個從庫分解查詢壓力。而熱數據更新比較頻繁,適合使用InnoDB存儲引擎。對於熱數據使用分庫分表分解壓力。
優點:
拆分後業務清晰,拆分規則明確。系統之間進行整合或擴展很容易。便於實現動靜分離、冷熱分離的數據庫表的設計模式。數據維護簡單。
缺點:
無法關聯查詢,只能程序自行解決,提高了系統的複雜度,事務處理複雜。

3.2 水平切分

根據表中數據邏輯關係,將同一個表中的數據按照某種條件拆分到多臺數據庫。每個表中包含一部分數據, 所有表加起來就是全量的數據。
優點:
單庫單表的數據保持在一定的量級,有助於性能的提高。
切分的表的結構相同,應用層改造較少,只需要增加路由規則即可。
提高了系統的穩定性和負載能力 。
缺點:
無法關聯查詢。事務處理複雜,數據擴容的難度和維護量極大。
通常兩種切分方式會同時使用, 垂直切分更偏向於業務拆分, 在技術上我們更關注水平切分的方案。

3.3 分庫分表的問題

(1)擴容
在分庫分表後, 如果需要對集羣進行擴容,這時候 擴容是很麻煩的,因爲路由規則可能發生變化,原有數據需要按照新規則遷移。
(2)查詢間題
分庫分表後,查詢的條件不是分庫分片的鍵值,這時候需要全庫掃描。
(3)跨庫事務
同時更新多個數據庫數據的事務

4. Mycat

Mycat是一個開源的分佈式數據庫系統,實現了MySQL協議,也就是前面說的代理分片,其後端可以用MySQL原生協議或者JDBC和多個MySQL服務器通信,其核心功能是分表分庫下如何和數據庫通信。Mycat目前可以支持MySQL、SQLServer、Oracle、DB2、PostgreSQL、MongoDB等數據庫。
Mycat通過攔截用戶發的SQL語句,對SQL語句進行分析,如分片分析、路由分析、讀寫分離分析、緩存分析等,然後將此SQL發往後端的真實數據庫,並將返回的結果做適當的處理,最終再返回給用戶。

4.1 常見概念

(1)邏輯庫(schema)
數據庫中間件可以被看做是一個或多個數據庫集羣構成的邏輯庫。
(2)邏輯表(table)
分佈式數據庫中,對應用來說讀寫數據的表就是邏輯表。
(3)分片表
分片表就是由於表數據過大進行水平切分到不同數據庫的表。
(4)非分片表
沒有進行數據切分的表
(5)ER表
關係型數據庫是基於實體關係模型(Entity-Relationship Model),通過其描述了真實世界中事物與關係。Mycat中基於此提出了基於E-R關係的數據分片策略,將子表的記錄與所關聯的父表記錄存放在同一個數據分片上,保證數據Join不會跨庫操作。
(6)全局表
一個真實的業務系統中,有些表變動不頻繁,數據量也不大。有時候需要將分片表和這些表進行關聯,Mycat 通過數據冗餘來解決這類表的join,將這些表定義爲全局表,即所有的分片都有一份數據的拷貝。
(7)分片節點(dataNode)
一個大表被分到不同的分片數據庫上面,每個表分片所在的數據庫就是分片節點(dataNode)。
(8)節點主機(dataHost)
每個分片節點(dataNode)不一定都會獨佔一臺機器,同一機器上面可以有多個分片數據庫,這樣一個或多個分片節點(dataNode)所在的機器就是節點主機(dataHost),量將讀寫壓力高的分片節點(dataNode)均衡的放在不同的節點主機(dataHost)。
(9)分片規則(rule)
按照某種業務規則把數據分到某個分片的規則就是分片規則。
(10)全局序列號(sequence)
數據切分後,原有的關係數據庫中的主鍵約束在分佈式條件下將無法使用,因此需要引入外部機制保證數據唯一性標識,這種保證全局性的數據唯一標識的機制就是全局序列號(sequence)

4.2 mycat目錄

(1)bin目錄
存放了啓動腳本,mycat支持命令{console|start|stop|restart|status|dump}。
mycat可通過9066端口進行連接管理。登陸命令:mysql -h主機 -u用戶名 -p密碼 -P9066 [-d邏輯庫]。

  • -h:後面是主機ip
  • -u:後面是server.xml中配置的邏輯庫用戶
  • -p:後面是server.xml中配置的邏輯庫密碼
  • -P:後面是端口默認9066
  • -d:後面是server.xml 中配置的邏輯庫

管理命令:

  • reload @@config:用於不重啓更新配置文件
  • show @@database:顯示MyCAT的數據庫的列表,對應schema.xml配置文件的schema子節點
  • show @@datanode:顯示MyCAT的數據節點的列表,對應schema.xml配置文件的dataNode節點,其中NAME表示dataNode 的名稱,dataHost表示對應dataHost屬性的值即數據主機,ACTIVE表示活躍連接數,IDLE表示閒置連接數,SIZE對應總連接數量
    查找schema下面的dataNode列表命令:
  • show @@datanode where schema = ?
  • show @@version:獲取MyCAT 的版本
  • show @@connection:獲取Mycat的前端連接狀態
  • kill @@connection id:用於殺掉連接。
  • show @@backend:查看後端連接狀態。
  • show @@sql:記錄用戶通過本地8066端口向Mycat-Server發送的SQL
  • show @@sql.slow:慢SQL時間閾值的

(2)conf目錄
conf目錄下存放配置文件,server.xml是Mycat服務器參數調整和用戶授權的配置文件,schema.xml 是邏輯庫定義和表以及分片定義的配置文件,rule.xml是分片規則的配置文件,配置文件修改,需要重啓Mycat 或者通過9066端口reload。
(3)lib目錄
存放mycat依賴的一些jar文件.
(4)log目錄
日誌存放在logs/mycat.log中,每天一個文件,日誌的配置是在conf/log4j.xml中。

4.3 配置文件

4.3.1 schema.xml

Schema.xml管理着MyCat的邏輯庫、表、分片規則、DataNode 以及DataSource。schema 標籤用於定義MyCat 實例中的邏輯庫,MyCat 可以有多個邏輯庫,每個邏輯庫都有自己的相關配置。
(1)schema標籤
schema標籤來劃分不同的邏輯庫。如果不配置schema標籤,所有的表屬於同一個默認的邏輯庫。在查詢不同的邏輯庫中表的時候需要切換到該邏輯庫下纔可以查詢到所需要的表。

	<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="post" dataNode="dnUser1" ruleRequired="false" primaryKey="post_code" />
		<table name="user_list" dataNode="dnUser1,dnUser2,dnUser3" rule="user-mod-long" />
		<table name="user_login" dataNode="dnUser1,dnUser2,dnUser3" rule="prefix-pattern" />
		<table name="area" primaryKey="area_code" type="global" dataNode="dnUser1,dnUser2,dnUser3" />
	</schema>
	<schema name="ORDERDB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="orderlist_buyer" primaryKey="id" dataNode="dnOrder1,dnOrder2"
			   rule="buyer-sharding-by-pattern">
			<childTable name="order_item_buyer" primaryKey="id" joinKey="order_id"
						parentKey="id">
			</childTable>
		</table>
		<table name="orderlist_merchant" primaryKey="id" dataNode="dnOrder1,dnOrder2"
			   rule="merchant-sharding-by-pattern">
			<childTable name="order_item_merchant" primaryKey="id" joinKey="order_id"
						parentKey="id">
			</childTable>
		</table>		
	</schema>

schema標籤屬性:

  • dataNode:邏輯庫所在具體的數據庫
  • checkSQLschema:該值爲true 時,如果我們執行語句select * from USERDB.post;則MyCat會把語句修改爲select * from post。即把表示schema 的字符去掉。但是如果SQL所帶的是並非是schema指定的名字,MyCat並不會刪除改字符,所以SQL語句的最好是不帶這個字段
  • sqlMaxLimit:SQL如果沒有limit,MyCat會自動的加上對應的值

(2)table標籤
Table標籤定義了邏輯表,所有需要拆分的表都需要在這個標籤中定義。同個schema標籤中定義的名稱必須唯一。
table標籤的相關屬性:

  • dataNode:定義這個邏輯表所屬的dataNode, 該屬性的值需要和dataNode標籤中name屬性的值一樣,多個以逗號隔開
  • rule:指定邏輯表要使用的規則,規則名字在rule.xml中定義,必須與tableRule標籤中name屬性一樣
  • ruleRequired:表是否一定要綁定分片規則,如果配置爲true,沒有配置規則程序會報錯
  • primaryKey:邏輯表對應真實表的主鍵。如果分片的規則使用非主鍵,那麼在使用主鍵查詢的時候,就會發送查詢語句到所有配置的DN 上,如果使用該屬性配置真實表的主鍵。MyCat會緩存主鍵與具體DN的信息,那麼再次使用非主鍵進行查詢就會直接發送語句給具體的DN,不會廣播、如果緩存並沒有命中的話,還是會發送語句給具體的DN來獲得數據
  • type:邏輯表的類型,目前邏輯表只有全局表(global)和普通表(不指定)兩種類型
  • autoIncrement:爲true 指定這個表有使用自增長主鍵。mysql對非自增長主鍵,使用last_insert_id()只會返回0。只有定義了自增長主鍵的表纔可以用last_insert_id()返回主鍵值。
    由於insert 操作的時候沒有帶入分片鍵,mycat會先取下這個表對應的全局序列,然後賦值給分片鍵。這樣才能正常的插入到數據庫。如果要使用這個功能最好配合使用數據庫模式的全局序列
  • subTables:分表功能,使用方式添加subTables=“表$1-3”。目前分表1.6 以後開始支持並且dataNode 在分表條件下只能配置一個,分表條件下不支持各種條件的join語句
  • needAddLimit:指定表是否需要自動的在每個語句後面加上limit限制

(3)childTable標籤
用於定義E-R 分片的子表。通過標籤上的屬性與父表進行關聯。配在table標籤裏。

  • name:子表的表名
  • joinKey:插入子表的時候會使用這個列的值查找父表存儲的數據節點。
  • parentKey:關聯父表的列名。程序首先獲取joinkey 的值,再通過parentKey屬性指定的列名產生查詢語句,通過執行該語句得到父表存儲在哪個分片上。從而確定子表存儲的位置。
  • primaryKey:同table標籤
  • needAddLimit:同table標籤

(4)dataNode標籤
定義了MyCat的數據節點,也就是數據分片。一個dataNode標籤就是一個獨立的數據分片。
dataNode標籤屬性:

  • name:定數據節點的名字,必須唯一,在table標籤上使用來建立表與分片對應的關係
  • dataHost:用於定義該分片屬於哪個數據庫實例的,屬性值是引用dataHost 標籤上定義的name屬性
  • database:用於定義該分片上的哪個庫

(5)dataHost標籤
定義了具體的數據庫實例、讀寫分離配置和心跳語句。

  • name:dataHost 標籤名稱,必須唯一
  • maxCon:每個讀寫實例連接池的最大連接。標籤內嵌套的writeHost、readHost 標籤都會使用這個屬性實例化出連接池的最大連接數。
  • minCon:每個讀寫實例連接池的最小連接,初始化連接池的大小。
  • balance:負載均衡類型,0代表不開啓讀寫分離機制,所有讀操作都發送到當前可用的writeHost上。1代表全部的readHost和備用的writeHost參與select語句的負載均衡。2代表所有讀操作隨機的在writeHost、readhost上分發。3代表所有讀請求隨機的分發到wiriterHost對應的readhost 執行,writerHost不負擔讀壓力,這個只在1.4 及其以後版本有
  • writeType:負載均衡類型,0代表寫操作發送到配置的第一個writeHost,第一個宕機後切換到生存的第二個writeHost,重新啓動後以切換後的爲準,切換記錄在配置文件中dnindex.properties中。1代表所有寫操作都隨機的發送到配置的writeHost,1.5 以後廢棄不推薦
  • dbType:指定後端連接的數據庫類型。比如mysql、mongodb、oracle、spark等。
  • dbDriver:連接後端數據庫使用的Driver,目前可選的值有native和JDBC。使用native 的話,因爲這個值執行的是二進制的mysql協議,所以可以使用mysql 和maridb。其他類型的數據庫則需要使用JDBC驅動來支持。需要將符合JDBC4標準的驅動JAR包放到MYCAT\lib 目錄下,並檢查驅動JAR包中包括如下目錄結構的文件:META-INF\services\java.sql.Driver。在這個文件內寫上具體的Driver類名,
  • switchType:-1表示不自動切換,1表示自動切換(默認),2表示基於主從同步的狀態決定是否切換,心跳語句爲show slave status,3表示基於MySQL galary cluster的切換機制(適合集羣),心跳語句爲show status like ‘wsrep%’
  • slaveThreshold:Mycat心跳機制通過檢測show slave status中的"Seconds_Behind_Master", “Slave_IO_Running”,“Slave_SQL_Running” 三個字段來確定當前主從同步的狀態以及Seconds_Behind_Master主從複製時延,當Seconds_Behind_Master>slaveThreshold 時,讀寫分離篩選器會過濾掉此Slave 機器,防止讀到很久之前的舊數據

(6)heartbeat標籤
這個標籤內指明用於和後端數據庫進行心跳檢查的語句
(7)writeHost 和readHost標籤
用來指定後端數據庫的相關配置,writeHost指定寫實例、readHost指定讀實例。
在一個dataHost內可以定義多個writeHost和readHost。但是如果writeHost指定的後端數據庫宕機,那麼這個writeHos 綁定的所有readHost都將不可用。這個writeHost宕機系統會自動的檢測到,並切換到備用的writeHost上去

  • host:用於標識不同實例,一般writeHost使用M1,readHost用S1
  • url:後端實例連接地址,如果是使用native的dbDriver爲address:port 這種形式。用JDBC爲jdbc:mysql://localhost:3306/
  • user:後端存儲實例連接用戶名
  • password:後端存儲實例連接密碼
  • weight:readhost中作爲讀節點的權重(1.4以後)
  • usingDecrypt:是否對密碼加密默認0,1位開啓,同時使用加密程序對密碼加密,加密命令爲:java -cp Mycat-server-1.4.1-dev.jar io.mycat.util.DecryptUtil 1:host:user:password。jia包在mycat的download下載目錄

4.3.2 server.xml

mycat需要的系統配置信息。
(1)user標籤

<user name="test">
<property name="password">test</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
<property name="benchmark">11111</property>
<privileges check="false">
<schema name="TESTDB" dml="0010" showTables="custome/mysql">
<table name="tbl_user" dml="0110"></table>
<table name="tbl_dynamic" dml="1111"></table>
</schema>
</privileges>
</user>

主要用於定義登錄mycat的用戶和權限。

  • Benchmark:mycat連接服務降級處理,benchmark基準,當前端的整體connection數達到基準值時, 對來自該賬戶的請求開始拒絕連接,0 或不設表示不限制

(2)privileges標籤
user標籤子節點。對用戶的schema及下級的table進行精細化的DML權限控制,節點中的check屬性是用於標識是否開啓DML權限檢查,默認false。
(3)system標籤

  • charset:字符集設置
  • processors:用於指定系統可用的線程數,默認值爲機器CPU核心線程數
  • processorBufferChunk:指定每次分配Socket Direct Buffer 的大小,默認是4096 個字節。這個屬性也影響buffer pool的長度
  • processorExecutor:用於指定NIOProcessor上共享的businessExecutor固定線程池大小。mycat在需要處理一些異步邏輯的時候會把任務提交到這個線程池中。新版本中這個連接池的使用頻率不是很大了,可以設置一個較小的值
  • sequnceHandlerType:指定使用Mycat全局序列的類型。0 爲本地文件方式,1 爲數據庫方式,2 爲時間戳序列方式,3 爲分佈式ZK ID生成器,4 爲zk遞增id生成,1.6增加兩種ZK的全局ID生成算法
  • idleTimeout:指定連接的空閒超時時間,默認30 分鐘
  • bindIp:mycat監聽的IP地址,默認值爲0.0.0.0
  • serverPort:定義mycat的使用端口,默認值爲8066
  • managerPort:定義mycat的管理端口,默認值爲9066
  • fakeMySQLVersion:mycat模擬的mysql版本號,默認值爲5.6 版本,目前支持設置5.5、,5.6 版本,其他版本可能會有問題
  • useGlobleTableCheck:全局表一致性檢測,0爲關閉。原理通過在全局表增加_MYCAT_OP_TIME字段來進行一致性檢測,類型爲bigint,create語句通過mycat執行會自動加上這個字段,其他情況請自己手工添加
  • handleDistributedTransactions:分佈式事務開關,0 爲不過濾分佈式事務,1 爲過濾分佈式事務,如果分佈式事務內只涉及全局表,則不過濾),2爲不過濾分佈式事務,但記錄分佈式事務日誌
  • useOffHeapForMerge:1表示使用非堆內存(Direct Memory)處理跨分片結果集的Merge/order by/group by/limit

4.3.3 rule.xml

定義了對錶進行拆分所涉及到的規則定義。
(1)tableRule標籤

  • name:指定唯一的名字,標識不同的表規則

(2)rule標籤
tableRule內子標籤,指定對物理表中的哪一列進行拆分和使用的路由算法。

  • columns:指定要拆分的列名字
  • algorithm:使用function標籤的name屬性。連接表規則和具體路由算法

(3)function標籤

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

4.4 分片規則

(1)主鍵分片vs 非主鍵分片
當沒有任何字段可以作爲分片字段的時候,主鍵分片就是唯一選擇,其優點是按照主鍵的查詢最快。若有某個合適的業務字段比較合適作爲分片字段,則建議採用此業務字段分片,選擇分片字段的條件如下:

  • 儘可能的比較均勻分佈數據到各個節點上
  • 該業務字段是最頻繁的或者最重要的查詢條件
  • 儘量規避跨庫Join

4.4.1 分片枚舉

在配置文件中配置可能的枚舉id,自己配置分片,本規則適用於特定的場景,比如按照省份分區,配置如下:

<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<property name="type">0</property>
<property name="defaultNode">0</property>
</function>

其中mapFile 標識配置文件名稱,type 默認值爲0,0 表示Integer,非零表示String,
所有的節點配置都是從0 開始,0代表節點1
defaultNode默認節點,小於0 表示不設置默認節點,大於等於0 表示設置默認節點。枚舉分片時,如果碰到不識別的枚舉值,就讓它路由到默認節點。

10000=0
10010=1
DEFAULT_NODE=1

4.4.2 固定分片hash算法

本條規則類似於十進制的求模運算,區別在於是二進制的操作,取id的二進制低10 位,即id二進制&1111111111。

<function name="func1" class="io.mycat.route.function.PartitionByLong">
<property name="partitionCount">2,1</property>
<property name="partitionLength">256,512</property>
</function>

其中partitionCount分片個數列表,partitionLength分片範圍列表,最大支持1024個 分區。count,length 兩個數組的長度必須是一致的。
1024 = sum((count[i]*length[i]))。
本例的分區策略:希望將數據水平分成3 份,前兩份各佔25%,第三份佔50%。

4.4.3 範圍約定

此分片適用於提前規劃好分片字段的某個範圍屬於哪個分片,
start <= range <= end.
range start-end ,data node index
K=1000,M=10000.

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
<property name="defaultNode">0</property>
</function>

其中,mapFile 代表配置文件路徑,defaultNode超過範圍後的默認節點。

0-500M=0
500M-1000M=1
1000M-1500M=2

4.4.4 取模

此規則爲對分片字段求摸運算。

<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<property name="count">3</property>
</function>

4.4.5 按日期(天)分片

此規則爲按天分片。

<function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2014-01-01</property>
<property name="sEndDate">2014-01-02</property>
<property name="sPartionDay">10</property>
</function>

其中dateFormat爲日期格式,sBeginDate是開始日期,sEndDate爲結束日期,sPartionDay爲分區天數。

4.4.6 取模範圍約束

此種規則是取模運算與範圍約束的結合。

<function name="sharding-by-pattern" class="io.mycat.route.function.PartitionByPattern">
<property name="patternValue">256</property>
<property name="defaultNode">2</property>
<property name="mapFile">partition-pattern.txt</property>
</function>

其中patternValue 即求模基數,defaoultNode默認節點,mapFile 配置文件路徑。

4.4.7 截取數字做hash 求模範圍約束

此種規則類似於取模範圍約束,支持數據符號字母取模。

<function name="sharding-by-pattern"
class="io.mycat.route.function.PartitionByPrefixPattern">
<property name="patternValue">256</property>
<property name="prefixLength">5</property>
<property name="mapFile">partition-pattern.txt</property>
</function>

其中patternValue即求模基數,prefixLength截取的位數,mapFile 配置文件路徑。
這裏採取的是將列種獲取前prefixLength位列所有ASCII 碼的和進行求模。

4.4.8 截取數字hash解析

此規則是截取字符串中的int 數值hash 分片。

<function name="sharding-by-stringhash"class="io.mycat.route.function.PartitionByString">
<property name="partitionLength">512</property><!-- zero-based -->
<property name="partitionCount">2</property>
<property name="hashSlice">0:2</property>
</function>

其中partitionLength代表字符串hash求模基數,partitionCount分區數,hashSlice是hash預算位,即根據子字符串中int值hash運算。

4.4.9 一致性hash

一致性hash 預算有效解決了分佈式數據的擴容問題。

<function name="murmur" class="io.mycat.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 值與物理節點的映射按行輸出到這個文件,沒有默認值,如果不指定,就不會輸出任何東西-->

一致性哈希

  • 首先求出服務器(節點)的哈希值,並將其配置到0~2的32次方的圓上。
  • 然後採用同樣的方法求出存儲數據的鍵的哈希值,並映射到相同的圓上。
  • 然後從數據映射到的位置開始順時針查找,將數據保存到找到的第一個服務器上

一致性哈希算法在服務節點太少時,容易因爲節點分部不均勻而造成數據傾斜問題。
爲了解決這種數據傾斜問題,一致性哈希算法引入了虛擬節點機制,即對每一個服務節點計算多個哈希,每個計算結果位置都放置一個此服務節點,稱爲虛擬節點。

4.4.10 按單月小時拆分

此規則是單月內按照小時拆分,最小粒度是小時,可以一天最多24個分片,最少1個分片,一個月完後下月從頭開始循環。
每個月月尾,需要手工清理數據。

<function name="sharding-by-hour" class="io.mycat.route.function.LatestMonthPartion">
<property name="splitOneDay">24</property>
</function>

其中splitOneDay爲一天切分的分片數

4.4.11 範圍求模分片

先進行範圍分片計算出歸屬分片組,組內再根據組內分片數量求模。

<function name="rang-mod"
class="io.mycat.route.function.PartitionByRangeMod">
<property name="mapFile">partition-range-mod.txt</property>
<property name="defaultNode">21</property>
</function>

其中mapFile代表配置文件路徑,defaultNode默認節點。
以下配置一個範圍代表一個分片組,=號後面的數字代表該分片組所擁有的分片的數量。

0-200M=5 //代表有5 個分片節點
200M1-400M=1
400M1-600M=4
600M1-800M=4
800M1-1000M=6

4.4.12 日期範圍hash分片

思想與範圍求模一致,當由於日期在取模會有數據集中問題,所以改成hash方法。
先根據日期分組,再根據時間hash使得短期內數據分佈的更均勻。

<function name="range-date-hash"
class="io.mycat.route.function.PartitionByRangeDateHash">
<property name="sBeginDate">2014-01-01 00:00:00</property>
<property name="sPartionDay">3</property>
<property name="dateFormat">yyyy-MM-dd HH:mm:ss</property>
<property name="groupPartionSize">6</property>
</function>

其中sPartionDay代表多少天分一個分片,groupPartionSize代表分片組的大小,例子中分片組共包含天數爲6*3=18天。

4.4.13 自然月分片

按月份列分區,每個自然月一個分片。

<function name="sharding-by-month" class="io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2014-01-01</property>
</function>

其中dateFormat爲日期字符串格式,默認爲yyyy-MM-dd,sBeginDate爲開始日期,sEndDate爲結束日期。

4.4.14 自然月分片應用指定

此規則是在運行階段有應用自主決定路由到那個分片。

<function name="sharding-by-substring"
class="io.mycat.route.function.PartitionDirectBySubString">
<property name="startIndex">0</property><!-- zero-based -->
<property name="size">2</property>
<property name="partitionCount">8</property>
<property name="defaultPartition">0</property>
</function>

配置說明:
此方法爲直接根據字符子串(必須是數字)計算分區號(由應用傳遞參數,顯式指定分區號)。
例如id=05-100000002在此配置中代表根據id中從startIndex=0,開始截取siz=2位數字即05,05就是獲取的分區,如果沒傳默認分配到defaultPartition。

5. mycat架構

在這裏插入圖片描述
Mycat由幾個模塊組成:通信協議、路由解析、結果集處理、數據庫連接、監控等模塊。
(1)通信協議
通信協議模塊承擔底層的收發數據、線程回調處理工作,主要採用Reactor(默認)、proactor模式來提高效率。協議層採用 MySQL協議。
(2)路由解析
路由解析模塊對SQL語句進行語法解析,解析從MySQL協議中解析出來並進入該模塊的SQL語句的條件、語句類型、攜帶的關鍵字等,對符合要求的SQL語句進行相關優化,最後根據這些路由計算單元進行路由計算。
(3)結果集處理
結果集處理對跨分片的結果進行匯聚、排序、截取等
(4)數據庫連接模塊
數據庫連接模塊負責創建、管理、維護後端的連接池。
(5)監控管理
監控管理負責對Mycat中的連接、內存等資源進行監控和管理。
(7)SQL執行模塊
SQL執行模塊負責從連接池中獲取相應的目標連接,對目標連接進行信息同步後,再根據路由解析的結果,把SQL語句分發到相應的節點執行。
主要流程
由通信協議模塊的讀寫事件發起通知。讀寫事件通知具體的回調代碼進行這次讀寫事件的處理。管理模塊的執行流程由定時器事件進行資源檢查和資源釋放時發起。
客戶端發送過來的數據通過協議解析、路由解析等流程進入執行組件。通過執行組件把數據發送到通信協議模塊,最終數據被寫入目標數據庫。
後端數據庫返回數據,通過協議解析後發送至回調模塊。如果是涉及多節點的數據,則執行流程將會先進入結果集匯聚、排序等模塊中,然後將處理後的數據通過通信協議模塊返回到客戶端。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章