1. 程式人生 > >分庫分表概念及其中介軟體

分庫分表概念及其中介軟體

簡介

    分庫分表是在做高併發多執行緒以及分散式事物系統專案中,用於減輕由於高訪問量大資料量導致的系統性能問題而使用的一種在資料庫層面的策略。

    常見的分庫分表有:垂直拆分、水平拆分兩種;Oracle和MySQL資料庫均可。根據專案中業務場景不同,而選擇不同的拆分方式,如單庫中:由於業務繁雜導致表的資料量大,那麼可以按業務垂直拆分成不同的細分業務表。另外,由於某些表的資料量過大如:單表資料量超過1000w等,則可把資料拆分到多個庫中,進行水平拆分 成db1/db2/db3...如此資料量平分後333w/333w/333w以減輕資料庫壓力從而提升系統性能。當業務既繁雜,單表資料量有過於龐大的時候,則可選擇垂直拆分

水平拆分兩種規則;根據業務場景,適量選擇拆分規則;從而達到提升系統性能和加大負載的能力等。

常用的分庫分表中介軟體

簡單易用的元件:

強悍重量級的中介軟體:

分庫分表需要解決的問題

    雖然分庫分表是一種高效快捷的,可以解決由於業務和資料量龐大而帶來的系統性能壓力等問題。但使用該策略的同時,本身也會產生一些問題;所以,決定使用分庫分表策略前,務必做好規劃以防止使用分庫分表規則後帶來的新的問題。

列出如下常見的幾個問題:

1、ID問題

一旦資料庫被切分到多個物理結點上,我們將不能再依賴資料庫自身的主鍵生成機制。一方面,某個分割槽資料庫自生成的ID無法保證在全域性上是唯一的;另一方面,應用程式在插入資料之前需要先獲得ID,以便進行SQL路由.
一些常見的主鍵生成策略

UUID

  使用UUID作主鍵是最簡單的方案,但是缺點也是非常明顯的。由於UUID非常的長,除佔用大量儲存空間外,最主要的問題是在索引上,在建立索引和基於索引進行查詢時都存在效能問題。

結合資料庫維護一個Sequence表

此方案的思路也很簡單,在資料庫中建立一個Sequence表(序列),表的結構類似於:

CREATE TABLE `SEQUENCE` (  
    `table_name` varchar(18) NOT NULL,  
    `nextid` bigint(20) NOT NULL,  
    PRIMARY KEY (`table_name`)  
) ENGINE=InnoDB

每當需要為某個表的新紀錄生成ID時就從Sequence表中取出對應表的nextid,並將nextid的值加1後更新到資料庫中以備下次使用。此方案也較簡單,但缺點同樣明顯:由於所有插入任何都需要訪問該表,該表很容易成為系統性能瓶頸,同時它也存在單點問題,一旦該表資料庫失效,整個應用程式將無法工作。有人提出使用Master-Slave進行主從同步,但這也只能解決單點問題,並不能解決讀寫比為1:1的訪問壓力問題。

Twitter的分散式自增ID演算法Snowflake

在分散式系統中,需要生成全域性UID的場合還是比較多的,twitter的snowflake解決了這種需求,實現也還是很簡單的,除去配置資訊,核心程式碼就是毫秒級時間41位 機器ID 10位 毫秒內序列12位。

* 10---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000

在上面的字串中,第一位為未使用(實際上也可作為long的符號位),接下來的41位為毫秒級時間,然後5位datacenter標識位,5位機器ID(並不算識別符號,實際是為執行緒標識),然後12位該毫秒內的當前毫秒內的計數,加起來剛好64位,為一個Long型。

這樣的好處是,整體上按照時間自增排序,並且整個分散式系統內不會產生ID碰撞(由datacenter和機器ID作區分),並且效率較高,經測試,snowflake每秒能夠產生26萬ID左右,完全滿足需要。

2、事務問題

解決事務問題目前有兩種可行的方案:分散式事務和通過應用程式與資料庫共同控制實現事務下面對兩套方案進行一個簡單的對比。

  • 方案一:使用分散式事務
    • 優點:交由資料庫管理,簡單有效
    • 缺點:效能代價高,特別是shard越來越多時
  • 方案二:由應用程式和資料庫共同控制
    • 原理:將一個跨多個數據庫的分散式事務分拆成多個僅處 於單個數據庫上面的小事務,並通過應用程式來總控 各個小事務。
    • 優點:效能上有優勢
    • 缺點:需要應用程式在事務控制上做靈活設計。如果使用 了spring的事務管理,改動起來會面臨一定的困難。

分散式事務

  • 優點
    1. 基於兩階段提交,最大限度地保證了跨資料庫操作的“原子性”,是分散式系統下最嚴格的事務實現方式。
    2. 實現簡單,工作量小。由於多數應用伺服器以及一些獨立的分散式事務協調器做了大量的封裝工作,使得專案中引入分散式事務的難度和工作量基本上可以忽略不計。
  • 缺點
    1. 系統“水平”伸縮的死敵。基於兩階段提交的分散式事務在提交事務時需要在多個節點之間進行協調,最大限度地推後了提交事務的時間點,客觀上延長了事務的執行時間,這會導致事務在訪問共享資源時發生衝突和死鎖的概率增高,隨著資料庫節點的增多,這種趨勢會越來越嚴重,從而成為系統在資料庫層面上水平伸縮的"枷鎖", 這是很多Sharding系統不採用分散式事務的主要原因。

