溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

死磕MyCat使用篇之第一篇

發(fā)布時(shí)間:2020-06-27 17:45:01 來源:網(wǎng)絡(luò) 閱讀:309 作者:編程同學(xué)會 欄目:MySQL數(shù)據(jù)庫

基本概念

直接介紹概念太枯燥了,還是拿個(gè)和背景篇相似的例子介紹
業(yè)務(wù)場景:客戶完成下單,快遞員接受并更新運(yùn)單狀態(tài),客戶可以隨時(shí)查看運(yùn)單狀態(tài)的任務(wù)。一票快遞可能有多個(gè)子母件。同時(shí),我們需要標(biāo)記每個(gè)運(yùn)單的狀態(tài),運(yùn)單狀態(tài)的解釋和含義保存在運(yùn)單狀態(tài)字典表中。
因此,我們需要建立如下表:

死磕MyCat使用篇之第一篇

我們現(xiàn)在按照業(yè)務(wù)將數(shù)據(jù)庫垂直拆分成運(yùn)單庫(單表2000tps,6000W數(shù)據(jù)),快遞員庫(單表1500tps,100W數(shù)據(jù)),客戶庫(單表1500tps,1000W數(shù)據(jù)記錄);假設(shè)每個(gè)MySQL數(shù)據(jù)庫單表不能超過2000W數(shù)據(jù),單表不能超過1000tps。那么運(yùn)單庫則需要分成3片,客戶庫需要分成2片,統(tǒng)一由MyCat管理。如下圖所示:

死磕MyCat使用篇之第一篇

1.邏輯庫

MyCat作為一個(gè)中間件,對應(yīng)用應(yīng)為無感知的。
應(yīng)用訪問MyCat,根據(jù)之前所述,應(yīng)用感知到后臺只是一個(gè)(或者多個(gè),和訪問MySQL實(shí)例一樣)數(shù)據(jù)庫(假設(shè)只有一個(gè)數(shù)據(jù)庫,這個(gè)庫叫SF,里面有運(yùn)單相關(guān)表,快遞員相關(guān)表和客戶相關(guān)表);這里MyCat的數(shù)據(jù)庫就是邏輯庫。訪問MyCat,結(jié)果應(yīng)該如下面所示

死磕MyCat使用篇之第一篇

雖然其中的表可能存在于不同的庫,但是表面上,他們屬于同一個(gè)MyCat實(shí)例中的同一個(gè)邏輯庫。所以,雖然上面的架構(gòu)圖顯示他們不在同一個(gè)數(shù)據(jù)庫,但是在MyCat中,他們在同一個(gè)邏輯庫。
2.邏輯表

在邏輯庫下的表就是邏輯表。邏輯表可以分片,也可以不分片。
orders表明顯是要分片的表,但是在MyCat看來,他們雖然分布在不同的分片節(jié)點(diǎn)上(分布在不同的MySQL數(shù)據(jù)庫上),但仍視為是同一個(gè)邏輯表,在同一個(gè)邏輯庫里。
2.1分片表

分片表,是指那些原有的很大數(shù)據(jù)的表,需要切分到多個(gè)數(shù)據(jù)庫的表,這樣,每個(gè)分片都有一部分?jǐn)?shù)據(jù),所有分片構(gòu)成了完整的數(shù)據(jù)。分片表都有自己的分片規(guī)則,根據(jù)分片規(guī)則確定分片。
配置里面,如下配置:

<table name="orders" primaryKey="id" dataNode="test$1-2" rule="mod-long">
</table>

意思就是用mod-long規(guī)則根據(jù)主鍵id將運(yùn)單表orders分割到test1,test2這兩個(gè)數(shù)據(jù)庫(分片節(jié)點(diǎn))上。
請求情況1:

select * from orders where id = 1;

對于分片表的查詢,如果按照分片列查詢,則請求只會被發(fā)送到一個(gè)分片上。
請求情況2:

select * from orders where id < 100 and id > 0;

對于分片表的查詢,如果按照分片列范圍(在字段類型支持范圍的情況下)查詢,則請求會根據(jù)分片規(guī)則計(jì)算兩個(gè)邊界值,然后將請求發(fā)送到對應(yīng)結(jié)果的分片上,并合并每個(gè)分片的結(jié)果。
請求情況3:

