1. 程式人生 > >資料庫分庫分表(sharding)(一)——基本思想、拆分策略和拆分所帶來的問題

資料庫分庫分表(sharding)(一)——基本思想、拆分策略和拆分所帶來的問題

資料庫分庫分表(sharding)(一)

      目的:我覺得學習一項技術,必須知道它的原理,尤其是這項技術的目的所在,為啥要用它!資料庫分庫分表的用處:資料庫中的資料量不一定是可控的,在未進行分庫分表的情況下,隨著時間和業務的發展,資料庫中的表會越來越多,表中的資料量也會越來越大,相應的資料操作,增刪改查也會越來越大;另外,由於無法進行分散式部署的情況下,一臺伺服器的資源(CPU,IO,磁碟,記憶體)是有限的,最終資料庫所能承載的資料量、資料處理能力都將遭遇瓶頸。基於上述原因,我們需要用到資料庫分庫分表操作。

一、基本思想

     分庫分表的目的就是講一個數據庫切分成多個部分放到不同的資料庫上,以便緩解單一資料庫的效能問題。

     舉個例子吧,當你面對海量資料的資料庫時,若歸因為表多導致的資料量大的話,建議採用垂直切分,就是把關係緊密(比如一個應用模組的表)的表

     放在一個數據庫(server)。如果表並不多,但是每張表的資料非常的多,那就要採用水平切分了。就是將表按照某種規則(常用方法是按ID雜湊)切分到多個數據庫(server)上。當然這只是舉了一個例子,因為現實情況要比這個複雜,需要將兩種切分方式聯合使用才能使得系統性能更優(因為可能一張表的資料量很大,超出了一臺伺服器的能力範圍,這時候就要在垂直拆分的基礎上再進行水平拆分)。OK,下面詳細介紹一下垂直切分和水平切分。

二、資料庫的垂直切分和水平切分

    垂直切分:就是按功能模組拆分,比如分為訂單庫,商品庫,使用者庫。垂直切分最大的特點就是簡單明瞭,實施方便。

    水平切分:將同一個表的資料進行分塊儲存到不同的資料庫。

    上面呢是兩個概念,我們來看一個具體的例子,有助於我們理解:

案例:簡單購物系統,涉及以下幾張表

1、產品表(資料量10w,穩定)

2、訂單表(資料量200W,且有增長趨勢)

3、使用者表(資料量100w,且有增長趨勢)

以mysql為例講述下水平拆分和垂直拆分,mysql資料庫能容忍的資料量級在百萬靜態資料到千萬

垂直拆分:

解決問題:表與表之間的io競爭

不解決的問題:但表中資料量增長出現的壓力

方案:把產品表和使用者表放到一個server上,訂單表單獨放到一個server上

水平拆分:

解決問題:單表中資料量增長出現的壓力

不解決的問題:表與表之間的io競爭

方案:使用者表通過性別拆分為男使用者表和女使用者表;訂單表通過已完成和完成中拆分為已完成訂單和未完成訂單;產品表未完成訂單放一個server上,已完成訂單表和男使用者表放一個server上,女使用者表放一個server上(女的愛購物,資料增量大)

三、拆分策略

     如上述所提到的,拆分一般順序是先垂直拆分再水平拆分。垂直拆分的結果正好為水平拆分做好鋪墊,垂直拆分的思路就是分析表之間的聚合關係,把關係緊密的表放在一個server上(多數情況下可能是同一個模組或者同一個“聚集”,聚集是指:領域驅動設計裡的“聚合根”),這個“聚合根”也是進行水平拆分的依據,所有和聚合根關聯的而資料將被水平分割到各自的shard碎片中。這樣出現跨shard關聯的可能性就非常的小,應用程式就不必打斷既有的表間關聯。舉個例子:對於社交網站,幾乎所有資料最終都會關聯到某個使用者上,基於使用者進行切分就是最好的選擇。再比如論壇系統,使用者和論壇兩個模組應該在垂直切分時被分在了兩個shard裡,對於論壇模組來說,Forum顯然是聚合根,因此按Forum進行水平切分,把Forum裡所有的帖子和回帖都隨Forum放在一個shard裡是很自然的。過幾天更新一版詳細的拆分策略

四、拆分所帶來的問題

1、事務問題

     事務問題的一般解決方式分為兩種:分散式事務和通過應用程式與資料庫共同控制實現事務

方案一;使用分散式事務

優點:交友資料庫管理,簡單有效

缺點:效能代價高,特別是shard越來越多時

方案二:由應用程式和資料庫共同控制

原理:將一個跨多個數據庫的分散式事務分成多個僅處於單個數據庫上面的小事務,並通過應用程式來總控各個小事務

優點:效能上有優勢

缺點:需要應用程式在事務控制上做靈活的設計

2、跨節點Join問題

     避免join操作,將操作分成多步完成。在第一次查詢的結果集中找出關聯資料的id,根據這些id發起第二次請求得到關聯資料。

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

    解決方案:與解決跨節點join問題的類似,分別在各個節點上得到結果後在應用程式端進行合併。

五、總結

     資料庫分庫原因是避免資料庫表與表之間的eio競爭,資料庫分表原因是為了避免單表資料量增長帶來的壓力。在實際專案中要先理清整個資料路庫的er關係圖,在進行拆分,此外需要對一些sql語句進行適當的拆分和優化。