1. 程式人生 > 其它 >【科普】談談分庫分表與分片

【科普】談談分庫分表與分片

一. 大綱

在談論資料庫架構和資料庫優化的時候,我們經常會聽到分庫分表分割槽分片(Sharding)等關鍵詞,對於這些概念,相信大家應該都有聽說過或是瀏覽過相關的文件,我們今天就來詳細瞭解下這幾個比較容易混淆的概念。

首先呢,我們需要知道上述的這些方案都是為了同一個目的而產生,那就是為了突破單表/庫過大單節點資料庫伺服器的效能瓶頸,解決資料庫的擴充套件性問題。

因為隨著表資料量的增長,單機資料庫的資源和處理能力有限,所以資料庫非常容易成為應用系統的瓶頸。

二. 分庫

垂直分庫微服務盛行的今天已經非常普及了,基本的思路就是按照業務模組來劃分出不同的資料庫,而不是像早期一樣將所有的資料表都放到同一個資料庫中。

系統層面的服務化拆分能夠解決業務系統層面的耦合效能瓶頸,有利於系統的擴充套件維護。

而資料庫層面的資料拆分,道理其實也是相通的,可以更加便於資料庫的管理、維護、監控、擴充套件等。

垂直分庫可以在一定程度上解決資料庫單機瓶頸,因為可以將不同的業務庫分散在不同的伺服器上,獨享資源,互不干擾,但是一定要了解清楚拆分的原則與技巧,否則會遇到很多問題,例如:跨庫JOIN分散式事務等。

三. 分表

分表就是將一張大表拆分成N個子表,根據切分規則,通常由如下兩種模式:

  • 垂直拆分:基於拆分表,將表中的某些欄位拆分出去放入到擴充套件表中。

  • 水平拆分:基於拆分表,通過規則匹配分類後,將資料放到若干個子表

    中。

3.1. 垂直分表

垂直分表在日常開發和設計中比較常見,通俗的說法叫做大表拆小表,拆分是基於關係型資料庫中的列(欄位)進行的。

通常情況下,當某個表中的欄位比較多時,可以新建一張擴充套件表,將不經常使用或者長度較大的欄位拆分出去。

垂直分表的作用比較有限,它只可以減少行資料大小,加快資料檢索的速度,但是無法解決因為表資料量增長而導致的壓力。

表字段拆分(垂直分表)建議在資料庫設計階段就做好,如果是在發展過程中拆分,則需要改寫以前的查詢語句,會額外帶來一定的成本和風險。

3.2. 水平分表

水平分表也稱為橫向分表,就是將表中不同的資料行按照一定規律分佈到不同的資料庫表中(這些表儲存在同一個資料庫中

),以此來降低單表資料量,優化查詢效能。

這種同庫下水平分表通常有以下幾張方式:

  1. 冷熱資料分離:

    • 定期將使用較少的歷史資料遷移到對應的歷史表中,減少原表的資料量。

  2. 業務分表:

    • 在程式碼層面實現分表,資料庫中存在多張子表,但在應用上層表現為一張表。

  3. 分割槽表:

    • 通過資料庫自帶的分割槽表功能實現分表,邏輯上表現為一張表,但是底層儲存在不同的分割槽上。



水平分表能夠降低單表的資料量(分割槽表必須要帶上分割槽條件才可以提前過濾),一定程度上緩解查詢效能瓶頸。但本質上這些表還是儲存在同一個庫,或者說同一個資料庫例項、同一個DB伺服器中,所以無法避免單機資料庫效能瓶頸的問題。

四. 分片

分片也叫做Sharding,或是水平分庫分表,都是相同的概念,與上面所講到的水平分表的概念類似,唯一不同點就在於將這些拆分出來的子表儲存在不同的資料庫伺服器中。



常見分片策略

  1. RANGE:按照範圍劃分,比如按照日期或者自增鍵進行範圍劃分。

  1. HASH: 採用 hash+mod 的組合劃分資料。

分片實現方式

  1. 客戶端:

    • 在客戶端實現分片,如比較流行的分庫分表框架Sharding-JDBC,就是在驅動層實現了分片功能,對上層應用保持透明。

  2. 中間層:

    • 通過在應用與DB之間接入中介軟體(Proxy),如DBLE、MaxScale等開源中介軟體,用於實現後端資料分片與路由查詢,對上層應用保持透明。

  3. 服務端:

    • 使用某些分散式資料庫,如TiDB、SequoiaDB等開源NewSQL,其在儲存引擎層實現了資料分片功能,對上層應用保持透明。

分片能夠有效的緩解單機、單庫、單表的效能瓶頸,突破IO、連線數、硬體資源等瓶頸。但是我們一旦將資料分片後,那麼整個資料庫架構就轉換成了分散式架構,也會引發諸多問題:

  1. 分散式事務:

    • 資料分片後,原先的本地事務就演變成了分散式事務了,一般需要通過二階段或三階段提交來保證分散式事務的ACID特性,效能也因此會有一定損耗。

  2. 跨庫join:

    • 分庫分表後,不同的表分佈在不同的伺服器上,所以無法直接通過sql join來進行查詢,這時候通常會建立冗餘欄位全域性表來實現跨庫join。

  3. SQL問題:

    • 資料分片後,SQL的執行需要分發到各個節點計算,然後將結果合併後再返回,效能會有所下降,並且當SQL較為複雜時,結果準確性也有可能出現問題。這個問題也是資料分片實現中最為關鍵的點,只能不斷優化完善,無法完全解決。

  4. 自增主鍵:

    • 資料分片後,我們將不能再依賴資料庫自身的自增鍵生成機制,需要配置額外的全域性序列來保證自增主鍵的全域性唯一。

五. 小結

需要注意的是,分片(Sharding)會為資料庫維護和業務邏輯帶來一系列複雜性和效能損耗,所以除非業務量大到萬不得已,否則切莫過度設計過早優化

面對資料庫效能問題,我們可以先嚐試用以下方式來解決:

  1. 資料優化:優化SQL、索引及相關資料庫引數配置。

  2. 硬體擴充套件:提升伺服器CPU、記憶體、磁碟IOPS等硬體配置。

  3. 讀寫分離:通過讀寫分離架構提高資料庫的整體效能。

  4. 資料拆分:通過垂直拆分庫表,或水平分表來解決大表效能問題

如果上述方式仍未能奏效,才考慮最複雜的方案:資料分片