版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、架構(gòu)設(shè)計:系統(tǒng)存儲MySQL橫向拆分與業(yè)務(wù)透明化使用MyCat配置橫向拆分之前文章中我們介紹了如何使用MyCat進行讀寫分離,類似的關(guān)系型數(shù)據(jù)庫的讀寫分離存儲方案可以在保持上層業(yè)務(wù)系統(tǒng)透明度的基礎(chǔ)上滿足70%業(yè)務(wù)系統(tǒng)的數(shù)據(jù)承載規(guī)模要求和性能要求。比起單純使用LVS + Replicaion的讀寫分離方案而言最大的優(yōu)勢在于更能增加對上層業(yè)務(wù)系統(tǒng)的透明性。當然如果 您覺得單個MyCat節(jié)點在高可用范疇或者性能范疇上還需要增強,還可以使用Keepalived、LVS等組件在多個MyCat節(jié)點上組成高可用集群或者負載集群。但是這個方案也有一個明顯的問題,那就是它沒有解決數(shù)據(jù)存儲規(guī)模的瓶頸。如果單個節(jié)點
2、上某個單表的數(shù)據(jù)規(guī)模超過了千萬級,那么這個節(jié)點的讀操作也會產(chǎn)生性能瓶頸。所以我們還需要進一步使用MyCat的分片技術(shù)對業(yè)務(wù)數(shù)據(jù)表進行橫向拆分。要說清楚MyCat對橫向拆分的支持,就首先要說清楚關(guān)系型數(shù)據(jù)庫橫向拆分所面臨的主要問題,以及MyCat為了解決這些問題所作的努力。總的來說橫向拆分的所面臨的問題主要分為兩大類,一類是數(shù)據(jù)讀的問題一類是數(shù)據(jù)寫的問題。本節(jié)我們首先分析討論一下數(shù)據(jù)讀的問題,后文中介紹MyCat對分布式事務(wù)的支持時我們再來討論橫向拆分時的數(shù)據(jù)寫問題。4-3-1、數(shù)據(jù)分片中的數(shù)據(jù)讀操作問題select TableA.*,TableB.xname,TableC.xcode from
3、 TableAleft join TableB on TableB.id = TableA.b_codeidleft join TableC on TableC.a_id = TableA.idwhere TableA.groupname = 'XXXX'以上查詢語句是我們在業(yè)務(wù)系統(tǒng)數(shù)據(jù)查詢的過程中經(jīng)常使用的一種查詢類型,是一種多個數(shù)據(jù)表進行左外連接的查詢語句。其中TableA業(yè)務(wù)表擁有大量的數(shù)據(jù)且變化頻率非常高,是需要進行拆分的主要數(shù)據(jù)表;TableB業(yè)務(wù)表可能是一張字典表,雖然它有比較大的數(shù)據(jù),但遠遠沒有達到千萬級別并且變化頻率很低(每天最多有10000次數(shù)據(jù)寫操作);Ta
4、bleC業(yè)務(wù)表中的數(shù)據(jù)量也很大,從技術(shù)角度上說該業(yè)務(wù)表可以做拆分也可以不做拆分,其中的TableC.a_id字段和TableA.id字段也是一種弱關(guān)聯(lián),也就是說TableC中的業(yè)務(wù)數(shù)據(jù)就算沒有關(guān)聯(lián)TableA中的業(yè)務(wù)數(shù)據(jù)也可以相對獨立的工作。當然以上說的是一種可能的業(yè)務(wù)數(shù)據(jù)狀態(tài),實際情況還可能更復(fù)雜。如果這些業(yè)務(wù)表同在一個數(shù)據(jù)庫中,甚至是存在于同一個MySQL實例的不同數(shù)據(jù)庫中,那么執(zhí)行以上查詢語句基本上沒有什么難度,技術(shù)人員使用MySQL的執(zhí)行計劃也可以很清晰的看到查詢語句的執(zhí)行過程:但是如果在分庫狀態(tài)下,那么查詢過程就沒有這么簡單了。首先來說,主要需要進行數(shù)據(jù)拆分處理的TableA中的數(shù)據(jù)
5、分布在不同的數(shù)據(jù)庫中,這些數(shù)據(jù)庫工作在不同的MySQL實例上。另外業(yè)務(wù)表TableC中的數(shù)據(jù)也進行了拆分,但是拆分時并沒有參考和其可能有關(guān)聯(lián)的TableA中的業(yè)務(wù)數(shù)據(jù)存儲分片情況,也就是說原來已有的關(guān)聯(lián)在拆分存儲后可能就消失了,而且即使拆分后的數(shù)據(jù)關(guān)聯(lián)還存在,但拆分前和拆分后執(zhí)行數(shù)據(jù)排序操作的結(jié)構(gòu)也可能是不同的。至于字典表TableB,由于可預(yù)見的時間內(nèi)數(shù)據(jù)總規(guī)模不大,所以可以不進行拆分所有拆分后的數(shù)據(jù)庫中TableB數(shù)據(jù)表的數(shù)據(jù)內(nèi)容完全一樣。下圖展示了一種數(shù)據(jù)表中數(shù)據(jù)進行隨機拆分后可能的存儲結(jié)構(gòu)和產(chǎn)生的問題:這樣來看,數(shù)據(jù)表橫向拆分過程中至少需要考慮以下讀操作問題:橫向拆分后數(shù)據(jù)表之間的邏輯
6、關(guān)聯(lián)問題:數(shù)據(jù)表間存在各種關(guān)聯(lián),有的關(guān)聯(lián)甚至還存在外鍵約束。數(shù)據(jù)拆分后的關(guān)聯(lián)關(guān)系應(yīng)該和拆分前的關(guān)聯(lián)關(guān)系保持一致,至少應(yīng)該保證通過數(shù)據(jù)庫中間件查詢得到的數(shù)據(jù)關(guān)聯(lián)結(jié)果和拆分前的關(guān)聯(lián)結(jié)果保持一致。橫向拆分后數(shù)據(jù)的排序和分頁問題:由于數(shù)據(jù)拆分后,排序動作會分別在各個拆分后的數(shù)據(jù)庫中單獨執(zhí)行,這可能就會導(dǎo)致拆分后的排序和分頁結(jié)果和拆分前的結(jié)果不一致。那么數(shù)據(jù)庫中間件需要保證能夠?qū)⑦@些結(jié)果集合進行整合并還原成拆分前的排序和分頁結(jié)果。橫向拆分后數(shù)據(jù)的分組操作問題:分組和統(tǒng)計操作同樣存在和以上描述類似的問題,各個拆分后的數(shù)據(jù)庫將單獨執(zhí)行分組和統(tǒng)計,這就可能導(dǎo)致用一個分區(qū)條件在各個拆分數(shù)據(jù)庫中都有分組和統(tǒng)計結(jié)果
7、。數(shù)據(jù)庫中間件還是需要保證能夠合并這些分組統(tǒng)計結(jié)果,并保證它們和拆分前的數(shù)據(jù)庫操作結(jié)果一致。4-3-2、全局表在數(shù)據(jù)庫的橫向拆分過程中,各種數(shù)據(jù)字典表基本上不需要進行拆分。這是因為這些數(shù)據(jù)表的數(shù)據(jù)規(guī)模都不會太大且變化頻率較低,另外一個原因是減少橫向拆分后表關(guān)聯(lián)操作的難度。類似省市縣信息、手機區(qū)號信息、功能菜單信息等數(shù)據(jù)都應(yīng)算作字典數(shù)據(jù)。根據(jù)實際工作經(jīng)驗,并不會出現(xiàn)所有業(yè)務(wù)表的數(shù)據(jù)規(guī)模都達到或超過千萬級規(guī)模,只有部分關(guān)鍵業(yè)務(wù)表的數(shù)據(jù)規(guī)模會出現(xiàn)這樣的情況,基于這樣的情況只有這些業(yè)務(wù)表和與它們直接關(guān)聯(lián)的部分數(shù)據(jù)表需要進行數(shù)據(jù)拆分設(shè)計。MyCat數(shù)據(jù)庫中間件中為除了以上情況外,各個不需要進行數(shù)據(jù)拆分的
8、數(shù)據(jù)表提供了一種冗余復(fù)制方案:全局表。如果一張業(yè)務(wù)表在schema.xml配置文件配設(shè)置成了全局表,那么MyCat將在涉及這張業(yè)務(wù)表的所有分片節(jié)點上保持這張數(shù)居表中數(shù)據(jù)完全一致。Mycat在Join操作中,業(yè)務(wù)表與全局表進行Join聚合會優(yōu)先選擇相同分片內(nèi)的全局表join,避免跨庫 Join;在進行數(shù)據(jù)插入操作時,MyCat將把數(shù)據(jù)分發(fā)到全局表對應(yīng)的所有分片執(zhí)行,在進行數(shù)據(jù)讀取時候?qū)S機獲取一個節(jié)點讀取數(shù)據(jù)。schema.xml配置文件中的全局表配置類似如下:.<schema .> # 請注意這里的type屬性,屬性值為“global”,代表全局表 # 這樣,在dn1和dn2兩個
9、分片節(jié)點中的t_area業(yè)務(wù)表中,其數(shù)據(jù)將保持完全一致。 <table name="t_area" primaryKey="id" type="global" dataNode="dn1,dn2" /></schema>.分片表為了在表關(guān)聯(lián)查詢性能和表關(guān)聯(lián)處理難易程度之間取得平衡,MyCat提供了兩種分片表類型和多種分片規(guī)則。對于業(yè)務(wù)關(guān)聯(lián)較為獨立的需要進行數(shù)據(jù)分片的業(yè)務(wù)表可以采用普通分片。然而有一類情況是,需要進行數(shù)據(jù)分片的業(yè)務(wù)表有一些非常重要的關(guān)聯(lián)數(shù)據(jù)也同時需要進行分片,例如訂單(orde
10、r)數(shù)據(jù)表和訂單明細(order_detail)數(shù)據(jù)表。很明顯訂單數(shù)據(jù)和訂單明細數(shù)據(jù)是經(jīng)常需要進行關(guān)聯(lián)查詢的,并且既然訂單數(shù)據(jù)達到了一定的規(guī)模需要進行數(shù)據(jù)分片,那么只會比它數(shù)據(jù)量更大的訂單明細表也同時需要進行分片。在這樣的關(guān)聯(lián)分片情況下,MyCat需要保證訂單明細A1、A2、A3、A4數(shù)據(jù)能夠正確的寫入到他們關(guān)聯(lián)的訂單信息A所在的分片上。這樣才能保證訂單A在join查詢訂單明細時,向請求者返回正確的查詢結(jié)果。MyCat提供的這種分片模式稱為ER分片/智能分片。在后續(xù)4-4、4-5和4-6節(jié)中,本文將和讀者一起來討論MyCat中支持數(shù)據(jù)分片的兩種關(guān)鍵分片表類型,普通分片和智能分片。我們還會一起討
11、論MyCat中主要支持的數(shù)據(jù)分片規(guī)則,包括mod-long、partbymonth、rang-mod、rang-long、hash-int等分片規(guī)則。MyCat還支持開發(fā)人員自定義分片規(guī)則,這個自定義方式也會進行介紹。4-3-4、Share join和catlet(人工智能)MyCat還向技術(shù)人員提供了兩種不同分片的查詢匯總功能,其中Share join是一個簡單的跨分片Join方式,目前支持 2 個表的 join,原理就是解析 SQL 語句,拆分成單表的 SQL 語句執(zhí)行,然后把各個節(jié)點的數(shù)據(jù)匯 集;另外一種catlet人工智能分片查詢功能,是將Join查詢語句分析后,從指定分片提取查詢結(jié)果
12、的前半部分,然后將查詢結(jié)果送入其它分片以便可以結(jié)合到這個結(jié)果所關(guān)聯(lián)的其他數(shù)據(jù)。Share join查詢的做法和人工智能分片查詢的做法往往無法實現(xiàn)高性能處理,所以這兩種不同分片的數(shù)據(jù)關(guān)聯(lián)查詢方式只適合開發(fā)人員使用,不建議在生產(chǎn)環(huán)境中使用。4-4、普通分片場景示例數(shù)據(jù)表普通分片是比較好理解的概念,即是說一個擁有相對獨立業(yè)務(wù)的數(shù)據(jù)表,按照一定的拆分規(guī)則將數(shù)據(jù)分別存儲在若干個獨立的數(shù)據(jù)庫中的操作。能夠進行這種分片操作的數(shù)據(jù)表的特點是,業(yè)務(wù)耦合度一般較低或者屬于基礎(chǔ)性功能模塊;這種數(shù)據(jù)表也可能存在和其它數(shù)據(jù)的關(guān)聯(lián),但是關(guān)聯(lián)的是一個或者多個字典數(shù)據(jù)表;即使這種數(shù)據(jù)表存在直接關(guān)聯(lián)的其它業(yè)務(wù)數(shù)據(jù),那么后者的數(shù)
13、據(jù)規(guī)模和變化頻率也不會在可預(yù)見的時間內(nèi)進行數(shù)據(jù)分片操作。這種場景在實際業(yè)務(wù)中是比較常見的,典型的就是用戶基礎(chǔ)信息:在產(chǎn)品第N次迭代時,考慮了后續(xù)幾個月內(nèi)注冊用戶量將突破1000萬大關(guān),且半年內(nèi)將繼續(xù)成幾何級增長。這時架構(gòu)師就必須考慮對“用戶中心子系統(tǒng)”中用戶基本信息進行分庫處理。用戶基本信息快速遷移/割接的問題很好解決,由于目前用戶基本信息只有百萬左右,所以可以考慮在每個分片庫先做整體冗余,然后再后續(xù)運維工作中再進行數(shù)據(jù)清掃。也可以在最初階段就考慮合適的分片規(guī)則,保證這幾百萬數(shù)據(jù)在后續(xù)存儲方案升級中將可以作為整個MySQL分庫分表集群的第一個分片節(jié)點組(后文在講解分片規(guī)則時會詳細講到)“用戶中
14、心子系統(tǒng)”中我們?yōu)榭赡艿?000萬用戶數(shù)據(jù)規(guī)模規(guī)劃了5個分片,每個分片中做兩組讀寫分離,每組讀寫分離包含一個寫節(jié)點和二至三個讀節(jié)點。并且這兩個組的寫節(jié)點互為主從。以下是schema.xml主配置文件中重要的設(shè)置內(nèi)容:<mycat:schema xmlns:mycat="http:/io.mycat/"> <!- 在這個測試示例中一共有三張邏輯表 -> <schema name="usercenterSchema" checkSQLschema="false" sqlMaxLimit="200&q
15、uot;> <!- 以下是若干張不需要進行數(shù)據(jù)分片的字典性質(zhì)的數(shù)據(jù)表 它們都以全局表的形式在每個分片節(jié)點上擁有完全一致的數(shù)據(jù) -> <table name="dictionaryA" primaryKey="Id" type="global" dataNode="dn1,dn2,dn3,dn4,dn5" /> <table name="dictionaryB" primaryKey="Id" type="global"
16、dataNode="dn1,dn2,dn3,dn4,dn5" /> <table name="dictionaryC" primaryKey="Id" type="global" dataNode="dn1,dn2,dn3,dn4,dn5" /> <table name="dictionaryD" primaryKey="Id" type="global" dataNode="dn1,dn2,dn3,d
17、n4,dn5" /> <!- 這是在本示例中我們需要進行分片的用戶基本信息數(shù)據(jù)表 -> <table name="usertable" primaryKey="Id" dataNode="dn1,dn2,dn3,dn4,dn5" rule="mod-long"/> </schema> <!- 設(shè)置五個邏輯節(jié)點/分片節(jié)點 這里注意一個問題,如果為了節(jié)約成本可以將某兩個或者某幾個邏輯節(jié)點 運行在相同的MySQL物理機群上,那么建議database屬性取不同的名字
18、 例如stacks01、stacks02、stacks03. -> <dataNode name="dn1" dataHost="dataHost1" database="stacks" /> <dataNode name="dn2" dataHost="dataHost2" database="stacks" /> <dataNode name="dn3" dataHost="dataHost3"
19、database="stacks" /> <dataNode name="dn4" dataHost="dataHost4" database="stacks" /> <dataNode name="dn5" dataHost="dataHost5" database="stacks" /> <!- 第一個分片節(jié)點中定義了兩個寫操作節(jié)點和其對應(yīng)的讀操作節(jié)點, writeType設(shè)置為0,表示一般情況下所有寫操作都發(fā)送到配
20、置的第一個寫節(jié)點上, 另一個寫節(jié)點和讀節(jié)點充當standby的角色。 -> <dataHost name="dataHost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="2"> <heartbeat>select user()</heartbeat&
21、gt; <writeHost host="dataHost1_hostM1" url="40:3306" user="root" password="123456"> <readHost host="dataHost1_hostS11" url="41:3306" user="root" password="123456"/> <readHost host=&
22、quot;dataHost1_hostS12" url="42:3306" user="root" password="123456"/> </writeHost> <writeHost host="dataHost1_hostM2" url="50:3306" user="root" password="123456"> <readHost host="
23、;dataHost1_hostS21" url="51:3306" user="root" password="123456"/> <readHost host="dataHost1_hostS22" url="52:3306" user="root" password="123456"/> </writeHost> </dataHost> .</my
24、cat:schema>以上配置示例中關(guān)于分片規(guī)則的部分(table標簽的rule屬性),我們將在后文中專門進行介紹。讀者在這里只需要知道“mod-long”是一種長整形取余的分片方式就可以了,另外全局表和分片表唯一的設(shè)置差別就是全局表需要明確指定type屬性,而分片表不需要。很明顯至少從現(xiàn)在的情況看,用戶基本信息雖然有直接關(guān)聯(lián)的數(shù)據(jù)信息,但是關(guān)聯(lián)的都是字典性質(zhì)的數(shù)據(jù)表,這些數(shù)據(jù)表都被設(shè)置為全局表,所以在任何分片中用戶基本信息都可以找到與它正確關(guān)聯(lián)的信息。最后需要再次注意的MyCat并不負責數(shù)據(jù)同步過程,所以所有節(jié)點的數(shù)據(jù)同步還需要技術(shù)人員根據(jù)頂層設(shè)計自行配置。4-5、ER分片及使用限制4
25、-5-1、ER分片基本使用經(jīng)過上一節(jié)示例的技術(shù)迭代過程,為不久的將來線上業(yè)務(wù)系統(tǒng)達到5000萬級別用戶基本信息的數(shù)據(jù)存儲規(guī)模的準備工作就完成了,但是新的要求又來了:我們需要記錄最近一年時間內(nèi)用戶對基本信息的修改情況。這部分修改情況可能來源于另一套日志采集系統(tǒng)(例如一套基于Apache Flume + Apache Kafka + Apache Storm的日志數(shù)據(jù)實時采集分析平臺)也可能直接來源于業(yè)務(wù)系統(tǒng)對數(shù)據(jù)變化的判斷,這里我們并不討論數(shù)據(jù)的來源問題,而只討論這部分用戶基本信息變化數(shù)據(jù)的存儲情況假設(shè)技術(shù)團隊已經(jīng)決定使用關(guān)系型數(shù)據(jù)庫存儲這些變化數(shù)據(jù)。很顯然用戶基本信息的修改明細和用戶基本信息存
26、在很強的關(guān)聯(lián)關(guān)系,且用戶基本信息的修改明細也需要進行分片。當用戶基本信息A進入分片數(shù)據(jù)庫X時,需要和這個用戶基本信息進行關(guān)聯(lián)的修改明細信息也必須正確進入數(shù)據(jù)庫X,這樣才能保持數(shù)據(jù)關(guān)聯(lián)的正確性。這是因為:如果數(shù)據(jù)表存在外鍵約束設(shè)定,那么用戶信息修改明細錯誤寫入分片時就會導(dǎo)致寫操作直接報錯分片數(shù)據(jù)庫無法找到關(guān)聯(lián)的用戶信息。而使用外鍵約束又是明確被建議的數(shù)據(jù)庫設(shè)計方式。即使數(shù)據(jù)表不存在外鍵約束設(shè)定,雖然用戶信息修改明細可以寫入和用戶基本信息不一致的分片,但是在基于用戶基本信息進行關(guān)聯(lián)查詢時就無法查詢到正確的關(guān)聯(lián)信息??磥硪诒3中阅艿那疤嵯陆鉀Q這個問題,就必須保證父級表和子級表在同時需要分片時,相關(guān)
27、聯(lián)數(shù)據(jù)能夠正確寫入相同的分片中,MyCat稱這樣的分片表為ER分片表。MyCat的主配置文件中使用table標簽的子標簽childTable對ER分片表的關(guān)系進行標識。如下示例:.<table name="usertable" primaryKey="Id" dataNode="dn1,dn2" rule="mod-long"> <childTable name="booktable" primaryKey="Id" joinKey="author
28、id" parentKey="Id"/></table>.關(guān)于table標簽已經(jīng)在上文中介紹過了,這里的使用方式相似。需要注意的是childTable標簽的幾個關(guān)鍵屬性:primaryKey屬性:該屬性和table標簽中的primaryKey屬性意義相同,表示該邏輯表對應(yīng)真實表的主鍵。joinKey屬性和parentKey屬性:在進行childTable表數(shù)據(jù)插入時,MyCat會首先依據(jù)joinKey屬性設(shè)置的字段拿到本次數(shù)據(jù)插入時該字段的值,然后再根據(jù)parentKey屬性指定的父級Table的列信息生成查詢語句,以便確定將要插入的這條數(shù)據(jù),其
29、父級數(shù)據(jù)在哪個分片上。有的讀者可能就要提問了:為什么不采用已設(shè)置的分片規(guī)則重新計算出數(shù)據(jù)存放的分片呢?這是因為分片規(guī)則可能會產(chǎn)生變化,即使分片規(guī)則沒有產(chǎn)生變化,很多規(guī)則下作為計算基準的“可用分片數(shù)量”也可能產(chǎn)生了變化。了解了ER分片表的基本工作方式,我們就可以對上一節(jié)用戶中心使用的普通分片場景進行調(diào)整,在其為用戶基本信息修改明細配置ER分片關(guān)系,調(diào)整后的配置文件如下所示(只列出了關(guān)鍵的變化位置,其他全局表的設(shè)置沒有變化):.<!- 原來的全局表設(shè)置還是沒有變 -><table name="dictionaryD" primaryKey="Id&q
30、uot; type="global" dataNode="dn1,dn2,dn3,dn4,dn5" /><!- 這是在本示例中我們需要進行分片的用戶基本信息數(shù)據(jù)表-><table name="usertable" primaryKey="Id" dataNode="dn1,dn2,dn3,dn4,dn5" rule="mod-long"> <!- 用戶基本信息修改明細 -> <childTable name="user
31、modifyDetails" primaryKey="Id" joinKey="userid" parentKey="Id"/></table>.請注意,我們并沒有為childTable設(shè)置分片規(guī)則和可以使用的分片節(jié)點,這是因為childTable每一條數(shù)據(jù)存儲的位置是由它父級Table表中每一條數(shù)據(jù)的實際存儲位置決定。通過ER分片我們可以保證類似如下的join關(guān)聯(lián)語句能夠在每個分片中正確執(zhí)行,并被匯總到MyCat服務(wù)上。這是MyCat服務(wù)對這些分片結(jié)果進行正確的二次整合的前提條件。# 無論是這兩張數(shù)據(jù)表做
32、怎樣的join關(guān)聯(lián),都可以保證沒個分片中的查詢結(jié)果是正確的。# 如以下這種查詢方法select usertable.*,usermodifyDetails.fieldname,usermodifyDetails.fieldnewValue from usertableleft join usermodifyDetails on usertable.Id = usermodifyDetails.userid# 或者這種查詢方法,又或者其它的只涉及這兩個數(shù)據(jù)表的一對多、多對一關(guān)聯(lián)查詢select usermodifyDetails.*,usertable.Id,usertable.username
33、 from usermodifyDetailsleft join usertable on usertable.Id = usermodifyDetails.userid主要分片規(guī)則上文提到MyCat的邏輯表支持多種分片規(guī)則,表現(xiàn)于schema配置文件中中table標簽的rule屬性。本節(jié)將以MyCat Version 1.6版為基礎(chǔ),介紹幾種經(jīng)常使用的分片規(guī)則,這些分片規(guī)則都通過rule.xml文件進行定義和配置。4-6-1、分片枚舉sharding-by-intfile.<tableRule name="sharding-by-intfile"> <r
34、ule> <!- columns表示分片計算時的取值列,記得設(shè)置成您的數(shù)據(jù)表列名 -> <columns>sharding_id</columns> <algorithm>hash-int</algorithm> </rule></tableRule>.<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="
35、mapFile">partition-hash-int.txt</property></function>.實現(xiàn)類io.mycat.route.function.PartitionByFileMap,這個分片規(guī)則是直接按照partition-hash-int.txt文件(默認)中定義的固定分片規(guī)則進行分片。其中可以設(shè)置的屬性包括:type:這個分片規(guī)則也不支持按照字符串為分片依據(jù),當type屬性的值為0時表示Integer,非零表示String,默認的屬性值為0。defaultNode:從MyCat Version 1.6版本開始,rule.xml配置文
36、件中就不再設(shè)置默認分片節(jié)點了。但是這個屬性還是存在的,如果碰到不識別的枚舉值,就讓它路由到默認節(jié)點;如果不配置默認節(jié)點(defaultNode值小于0表示不配置默認節(jié)點),碰到不識別的枚舉值就會報錯:like this:cant find datanode for sharding column:column_name val:ffffffff。mapFile:固定枚舉分片所設(shè)置的枚舉規(guī)則存儲的文件,默認的文件名就是partition-hash-int.txt,并且和rule.xml文件在一個工作目錄下。partition-hash-int.txt文件的定義類似如下:# 如果取值列的值為100
37、00則將數(shù)據(jù)送入0號分片10000=010010=1我們來跟蹤一下PartitionByFileMap類的源碼,會發(fā)現(xiàn)這個分片規(guī)則工作很簡單簡單有它的好處,不會在分片過程中浪費太多的計算時間計算分片目標:.public class PartitionByFileMap extends AbstractPartionAlgorithm implements RuleAlgorithm . / 默認節(jié)點在map中的key private static final String DEFAULT_NODE = "DEFAULT_NODE" / 在配置文件的配置規(guī)則會被初始化到app
38、2Partition對象中 / 這個Map對象的value表示分片節(jié)點編號從0開始編號 private Map<Object, Integer> app2Partition; . public Integer calculate(String columnValue) / columnValue既是當前將要進行的數(shù)據(jù)分片所取的列值 Object value = columnValue; / 如果配置文件設(shè)置了type為0,則需要將值轉(zhuǎn)為數(shù)字 if(type = 0) value = Integer.valueOf(columnValue); Integer rst = null;
39、/ 取得關(guān)聯(lián)的分片,從app2Partition對象中 / 注意,這個地方的變量命名可能會使閱讀者產(chǎn)生歧義 / 實際上這value對象代表了app2Partition中的key信息。 Integer pid = app2Partition.get(value); if (pid != null) rst = pid; / 如果沒有取到對應(yīng)的分片,則試圖取默認分片 else rst =app2Partition.get(DEFAULT_NODE); return rst; .4-6-2、取模的分片方式:mod-long.<tableRule name="mod-long"
40、;> <rule> <!- columns表示分片計算時的取值列,記得設(shè)置成您的數(shù)據(jù)表列名 -> <columns>id</columns> <algorithm>mod-long</algorithm> </rule></tableRule>.<function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!- how many ata nodes
41、-> <property name="count">2</property></function>.實現(xiàn)類:io.mycat.route.function.PartitionByMod,這個分片規(guī)則只適合數(shù)字形式的列,并且規(guī)則的實現(xiàn)更簡單:既是按照將要插入數(shù)據(jù)的指定列進行取模運算。該規(guī)則需要設(shè)置一個count屬性,這個數(shù)據(jù)就是現(xiàn)存的分片節(jié)點的個數(shù)用于進行取模運算的基數(shù):.public class PartionByMod extends AbstractPartionAlgorithm implements RuleAlgorith
42、m . # 該屬性設(shè)置當前的分片節(jié)點數(shù)量 private int count; . public Integer calculate(String columnValue) # 取絕對值 BigInteger bigNum = new BigInteger(columnValue).abs(); # 返回取模運算的值 # 如果您不清楚BigInteger類型的特性,請自行查閱資料 return (bigNum.mod(BigInteger.valueOf(count).intValue(); .4-6-3、約定數(shù)字范圍auto-sharding-long.<tableRule name=
43、"auto-sharding-long"> <rule> <!- columns表示分片計算時的取值列,記得設(shè)置成您的數(shù)據(jù)表列名 -> <columns>id</columns> <algorithm>rang-long</algorithm> </rule></tableRule>.<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong&
44、quot;> <property name="mapFile">autopartition-long.txt</property></function>.實現(xiàn)類:io.mycat.route.function.AutoPartitionByLong,這個規(guī)則下MyCat會使用autopartition-long.txt文件(默認的文件路徑)中已經(jīng)設(shè)置好的數(shù)字范圍決定將數(shù)據(jù)存儲到哪個分片中,autopartition-long.txt文件中的配置類似如下:# 這個配置文件的含義是# 指定分片列的數(shù)值為05000000的數(shù)據(jù)都在0號分片
45、中0-500M=0# 指定分片列的數(shù)值為500000010000000的數(shù)據(jù)都在1號分片中500M-1000M=11000M-1500M=2如果您的業(yè)務(wù)系統(tǒng)后續(xù)考慮方便的增加分片節(jié)點,可以考慮優(yōu)先使用這種分片規(guī)則,因為這種固定設(shè)置的分片規(guī)則既簡單又實用。以下是AutoPartitionByLong類的重要判斷代碼,通過查看代碼中主要的分片過程,有助于我們理解這種分片規(guī)則:.public class AutoPartitionByLong extends AbstractPartionAlgorithm implements RuleAlgorithm private String mapFil
46、e; / defaultNode設(shè)置為-1,表示沒有默認的分片節(jié)點。 private int defaultNode = -1; . / longRongs在初始化時被設(shè)置 / 在autopartition-long.txt文件中有幾行設(shè)置范圍,就有幾個LongRange對象。(參見該類中沒有列出的initialize方法) private LongRange longRongs; . public Integer calculate(String columnValue) long value = Long.valueOf(columnValue); Integer rst = null;
47、for (LongRange longRang : this.longRongs) / 如果條件成立,就說明找到了可以承載columnValue值的那個數(shù)據(jù)庫分片編號 if (value <= longRang.valueEnd && value >= longRang.valueStart) return longRang.nodeIndx; /數(shù)據(jù)超過范圍,暫時使用配置的默認節(jié)點(如果有的話) if(rst =null && defaultNode >= 0) return defaultNode; / 返回null,則說明沒有找到可承載c
48、olumnValue的分片編號 / 也沒有進行默認分片的設(shè)置(這是MyCat會報錯) return rst; . / LongRange對象有三個屬性: static class LongRange / 該屬性為當前范圍所存儲的分片編號 public final int nodeIndx; / 該屬性為范圍的開始值 public final long valueStart; / 該屬性為范圍的結(jié)束值 public final long valueEnd; . .注意,在以上代碼片段的注釋中有一句“暫時使用配置的默認節(jié)點”。這句話不是筆者的注釋,而是該類的編寫者“wuzhi”加的注釋,也就是說這
49、里判斷成立后的處理代碼可能會在后續(xù)版本中進行修改。4-6-4、自然月分片:sharding-by-month.<tableRule name="sharding-by-month"> <rule> <!- columns屬性同樣表示分片計算時的取值列,記得設(shè)置成您的數(shù)據(jù)表列名 -> <columns>create_date</columns> <algorithm>partbymonth</algorithm> </rule></tableRule>.<func
50、tion name="partbymonth" class="io.mycat.route.function.PartitionByMonth"> <property name="dateFormat">yyyy-MM-dd</property> <property name="sBeginDate">2015-01-01</property></function>.實現(xiàn)類io.mycat.route.function.PartitionByMont
51、h,該分片規(guī)則可按照每個自然月為一個分片數(shù)據(jù)庫,也就是說技術(shù)團隊可以將數(shù)據(jù)放置到分片數(shù)據(jù)庫中,并且每個月增加一個分片數(shù)據(jù)庫,而不對之前的分片數(shù)據(jù)庫產(chǎn)生影響。該規(guī)則有三個屬性可以設(shè)置:dateFormat:日期數(shù)據(jù)列的數(shù)據(jù)格式。該屬性必須要設(shè)置,否則分區(qū)規(guī)則將無法進行正常工作。默認的配置文件中,這個數(shù)據(jù)都存在默認值,就是以上示例中看到的yyyy-MM-dd。sBeginDate:這個屬性是指存儲的數(shù)據(jù)中,涉及的分區(qū)日期列的開始時間。sEndDate:這個屬性是指存儲的數(shù)據(jù)中,涉及的分區(qū)日期列的結(jié)束時間,該值可以不進行設(shè)置。實際上設(shè)置sEndDate和不設(shè)置sEndDate,PartitionBy
52、Month將按照兩種不同的方式工作,詳見下文代碼分析。.public class PartitionByMonth extends AbstractPartitionAlgorithm implements RuleAlgorithm . / 以下三個屬性就是技術(shù)人員在配置文件中設(shè)置的屬性 private String sBeginDate; private String dateFormat; private String sEndDate; / 日期計算對象,專門用于根據(jù)設(shè)置開始事件和結(jié)束時間參與分片計算 private Calendar beginDate; private Calend
53、ar endDate; / 這個參數(shù)很重要,分區(qū)總數(shù),后面的代碼分析中會進行講述 private int nPartition; . public void init() . / 關(guān)鍵點在這里,當技術(shù)人員設(shè)置了sEndDate的值后 / 該規(guī)則將計算一個nPartition的參數(shù)值 if(sEndDate!=null&&!sEndDate.equals("") endDate = Calendar.getInstance(); endDate.setTime(new SimpleDateFormat(dateFormat).parse(sEndDate);
54、/ nPartition 為結(jié)束時間和開始時間的年差 * 12 / 加上結(jié)束時間和開始時間的月差 最后再 + 1 / 如果結(jié)束時間為2016-05,開始時間為2015-08則: / 12 + 7 - 4 + 1 = 16個月 nPartition = (endDate.get(Calendar.YEAR) - beginDate.get(Calendar.YEAR) * 12 + endDate.get(Calendar.MONTH) - beginDate.get(Calendar.MONTH) + 1; / nPartition出現(xiàn)小于0的情況,則說明開始時間和結(jié)束時間的設(shè)置錯誤。 if
55、(nPartition <= 0) throw new java.lang.IllegalArgumentException("Incorrect time range for month partitioning!"); / 如果沒有設(shè)置結(jié)束時間,則nPartition為-1。 else nPartition = -1; . / 正式的分片計算 public Integer calculate(String columnValue) try int targetPartition; Calendar curTime = Calendar.getInstance();
56、 curTime.setTime(formatter.get().parse(columnValue); / 目標分片的計算方式為: / 當前時間和開始時間的年差 * 12 / 加上當前時間和開始時間的月差 / 如果開始時間為2015-08,當前時間為2015-12則: / 0 + 11 - 7 = 4,也就是第五個分片庫 targetPartition = (curTime.get(Calendar.YEAR) - beginDate.get(Calendar.YEAR) * 12 + curTime.get(Calendar.MONTH) - beginDate.get(Calendar.
57、MONTH); / 如果設(shè)置了結(jié)束時間,說明分片數(shù)量是有限制的,需要在reCalculatePartition方法中,基于targetPartition進行取余運算 if (nPartition > 0) targetPartition = reCalculatePartition(targetPartition); return targetPartition; catch (ParseException e) throw new IllegalArgumentException(new StringBuilder().append("columnValue:").append(columnValue).append(" Please chec
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 石河子大學(xué)《園林設(shè)計初步》2022-2023學(xué)年第一學(xué)期期末試卷
- 門衛(wèi)室施工組織設(shè)計方案
- 石河子大學(xué)《水利工程監(jiān)理》2023-2024學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《臨床技能學(xué)二》2021-2022學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《工業(yè)制劑綜合實驗》2022-2023學(xué)年第一學(xué)期期末試卷
- 沈陽理工大學(xué)《數(shù)字信號處理》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽理工大學(xué)《面向?qū)ο蟪绦蛟O(shè)計(C++)》2022-2023學(xué)年期末試卷
- 沈陽理工大學(xué)《翻譯技能綜合訓(xùn)練》2022-2023學(xué)年第一學(xué)期期末試卷
- 沈陽理工大學(xué)《車輛振動與噪聲控制》2023-2024學(xué)年期末試卷
- 沈陽理工大學(xué)《包裝設(shè)計》2023-2024學(xué)年第一學(xué)期期末試卷
- 收銀審核員考試:收銀員試題及答案(三)
- 土地復(fù)墾施工組織設(shè)計58446
- 急性胰腺炎的診斷與處理:國內(nèi)外主要指南的比較與解讀
- 電大財務(wù)大數(shù)據(jù)分析編程作業(yè)5
- (正式版)HGT 2782-2024 化工催化劑顆??箟核榱Φ臏y定
- 小學(xué)科普社團活動方案
- DG-TJ08-2413-2023 優(yōu).秀歷史建筑外墻修繕技術(shù)標準
- 家用光伏發(fā)電儲能裝置的設(shè)計
- 2024-2029全球及中國客戶服務(wù)BPO行業(yè)市場發(fā)展分析及前景趨勢與投資發(fā)展研究報告
- 某污水處理設(shè)備質(zhì)量保證措施
- AR眼鏡簡介介紹
評論
0/150
提交評論