基於Best Efforts 1PC模式的事務

參考spring-data-neo4j的實現。鑑於Best Efforts 1PC模式的效能優勢,以及相對簡單的實現方式,它被大多數的sharding框架和專案採用

事務補償(冪等值)

    對於那些對效能要求很高,但對一致性要求並不高的系統,往往並不苛求系統的實時一致性,只要在一個允許的時間週期內達到最終一致性即可,這使得事務補償機制成為一種可行的方案。事務補償機制最初被提出是在“長事務”的處理中,但是對於分散式系統確保一致性也有很好的參考意義。籠統地講,與事務在執行中發生錯誤後立即回滾的方式不同,事務補償是一種事後檢查並補救的措施,它只期望在一個容許時間週期內得到最終一致的結果就可以了。事務補償的實現與系統業務緊密相關,並沒有一種標準的處理方式。一些常見的實現方式有:對資料進行對帳檢查;基於日誌進行比對;定期同標準資料來源進行同步,等等。

3、跨節點的count,order by,group by以及聚合函式問題

    這些是一類問題,因為它們都需要基於全部資料集合進行計算。多數的代理都不會自動處理合並工作。解決方案:與解決跨節點join問題的類似,分別在各個節點上得到結果後在應用程式端進行合併。和join不同的是每個結點的查詢可以並行執行,因此很多時候它的速度要比單一大表快很多。但如果結果集很大,對應用程式記憶體的消耗是一個問題。

4、跨節點Join的問題

    只要是進行切分,跨節點Join的問題是不可避免的。但是良好的設計和切分卻可以減少此類情況的發生。解決這一問題的普遍做法是分兩次查詢實現。在第一次查詢的結果集中找出關聯資料的id,根據這些id發起第二次請求得到關聯資料。

5、資料遷移,容量規劃,擴容等問題

    來自淘寶綜合業務平臺團隊,它利用對2的倍數取餘具有向前相容的特性(如對4取餘得1的數對2取餘也是1)來分配資料,避免了行級別的資料遷移,但是依然需要進行表級別的遷移,同時對擴容規模和分表數量都有限制。總得來說,這些方案都不是十分的理想,多多少少都存在一些缺點,這也從一個側面反映出了Sharding擴容的難度。

分庫策略

分庫維度確定後,如何把記錄分到各個庫裡呢?
一般有兩種方式:

  • 根據數值範圍,比如使用者Id為1-9999的記錄分到第一個庫,10000-20000的分到第二個庫,以此類推。
  • 根據數值取模,比如使用者Id mod n,餘數為0的記錄放到第一個庫,餘數為1的放到第二個庫,以此類推

優劣比較:
評價指標按照範圍分庫按照Mod分庫
庫數量前期數目比較小,可以隨使用者/業務按需增長前期即根據mode因子確定庫數量,數目一般比較大
訪問效能前期庫數量小,全庫查詢消耗資源少,單庫查詢效能略差前期庫數量大,全庫查詢消耗資源多,單庫查詢效能略好
調整庫數量比較容易,一般只需為新使用者增加庫,老庫拆分也隻影響單個庫困難,改變mod因子導致資料在所有庫之間遷移
資料熱點新舊使用者購物頻率有差異,有資料熱點問題新舊使用者均勻到分佈到各個庫,無熱點
實踐中,為了處理簡單,選擇mod分庫的比較多。同時二次分庫時,為了資料遷移方便,一般是按倍數增加,比如初始4個庫,二次分裂為8個,再16個。這樣對於某個庫的資料,一半資料移到新庫,剩餘不動,對比每次只增加一個庫,所有資料都要大規模變動。
補充下,mod分庫一般每個庫記錄數比較均勻,但也有些資料庫,存在超級Id,這些Id的記錄遠遠超過其他Id,比如在廣告場景下,某個大廣告主的廣告數可能佔總體很大比例。如果按照廣告主Id取模分庫,某些庫的記錄數會特別多,對於這些超級Id,需要提供單獨庫來儲存記錄。

分庫數量

分庫數量首先和單庫能處理的記錄數有關,一般來說,Mysql 單庫超過5000萬條記錄,Oracle單庫超過1億條記錄,DB壓力就很大(當然處理能力和欄位數量/訪問模式/記錄長度有進一步關係)。

在滿足上述前提下,如果分庫數量少,達不到分散儲存和減輕DB效能壓力的目的;如果分庫的數量多,好處是每個庫記錄少,單庫訪問效能好,但對於跨多個庫的訪問,應用程式需要訪問多個庫,如果是併發模式,要消耗寶貴的執行緒資源;如果是序列模式,執行時間會急劇增加。

最後分庫數量還直接影響硬體的投入,一般每個分庫跑在單獨物理機上,多一個庫意味多一臺裝置。所以具體分多少個庫,要綜合評估,一般初次分庫建議分4-8個庫。

 

關注個人技術公眾號:nick_coding1024

不定期分享最新前沿技術框架和bat大廠常用技術等,加群不定期分享行業內大牛直播講課以及獲得內退一線網際網路公司機會。