select * from orders where initialpoint = 'Beijing';

像這種根據(jù)非分片列查詢的情況,請求會被發(fā)送到所有分片上,并合并每個(gè)分片的結(jié)果。
請求情況4:
請求為更新類型的sql語句,與查詢的三種情況相同處理。
2.2 非分片表

一個(gè)數(shù)據(jù)庫中并不是所有的表都很大,某些表是可以不用進(jìn)行切分的,非分片是相對分片表來說的,就是那些不需要進(jìn)行數(shù)據(jù)切分的表。
例如:

<table name="courier" primaryKey="id" dataNode="test3">
</table>

意思就是快遞員表不用分片,保存在test3這個(gè)分片節(jié)點(diǎn)上。
對于非分片表的操作和對普通數(shù)據(jù)庫的一樣,因?yàn)椴簧婕暗椒植际綌?shù)據(jù)庫。
2.3 ER表

關(guān)系型數(shù)據(jù)庫是基于實(shí)體關(guān)系模型(Entity-Relationship Model)之上,通過其描述了真實(shí)世界中事物與關(guān)系,Mycat中的ER表即是來源于此。根據(jù)這一思路,提出了基于E-R關(guān)系的數(shù)據(jù)分片策略,子表的記錄與所關(guān)聯(lián)的父表記錄存放在同一個(gè)數(shù)據(jù)分片上,即子表依賴于父表,通過表分組(Table Group)保證數(shù)據(jù)Join不會跨庫操作。
表分組(Table Group)是解決跨分片數(shù)據(jù)join的一種很好的思路,也是數(shù)據(jù)切分規(guī)劃的重要一條規(guī)則。
如下:

<!-- 運(yùn)單表,對主鍵id對2取模 -->
<table name="orders" primaryKey="id" dataNode="test$1-2" rule="mod-long">
    <!-- 運(yùn)單子母件表,運(yùn)單表的子表,order_id與orders的id列對應(yīng) -->
    <childTable name="orders_cargo" joinKey="order_id" parentKey="id">
    </childTable>        
</table>

運(yùn)單表為分片表,運(yùn)單表和運(yùn)單子母件表為一對多關(guān)系,可以做成父子表。
對于子表的sql請求,都是通過joinKey對應(yīng)到父表對應(yīng)字段后,按照之前分片表的規(guī)則進(jìn)行處理。
2.4 全局表

一個(gè)真實(shí)的業(yè)務(wù)系統(tǒng)中,往往存在大量的類似字典表的表,這些表基本上很少變動,字典表具有以下幾個(gè)特性:

變動不頻繁
數(shù)據(jù)量總體變化不大
數(shù)據(jù)規(guī)模不大,很少有超過數(shù)十萬條記錄。

對于這類的表,在分片的情況下,當(dāng)業(yè)務(wù)表因?yàn)橐?guī)模而進(jìn)行分片以后,業(yè)務(wù)表與這些附屬的字典表之間的關(guān)聯(lián),就成了比較棘手的問題,所以Mycat中通過數(shù)據(jù)冗余來解決這類表的join,即所有的分片都有一份數(shù)據(jù)的拷貝,所有將字典表或者符合字典表特性的一些表定義為全局表。
數(shù)據(jù)冗余是解決跨分片數(shù)據(jù)join的一種很好的思路,也是數(shù)據(jù)切分規(guī)劃的另外一條重要規(guī)則
比如:

<!-- 運(yùn)單狀態(tài)信息表,公共表,放在和運(yùn)單表同樣的分片上 -->
<table name="order_status_interception" primaryKey="id" type="global" dataNode="test$1-2">
</table>

運(yùn)單狀態(tài)信息字典表,只是注釋每種運(yùn)單狀態(tài),就是典型的字典表,與分片表orders為多對一的關(guān)系。
對于全局表,所有的查詢請求,只會發(fā)送到其中一個(gè)全局表分片上執(zhí)行,所有的更新請求,會在每個(gè)全局表分片上執(zhí)行。
2.5 如何決定?

根據(jù)之前的描述,我們可以推斷出,對于分片表的修改和查詢,如果是按照分片字段進(jìn)行查找的話,則請求會被轉(zhuǎn)發(fā)到一個(gè)分片上。如果不是按照分片字段的話,就會把請求發(fā)到每一個(gè)分片上進(jìn)行查找。所以,分片字段的選擇比較重要!對于全局表,相當(dāng)于在每個(gè)分片上有一份相同的復(fù)制,修改請求會在每一個(gè)分片上執(zhí)行,但是查詢只會落到一個(gè)分片上。所以,全局表盡量是不會改變的而且是需要和分片表做Join操作的,如果經(jīng)常改變或者不需要做join,最好還是做成非分片表。

先拋出了這幾種邏輯表的概念,大家先有個(gè)印象?,F(xiàn)在我們結(jié)合具體實(shí)際討論如何決定表的類型。

首先,orders表可定是分片表。orders_cargo表是子母件表,一個(gè)order可能有多個(gè)子母件,所以,最好把orders_cargo作為orders的子表。
這種情況下,orders與orders_cargo按照對應(yīng)鍵(就是子表按照哪個(gè)鍵與主表的哪個(gè)鍵對應(yīng)進(jìn)行分片。比如orders_cargo就是order_id與orders的id對應(yīng)。這是以order_id與orders的id進(jìn)行join結(jié)果就是對的)join結(jié)果也是正確的。

死磕MyCat使用篇之第一篇

一對n場景架構(gòu)
像這種簡單的從屬關(guān)系一對n的表,我們處理起來很簡單,一般將它們按照需要做join的鍵設(shè)為父子表即可。

但是下面的場景很麻煩,比如快遞員與運(yùn)單就是多對多的關(guān)系,客戶對于運(yùn)單也是多對多的關(guān)系(一個(gè)收方,一個(gè)寄方)。我們既有快遞員需要查看自己的所有運(yùn)單的場景和客戶查看自己所有運(yùn)單的場景。相對的,我們也有查看一個(gè)運(yùn)單涉及到的快遞員還有客戶的場景。
customer表(客戶表)以及courier表(快遞員表)因?yàn)榕c分片表orders之間不做join操作,所以不用作為公共表。
首先,關(guān)系表可以作為公共表,這樣的話,涉及到與分片表的join操作沒有限制,因?yàn)樵诿總€(gè)分片,公共表都是完整的。但是,關(guān)系表的更新很頻繁,我們可能不能忍受每更新一次關(guān)系表就跑到每個(gè)分片上都更新一次(性能,可靠性考慮)。
那么作為運(yùn)單的子表呢?那么查找一個(gè)運(yùn)單涉及到的快遞員還有客戶就比較簡單。因?yàn)楦鶕?jù)運(yùn)單號(也就是分片id)查詢,MyCat就會根據(jù)分片規(guī)則給他定位到具體分片,而不是去按分片搜索。

死磕MyCat使用篇之第一篇

這里寫圖片描述
但是相應(yīng)的,快遞員查看自己所有運(yùn)單的場景就比較慢,因?yàn)檎埱笫前l(fā)送到每一個(gè)分片上查找。
死磕MyCat使用篇之第一篇

這里寫圖片描述
作為快遞員的子表也有同樣的缺陷。
還有一種方法,就是這種關(guān)系表同時(shí)作為運(yùn)單和快遞員的子表。但是這樣,目前需要應(yīng)用自己去做雙寫。MyCat目前還沒實(shí)現(xiàn)這種。當(dāng)然,我覺得這是一個(gè)我們自己可以根據(jù)需要改進(jìn)的地方。MyCat中間件根據(jù)關(guān)系冗余表關(guān)系進(jìn)行雙寫

另外,究竟取哪種方法,都是從業(yè)務(wù)出發(fā)去考慮的。在這里,如果從快遞員出發(fā)去查找以及從運(yùn)單出發(fā)去查找的業(yè)務(wù)壓力差不多大的話,那么最好就采用關(guān)系表同時(shí)作為運(yùn)單和客戶的子表這種方法。然后將快遞員和運(yùn)單的業(yè)務(wù)獨(dú)立,每個(gè)業(yè)務(wù)應(yīng)用都去維護(hù)自己的關(guān)系表,同時(shí)通過消息隊(duì)列來保持關(guān)系表之間的一致性。這樣也不失為一種方法。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI