分庫分表

zhegeMaw發表於2024-08-20

一、資料庫效能影響因素

  • 資料量

MySQL單庫資料量在5000萬以內效能比較好,超過閾值後效能會隨著資料量的增大而變弱。MySQL單表的資料量是500w-1000w之間效能比較好,超過1000w效能也會下降(因為表資料為1000萬時建立的索引如果是B+Tree型別的話一般樹高在3~5之間,所以查詢的速度自然也是很快速的)。

  • 磁碟、CPU、記憶體等機器效能

因為單個服務的磁碟空間是有限制的,如果併發壓力下,所有的請求都訪問同一個節點,肯定會對磁碟IO造成非常大的影響。

  • 資料庫連線

資料庫連線是非常稀少的資源,如果一個庫裡既有使用者、商品、訂單相關的資料,當海量使用者同時操作時,資料庫連線就很可能成為瓶頸(在高併發情況下,大量請求落入資料庫,最終會導致資料庫的活躍連線數增加,進而逼近甚至達到資料庫可承載活躍連線數的閾值)。

二、分庫分表

綜述:垂直拆分更偏向於業務拆分的過程,在技術上我們更傾向於水平切分的方案

2.1 分表

按照規則把一張表劃分成多張表,使用時時根據規則找到對應資料,然後操作它。

  • 分表原因:單表資料量過大時,查詢會很慢。(索引會很大,開銷大;頻繁讀寫,加鎖操作密集)
  • 多張表還是在一臺機器上。

2.1.1 水平分表——按行進行劃分,橫著切成多個表。

  • 方案1:按範圍切分方式。可以根據某個欄位的範圍做劃分,比如訂單號欄位,從0到10000一個表,10001到20000一個表。
    • 優點:擴容比較方便,因為如果ID範圍不夠了,只需要調整規則,然後建好新表即可。  
    • 缺點:無法解決熱點問題,如果某一段資料訪問QPS特別高,就會落到單表上進行操作。 
  • 方案2:HASH取模。可以根據某個欄位的HASH取模做劃分,建議是 2^n,這樣可以方便在擴容的時儘可能的少遷移資料。比如將一個使用者表分成8個子表,可以取使用者id,然後hash後取8的模,從而分配到不同的資料庫上。
    • 優點:資料雜湊均衡,每個表的資料量大致相同;請求壓力雜湊均衡,不存在訪問熱點。
    • 缺點:擴容不方便,需要資料遷移。這種劃分一旦確定後,就無法改變子表數量了。
  • 方案3:根據業務(地理/國籍/型別等)劃分。比如按照華東,華南,華北這樣來區分業務表,或者安卓使用者,IOS使用者等來區分使用者表。
  • 方案4:按照時間切分,比如將6個月前,甚至一年前的資料切出去放到另外的一張表,因為隨著時間流逝,這些表的資料被查詢的機率變小,所以沒必要和“熱資料”放在一起,這個也是“冷熱資料分離”。

2.1.2 垂直分表——按列進行劃分,將不常用的屬性列拆分出來。

  • 方案1:按活躍度劃分。將“不常用”或者“資料量大”的欄位拆分到“擴充套件表”上。這樣避免查詢時,資料量太大造成的“跨頁”問題。

2.2 分庫

將一個庫分成多個庫,並部署在多個伺服器上。

  • 分庫原因:單機的機器效能(磁碟IO瓶頸)有限,分庫可以減小單機的壓力、突破效能瓶頸。
2.2.1 水平分庫
  • 將單個庫中的表作水平分表,然後將子表分別置於不同的子庫當中,獨立部署。

  • 因為庫中內容的主要載體是表,所以水平分庫和水平分表基本上如影隨形。

2.2.2 垂直分庫
  • 以表為依據,按照業務歸屬不同,將不同的表拆分到不同的庫中。

2.3 具體分庫分表

首先考慮:資料量、併發量

  • 資料量大,就分表;
  • 併發高,就分庫。

一般情況下,我們的方案都需要同時做分庫分表,這時候分多少個庫,多少張表,分別用預估的併發量和資料量來計算就可以了。

參考資料

https://zhuanlan.zhihu.com/p/342814592

相關文章