在數據切分處理中,特別是水平切分中,中間件最終要的兩個處理過程就是數據的切分、數據的聚合。選擇合適的切分規則,至關重要,因為它決定了後續數據聚合的難易程度,甚至可以避免跨庫的數據聚合處理。
避跨庫 join 的很好的方式,但不是所有的業務場景都適合這樣的規則,因此本文將講述如何選擇合適的切分規則。
如果業務中有些數據類似於數據字典,比如配置文件的配置,常用業務的配置或者數據量不大很少變動的表,這些表往往不是特別大,而且大部分的業務場景都會用到,那麽這種表適合於 Mycat 全局表,無須對數據
進行切分,只要在所有的分片上保存壹份數據即可, Mycat 在 Join 操作中,業務表與全局表進行 Join 聚合會優先選擇相同分片內的全局表 join,避免跨庫 Join,在進行數據插入操作時, mycat 將把數據分發到全局表對應的所有分片執行,在進行數據讀取時候將會隨機獲取壹個節點讀取數據。
目前 Mycat 沒有做全局表的數據壹致性檢查,後續版本 1.4 之後可能會提供全局表壹致性檢查,檢查每個分片的數據壹致性。
全局表的配置如下:
有壹類業務,例如訂單(order)跟訂單明細(order_detail) ,明細表會依賴於訂單,也就是說會存在表的主從關系,這類似業務的切分可以抽象出合適的切分規則,比如根據用戶 ID 切分,其他相關的表都依賴於用戶 ID,再或者根據訂單 ID 切分,總之部分業務總會可以抽象出父子關系的表。這類表適用於 ER 分片表,子表的記錄與所關聯的父表記錄存放在同壹個數據分片上,避免數據 Join 跨庫操作。
以 order 與 order_detail 例子為例, schema.xml 中定義如下的分片配置,order,order_detail 根據 order_id進行數據切分,保證相同 order_id 的數據分到同壹個分片上,在進行數據插入操作時, Mycat 會獲取 order 所在的分片,然後將 order_detail 也插入到 order 所在的分片。
有壹類業務場景是 “主表 A+關系表+主表 B” ,舉例來說就是商戶會員+訂單+商戶,對應這類業務,如何切分?
從會員的角度,如果需要查詢會員購買的訂單,那按照會員進行切分即可,但是如果要查詢商戶當天售出的訂單,那又需要按照商戶做切分,可是如果既要按照會員又要按照商戶切分,幾乎是無法實現,這類業務如何選擇切分規則非常難。目前還暫時無法很好支持這種模式下的 3 個表之間的關聯。目前總的原則是需要從業務角度來看,關系表更偏向哪個表,即“A 的關系” 還是“B 的關系” ,來決定關系表跟從那個方向存儲,未來 Mycat版本中將考慮將中間表進行雙向復制,以實現從 A-關系表 以及 B-關系表的雙向關聯查詢如下圖所示:
當妳沒人任何字段可以作為分片字段的時候,主鍵分片就是唯壹選擇,其優點是按照主鍵的查詢最快,當采用自動增長的序列號作為主鍵時,還能比較均勻的將數據分片在不同的節點上。
若有某個合適的業務字段比較合適作為分片字段,則建議采用此業務字段分片,選擇分片字段的條件如下:
對於非主鍵分片的 table, 填寫屬性 primaryKey,此時 MyCAT 會將妳根據主鍵查詢的 SQL 語句的第壹次執行結果進行分析,確定該 Table 的某個主鍵在什麽分片上,並進行主鍵到分片 ID 的緩存。第二次或後續查詢
mycat 會優先從緩存中查詢是否有 id–>node 即主鍵到分片的映射,如果有直接查詢,通過此種方法提高了非主鍵分片的查詢性能。
通過在配置文件中配置可能的枚舉 id,自己配置分片,本規則適用於特定的場景,比如有些業務需要按照省份或區縣來做保存,而全國省份區縣固定的,這類業務使用本條規則,配置如下:
上面 columns 標識將要分片的表字段, algorithm 分片函數,
其中分片函數配置中, mapFile 標識配置文件名稱, type 默認值為 0, 0 表示 Integer,非零表示 String;
所有的節點配置都是從 0 開始, 0 代表節點 1:
本條規則類似於十進制的求模運算,區別在於是二進制的操作,是取 id 的二進制低 10 位,即 id 二進制&1111111111 。
此算法的優點在於如果按照 10 進制取模運算,在連續插入 1 -10 時候 1 -10 會被分到 1 -10 個分片,增大了插入的事務控制難度,而此算法根據二進制則可能會分到連續的分片,減少插入事務事務控制難度。
配置說明:
上面 columns 標識將要分片的表字段, algorithm 分片函數,partitionCount 分片個數列表, partitionLength 分片範圍列表
分區長度:默認為最大 2^n=1024 ,即最大支持 1024 分區
約 束 :
count,length 兩個數組的長度必須是壹致的。
1024 = sum((count[i] length[i])). count 和 length 兩個向量的點積恒等於 1024
用法例子:
如果需要平均分配設置:平均分為 4 分片, partitionCount partitionLength=1024
此分片適用於,提前規劃好分片字段某個範圍屬於哪個分片,
配置說明:
上面 columns 標識將要分片的表字段,algorithm 分片函數,rang-long 函數中 mapFile 代表配置文件路徑,defaultNode 超過範圍後的默認節點。
所有的節點配置都是從 0 開始,及 0 代表節點 1 ,此配置非常簡單,即預先制定可能的 id 範圍到某個分片:
此規則為對分片字段求摸運算。
配置說明:
上面 columns 標識將要分片的表字段, algorithm 分片函數,
此種配置非常明確即根據 id 進行十進制求模預算,相比固定分片 hash,此種在批量插入時可能存在批量插入單事務插入多數據分片,增大事務壹致性難度。
此規則為按天分片:
配置說明:
columns :標識將要分片的表字段
algorithm :分片函數
dateFormat :日期格式
sBeginDate :開始日期
sEndDate:結束日期
sPartionDay :分區天數,即默認從開始日期算起,分隔 10 天壹個分區
如果配置了 sEndDate 則代表數據達到了這個日期的分片後後循環從開始分片插入。
此種規則是取模運算與範圍約束的結合,主要為了後續數據遷移做準備,即可以自主決定取模後數據的節點分布。
partition-pattern.txt內容如下:
配置說明:
上面 columns 標識將要分片的表字段, algorithm 分片函數,patternValue 即求模基數, defaoultNode默認節點,如果配置了默認,則不會按照求模運算;
mapFile 配置文件路徑:
配置文件中, 1 -32 即代表 id%256 後分布的範圍,如果在 1 -32 則在分區 1 ,其他類推,如果 id 非數據,則會分配在 defaoultNode 默認節點: