來自Citus的Ozgun Erdogan分享了進行數(shù)據(jù)庫分片的三個原則,并強調(diào)應(yīng)用類型是決定數(shù)據(jù)庫分片最主要的因素。其中B2B類型的應(yīng)用最容易進行數(shù)據(jù)庫分片。
在數(shù)據(jù)庫很小的時候,可以很容易地通過添加硬件來擴展數(shù)據(jù)庫。但隨著數(shù)據(jù)表數(shù)量的不斷增長,我們需要尋找其他的方式來伸縮數(shù)據(jù)庫。
分片是伸縮數(shù)據(jù)庫最好的方式之一。通過分片將數(shù)據(jù)庫拆分成更小的單元,可以線性地擴展數(shù)據(jù)庫的CPU、內(nèi)存和磁盤資源。不過在分片這個問題上也存在一些爭議,網(wǎng)絡(luò)上充斥著各種有關(guān)分片的不同觀點,如“essential to scaling your database infrastructure”和“why you never want to shard”。那么問題來了,我們應(yīng)該采納哪一種觀點?而一般來說,答案通常會是“它取決于”。
分片的原理很簡單,就是通過一個鍵(或者說列)來均勻地分布數(shù)據(jù)。不過理論雖簡單,在真正遇到要對數(shù)據(jù)庫進行分片時,很可能會陷入一團手忙腳亂之中。
在Citus,我們曾經(jīng)幫助數(shù)百個團隊進行數(shù)據(jù)庫分片,也從中總結(jié)了一些關(guān)鍵的分片模式。
在這篇文章里,我們會先探討一些決定分片成敗的關(guān)鍵屬性,然后從底層細節(jié)分析這些屬性之間的不同點。在進行大型數(shù)據(jù)庫分片時,應(yīng)用程序的類型將成為最主要的影響因素。
成功分片取決于三個關(guān)鍵屬性
我們發(fā)現(xiàn)有三個關(guān)鍵屬性會影響到成功的分片。下圖通過三個方向軸展示了這三個屬性,并在每個軸上面放置了一些知名的公司作為例子。
X-軸表示負載類型,從左側(cè)的事務(wù)開始延伸到右側(cè)的數(shù)據(jù)倉庫。在進行數(shù)據(jù)庫伸縮時,這一維度最具有識別度。
Z-軸表示另一個非常重要的屬性,也就是應(yīng)用程序當前所處的生命周期。此時你的數(shù)據(jù)庫里有多少數(shù)據(jù)表?你的應(yīng)用程序已經(jīng)運行了多長時間?一個運行了幾個月的數(shù)據(jù)庫要比運行了數(shù)年的數(shù)據(jù)庫更容易進行分片。
在Citus,我們發(fā)現(xiàn)大部分用戶都有自己的應(yīng)用程序。應(yīng)用程序越是成熟,Y-軸就顯得越為重要。不過這個維度不如其他兩個維度那么具有識別度。事實上,很多討論分片的文章之所以會得出互相矛盾的結(jié)論,是因為它們只是基于單一的應(yīng)用類型。
分片中最重要的屬性:應(yīng)用類型(B2B或B2C)
Y-軸展示了在對成熟數(shù)據(jù)庫進行分片時最為重要的屬性:應(yīng)用程序的類型。在這條軸上,B2B應(yīng)用處于最上端,它們的數(shù)據(jù)模型更容易進行分片。B2C應(yīng)用處于軸的底部,比如Amazon和Facebook,它們的分片需要做更多的工作。接下來,我們挑選了三家知名的公司來比對它們之間的不同點。
B2B類型:Salesforce
CRM系統(tǒng)是B2B應(yīng)用最為典型的例子。構(gòu)建CRM系統(tǒng)的目的是為了要給其他客戶提供服務(wù)的,我們假設(shè)GE Aviation是你的一個客戶,他們正在使用Salesforce。
GE Aviation有如下的一些實體。
客戶(customer):公司的顧客。用戶(user):用戶可以登錄GE公司的儀表盤。負責(zé)人(lead):GE與這些負責(zé)人商談業(yè)務(wù)。聯(lián)系人(contact):GE與這些聯(lián)系人有了業(yè)務(wù)往來,并知道他們的聯(lián)系方式。賬號(account):業(yè)務(wù)代表和擁有聯(lián)系人的人。機會(opportunity):與賬號和聯(lián)系人相關(guān)的銷售事件。如果把這些實體之間的復(fù)雜關(guān)系映射到數(shù)據(jù)庫里,看起來是這樣的:
整個圖咋一看確實很復(fù)雜,不過如果你多花一點時間看仔細一點,你會發(fā)現(xiàn)大多數(shù)表都是源自customer表。通過往每個表里添加customer_id列可以把表間關(guān)系轉(zhuǎn)換成如下形式:
通過這種簡單的轉(zhuǎn)換,就可以通過customer_id這個鍵進行數(shù)據(jù)庫分片。這個鍵可以讓數(shù)據(jù)均勻地分布,而大部分查詢都需要帶上這個鍵。另外,你還可以根據(jù)customer_id把相關(guān)表聚集在同一個位置,這樣就可以繼續(xù)使用關(guān)系型數(shù)據(jù)庫的一些關(guān)鍵特性,比如事務(wù)、表連接和外鍵。
換句話說,如果你的應(yīng)用類型是B2B的,那么你的數(shù)據(jù)就具備了分片的天然特性。
B2C類型:Amazon
Amazon是B2C應(yīng)用最為典型的例子。在構(gòu)建像Amazon這樣的網(wǎng)站時,有許多東西需要考慮。首先,用戶來到你的網(wǎng)站,瀏覽你的商品,比如書或電子產(chǎn)品。假設(shè)用戶在瀏覽《Harry Potter 7》,他們也可以看到這個產(chǎn)品的分類信息,比如書本的作者、價格、封面和其他圖片。
用戶在登錄網(wǎng)站之后,開始訪問用戶相關(guān)的數(shù)據(jù)。用戶需要得到認證,然后獲得給產(chǎn)品添加評論的權(quán)限或者把產(chǎn)品添加到購物車里。在某個時候,用戶決定要購買購物車里的產(chǎn)品,于是就下單。訂單經(jīng)過處理之后,開始進入物流運送流程。
你會發(fā)現(xiàn),現(xiàn)在的關(guān)系圖與Salesforce的關(guān)系圖有一個很大的不同點。現(xiàn)在的關(guān)系圖中不止一個中心點,而是三個:分類(catalog)、用戶(user)和訂單(order)。
要對這種B2C類型的數(shù)據(jù)進行分片,可以考慮將它們重構(gòu)成微服務(wù)。例如,與產(chǎn)品目錄相關(guān)的服務(wù)提供目錄服務(wù),用戶相關(guān)的服務(wù)提供認證和購物車服務(wù)。服務(wù)之間的API定義了底層數(shù)據(jù)訪問的邊界。
數(shù)據(jù)經(jīng)過拆分之后,就可以進行分片。事實上,Amazon在遷移到面向服務(wù)架構(gòu)時就使用了類似的方式進行數(shù)據(jù)分片。
這種分片方式與B2B應(yīng)用的分片在好處和成本比率上有很大的差別。從好處方面來看,你可以依賴數(shù)據(jù)庫從不同的數(shù)據(jù)庫連接數(shù)據(jù),或者為數(shù)據(jù)集提供事務(wù)和約束。從成本方面來看,現(xiàn)在要進行分片的不止是一個數(shù)據(jù)集,而是多個。
B2C2C類型:Instacart
在B2B和B2C之間還有另外一種類型的網(wǎng)站,比如Postmates、Instacart或Lyft。[Instacart][12]的主營業(yè)務(wù)是將本地商店的貨物運送給用戶。從某方面來看,Instacart與Amazon有點類似。Instacart的數(shù)據(jù)模型具有三個維度:提供貨物的本地商店、訂購商品的用戶和運送貨物的司機。所以,很難在這當中挑出一個鍵進行分片。
如果你的應(yīng)用屬于B2C2C類型,可能需要采取不同的策略。你會發(fā)現(xiàn)大部分數(shù)據(jù)表會共享一個維度:地理位置信息。在這種情況下,你可能會選擇城市或地理位置作為分片的鍵。
一般來說,B2B2C應(yīng)用或B2C2C應(yīng)用的分片處于圖譜的中間。B2B2C分片的好處和成本之間的比率要高于B2C應(yīng)用,但低于B2B應(yīng)用。
結(jié)論
網(wǎng)絡(luò)上存在很多有關(guān)分片的觀點。我們發(fā)現(xiàn)它們大部分都是基于單一的應(yīng)用類型。事實上,應(yīng)用類型比其他因素更能影響到分片。B2B類型的應(yīng)用最容易進行分片。