电竞比分网-中国电竞赛事及体育赛事平台

分享

分庫分表總結(jié),Mycat從入門到放棄

 順溜的書架 2019-09-27

之前調(diào)研分庫分表框架,最后選擇了sharding-jdbc,

下面是我總結(jié)的各個(gè)框架:

Atlas:不能實(shí)現(xiàn)分布式分表,所有的子表必須在同一臺(tái)DB的同一個(gè)database里且所有的子表必須事先建好,Atlas沒有自動(dòng)建表的功能。Atlas參考鏈接
Cobar:必須將拆分后的表分別放入不同的庫來實(shí)現(xiàn)分布式。Cobar參考鏈接
TDDL:阿里,功能強(qiáng)大,過于復(fù)雜,部分開源。需要評(píng)估使用情況,防止過剩。阿里云能買到完整的。
Mycat :國內(nèi)開源,從入門到放棄。mycat參考鏈接
heisenberg:百度開源,相對(duì)簡(jiǎn)單,易于管理。但是github很久沒有維護(hù)了。heisenberg參考鏈接
Oceanus:功能強(qiáng)大,開源,簡(jiǎn)化開發(fā)和配置成功。但產(chǎn)品還不成熟。
vitess:google產(chǎn)品,集群基于ZooKeeper管理,通過RPC方式進(jìn)行數(shù)據(jù)處理,可支撐高流量,它還添加了一個(gè)連接池,具有基于行的高速緩存,重寫SQL查詢,更安全。vitess參考鏈接
OneProxy:中國廠商產(chǎn)品,穩(wěn)定性待確認(rèn)。 OneProxy參考鏈接
Sharding-JDBC:當(dāng)當(dāng)最新開源。2018年架構(gòu)師去京東,現(xiàn)在有專門的團(tuán)隊(duì)維護(hù),這方面都有保障,最后選擇了它。Sharding-JDBC參考鏈接

總結(jié):國外的不能用,國內(nèi)的小廠商不能用,使用有限制的不能用,mycat名氣大實(shí)際一般不能用,百度的heisenberg好久沒維護(hù)放棄。最后只有TDDL和sj,阿里系或者使用阿里云的可以用TDDL。非阿里系建議還是Sharding-JDBC。

Sharding-JDBC的作者去了京東,目前有專門的團(tuán)隊(duì)維護(hù)。


下面是轉(zhuǎn)的一篇:Mycat從入門到放棄,這篇文章寫得非常好,對(duì)分庫分表入門有醍醐灌頂之感

轉(zhuǎn)自:https://blog.csdn.net/u013235478/article/details/53178657

當(dāng)初寫這篇文章的初衷只是想提醒自己在用一個(gè)開源產(chǎn)品前不僅要了解其提供的功能,更要了解其功能和場(chǎng)景邊界。

1.非分片字段查詢

Mycat中的路由結(jié)果是通過分片字段分片方法來確定的。例如下圖中的一個(gè)Mycat分庫方案:

  • 根據(jù) tt_waybill 表的 id 字段來進(jìn)行分片
  • 分片方法為 id 值取 3 的模,根據(jù)模值確定在DB1,DB2,DB3中的某個(gè)分片

非分片字段查詢

如果查詢條件中有 id 字段的情況還好,查詢將會(huì)落到某個(gè)具體的分片。例如:

mysql>select * from tt_waybill where id = 12330;

此時(shí)Mycat會(huì)計(jì)算路由結(jié)果

12330 % 3 = 0 –> DB1

并將該請(qǐng)求路由到DB1上去執(zhí)行。 


如果查詢條件中沒有 分片字段 條件,例如:

mysql>select * from tt_waybill where waybill_no =88661;

此時(shí)Mycat無法計(jì)算路由,便發(fā)送到所有節(jié)點(diǎn)上執(zhí)行:

DB1 –> select * from tt_waybill where waybill_no =88661; 
DB2 –> select * from tt_waybill where waybill_no =88661; 
DB3 –> select * from tt_waybill where waybill_no =88661;

如果該分片字段選擇度高,也是業(yè)務(wù)常用的查詢維度,一般只有一個(gè)或極少數(shù)個(gè)DB節(jié)點(diǎn)命中(返回結(jié)果集)。示例中只有3個(gè)DB節(jié)點(diǎn),而實(shí)際應(yīng)用中的DB節(jié)點(diǎn)數(shù)遠(yuǎn)超過這個(gè),假如有50個(gè),那么前端的一個(gè)查詢,落到MySQL數(shù)據(jù)庫上則變成50個(gè)查詢,會(huì)極大消耗Mycat和MySQL數(shù)據(jù)庫資源。

如果設(shè)計(jì)使用Mycat時(shí)有非分片字段查詢,請(qǐng)考慮放棄!

2.分頁排序

先看一下Mycat是如何處理分頁操作的,假如有如下Mycat分庫方案: 
一張表有30份數(shù)據(jù)分布在3個(gè)分片DB上,具體數(shù)據(jù)分布如下

DB1:[0,1,2,3,4,10,11,12,13,14] 
DB2:[5,6,7,8,9,16,17,18,19] 
DB3:[20,21,22,23,24,25,26,27,28,29]

(這個(gè)示例的場(chǎng)景中沒有查詢條件,所以都是全分片查詢,也就沒有假定該表的分片字段和分片方法)

分頁

當(dāng)應(yīng)用執(zhí)行如下分頁查詢時(shí)

mysql>select * from table limit 2;

Mycat將該SQL請(qǐng)求分發(fā)到各個(gè)DB節(jié)點(diǎn)去執(zhí)行,并接收各個(gè)DB節(jié)點(diǎn)的返回結(jié)果

DB1: [0,1] 
DB2: [5,6] 
DB3: [20,21]

但Mycat向應(yīng)用返回的結(jié)果集取決于哪個(gè)DB節(jié)點(diǎn)最先返回結(jié)果給Mycat。如果Mycat最先收到DB1節(jié)點(diǎn)的結(jié)果集,那么Mycat返回給應(yīng)用端的結(jié)果集為 [0,1],如果Mycat最先收到DB2節(jié)點(diǎn)的結(jié)果集,那么返回給應(yīng)用端的結(jié)果集為 [5,6]。也就是說,相同情況下,同一個(gè)SQL,在Mycat上執(zhí)行時(shí)會(huì)有不同的返回結(jié)果。

在Mycat中執(zhí)行分頁操作時(shí)必須顯示加上排序條件才能保證結(jié)果的正確性,下面看一下Mycat對(duì)排序分頁的處理邏輯。 
假如在前面的分頁查詢中加上了排序條件(假如表數(shù)據(jù)的列名為id

mysql>select * from table order by id limit 2;

Mycat的處理邏輯如下圖:

排序分頁

在有排序呢條件的情況下,Mycat接收到各個(gè)DB節(jié)點(diǎn)的返回結(jié)果后,對(duì)其進(jìn)行最小堆運(yùn)算,計(jì)算出所有結(jié)果集中最小的兩條記錄 [0,1] 返回給應(yīng)用。

但是,當(dāng)排序分頁中有 偏移量 (offset)時(shí),處理邏輯又有不同。假如應(yīng)用的查詢SQL如下:

mysql>select * from table order by id limit 5,2;

如果按照上述排序分頁邏輯來處理,那么處理結(jié)果如下圖:

排序偏移分頁

Mycat將各個(gè)DB節(jié)點(diǎn)返回的數(shù)據(jù) [10,11], [16,17], [20,21] 經(jīng)過最小堆計(jì)算后返回給應(yīng)用的結(jié)果集是 [10,11]??墒牵瑢?duì)于應(yīng)用而言,該表的所有數(shù)據(jù)明明是 0-29 這30個(gè)數(shù)據(jù)的集合,limit 5,2 操作返回的結(jié)果集應(yīng)該是 [5,6],如果返回 [10,11]則是錯(cuò)誤的處理邏輯。

所以Mycat在處理 有偏移量的排序分頁 時(shí)是另外一套邏輯——改寫SQL 。如下圖:

正確排序偏移分頁

Mycat在下發(fā)有 limit m,n 的SQL語句時(shí)會(huì)對(duì)其進(jìn)行改寫,改寫成 limit 0, m+n 來保證查詢結(jié)果的邏輯正確性。所以,Mycat發(fā)送到后端DB上的SQL語句是

mysql>select * from table order by id limit 0,7;

各個(gè)DB返回給Mycat的結(jié)果集是

DB1: [0,1,2,3,4,10,11] 
DB2: [5,6,7,8,9,16,17] 
DB3: [20,21,22,23,24,25,26]

經(jīng)過最小堆計(jì)算后得到最小序列 [0,1,2,3,4,5,6] ,然后返回偏移量為5的兩個(gè)結(jié)果為 [5,6] 。

雖然Mycat返回了正確的結(jié)果,但是仔細(xì)推敲發(fā)現(xiàn)這類操作的處理邏輯是及其消耗(浪費(fèi))資源的。應(yīng)用需要的結(jié)果集為2條,Mycat中需要處理的結(jié)果數(shù)為21條。也就是說,對(duì)于有 t 個(gè)DB節(jié)點(diǎn)的全分片 limit m, n 操作,Mycat需要處理的數(shù)據(jù)量為 (m+n)*t 個(gè)。比如實(shí)際應(yīng)用中有50個(gè)DB節(jié)點(diǎn),要執(zhí)行l(wèi)imit 1000,10操作,則Mycat處理的數(shù)據(jù)量為 50500 條,返回結(jié)果集為10,當(dāng)偏移量更大時(shí),內(nèi)存和CPU資源的消耗則是數(shù)十倍增加。

如果設(shè)計(jì)使用Mycat時(shí)有分頁排序,請(qǐng)考慮放棄!

3.任意表JOIN

先看一下在單庫中JOIN中的場(chǎng)景。假設(shè)在某單庫中有 player  team 兩張表,player 表中的 team_id 字段與 team 表中的 id 字段相關(guān)聯(lián)。操作場(chǎng)景如下圖:

單個(gè)DB中JOIN

JOIN操作的SQL如下

mysql>select p_name,t_name from player p, team t where p.no = 3 and p.team_id = t.id;

此時(shí)能查詢出結(jié)果

p_namet_name
WadeHeat


如果將這兩個(gè)表的數(shù)據(jù)分庫后,相關(guān)聯(lián)的數(shù)據(jù)可能分布在不同的DB節(jié)點(diǎn)上,如下圖:

分庫JOIN

這個(gè)SQL在各個(gè)單獨(dú)的分片DB中都查不出結(jié)果,也就是說Mycat不能查詢出正確的結(jié)果集。

設(shè)計(jì)使用Mycat時(shí)如果要進(jìn)行表JOIN操作,要確保兩個(gè)表的關(guān)聯(lián)字段具有相同的數(shù)據(jù)分布,否則請(qǐng)考慮放棄!

4.分布式事務(wù)

Mycat并沒有根據(jù)二階段提交協(xié)議實(shí)現(xiàn) XA事務(wù),而是只保證 prepare 階段數(shù)據(jù)一致性的 弱XA事務(wù) ,實(shí)現(xiàn)過程如下:

應(yīng)用開啟事務(wù)后Mycat標(biāo)識(shí)該連接為非自動(dòng)提交,比如前端執(zhí)行

mysql>begin;

Mycat不會(huì)立即把命令發(fā)送到DB節(jié)點(diǎn)上,等后續(xù)下發(fā)SQL時(shí),Mycat從連接池獲取非自動(dòng)提交的連接去執(zhí)行。

弱XA事務(wù)1

Mycat會(huì)等待各個(gè)節(jié)點(diǎn)的返回結(jié)果,如果都執(zhí)行成功,Mycat給該連接標(biāo)識(shí)為 Prepare Ready 狀態(tài),如果有一個(gè)節(jié)點(diǎn)執(zhí)行失敗,則標(biāo)識(shí)為 Rollback 狀態(tài)。

弱XA事務(wù)2

執(zhí)行完成后Mycat等待前端發(fā)送 commit  rollback 命令。發(fā)送 commit 命令時(shí),Mycat檢測(cè)當(dāng)前連接是否為 Prepare Ready 狀態(tài),若是,則將 commit 命令發(fā)送到各個(gè)DB節(jié)點(diǎn)。

弱XA事務(wù)3

但是,這一階段是無法保證一致性的,如果一個(gè)DB節(jié)點(diǎn)在 commit 時(shí)故障,而其他DB節(jié)點(diǎn) commit 成功,Mycat會(huì)一直等待故障DB節(jié)點(diǎn)返回結(jié)果。Mycat只有收到所有DB節(jié)點(diǎn)的成功執(zhí)行結(jié)果才會(huì)向前端返回 執(zhí)行成功 的包,此時(shí)Mycat只能一直 waiting 直至TIMEOUT,導(dǎo)致事務(wù)一致性被破壞。

設(shè)計(jì)使用Mycat時(shí)如果有分布式事務(wù),得先看是否得保證事務(wù)得強(qiáng)一致性,否則請(qǐng)考慮放棄!


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多