一文搞懂MySQL資料庫分庫分表

如果資料量過大,大家一般會分庫分表。分庫需要注意的內容比較少,但分表需要注意的內容就多了。

工作這幾年沒遇過資料量特別大的業務,那些過億的資料,因為索引設定合理,單表效能沒有影響,所以實戰中一直沒用過分表。最近手裡有個專案,預估資料量會很大,分表方案是選項之一,趁著這次機會,把分表的內容整理一下。

這次要講的主要是水平分庫分表,其它種類的分庫、分表比較容易理解。後面如果不詳細說明,都指水平分庫分表。

1。基礎知識

1。1分庫分表定義

1。1。1分庫

垂直分庫

:按照業務模組進行切分,將不同模組的表切分到不同的資料庫中。

如電商系統有電商資料庫,按照業務模組可以分為使用者庫、商品庫、訂單庫,這些都可以當做獨立資料庫,不需要放到一起。好處是既能獨立變更,又能隔絕相互影響。

一文搞懂MySQL資料庫分庫分表

1。1。2分表

垂直分表

:也就是“大表拆小表”,基於列欄位進行的。一般是因為表設計不合理,需要進行拆分。

如一張表存放學生、老師、課程、成績資訊,最好拆分為學生表、課程表、成績表。

水平分表

:針對資料量巨大的單張表(比如訂單表),按照某種規則(

RANGE

HASH取模

等),切分到多張表裡面去。但是這些表還是在同一個庫中,所以

庫級別的資料庫操作還是有IO瓶頸

。不建議採用。

水平分庫分表

:將單張表的資料切分到多個伺服器上去,每個伺服器具有相應的庫與表,只是表中資料集合不同。水平分庫分表能夠有效的緩解單機和單庫的效能瓶頸和壓力,突破IO、連線數、硬體資源等的瓶頸。

一文搞懂MySQL資料庫分庫分表

1。2分割槽與分片的區別

分表時經常能看到兩個名詞:分割槽和分片。這兩個詞都是指將大表的資料分成多塊,但兩者還是有本質區別的。

Sharding(分片) 的思想從分割槽的思想而來,但資料庫分割槽基本上是資料物件級別的處理,比如表和索引的分割槽,每個子資料集上能夠有不同的物理儲存屬性,還是單個數據庫範圍內的操作,而 Sharding 是能夠跨資料庫,甚至跨越物理機器的。

MySQL5。1提供的分割槽(Partition)功能確實可以實現表的分割槽,但是這種分割槽是侷限在單個數據庫範圍裡的,它不能跨越伺服器的限制。

一文搞懂MySQL資料庫分庫分表

我們在分表的時候,一般使用的是分片方案,即資料存放在多個物理機器。

1。3分片策略

分片規則一般有如下:

1。3。1按照雜湊切片

mod-long:用於分割槽列為數值的hash分割槽分片列 id=分割槽列值 mod 分片數

mod-long-by-hash:用於分割槽列為字串的hash分割槽分片列id=hash(分割槽列值) mod 分片數

1。3。2按照範圍切片

range:建表時建立分割槽規則,根據分割槽規則就可以確定分割槽列的值在哪個分割槽上一般分割槽列為時間或者數值,如

date_range:

0

1000000

1

2000000

2

3000000

3

4000000

4

: maxvalue

如果分割槽列值為1500000,則資料放到1號分片上。

2。分庫分表中介軟體

需要使用者感知不到這是分片表,使用時需要和正常表一樣,一般需要引入中介軟體。

操作分片表一般有三種方式:

2。1客戶端分片

所謂的客戶端分片即在使用資料庫的應用層直接操作分片邏輯,分片規則需要在同一個應用的多個節點間進行同步,每個應用層嵌入一個操作切片的邏輯實現。如噹噹網的Sharding JDBC。

一文搞懂MySQL資料庫分庫分表

2。2代理分片

代理分片就是在應用層和資料庫層之間新增一個代理層,把分片的路由規則配置在代理層,代理層對外提供與JDBC相容的介面給應用層,在業務實現之後,在代理層配置路由規則即可。如Mycat就是基於此種解決方案來實現的。

一文搞懂MySQL資料庫分庫分表

2。3支援事務的分散式資料庫

支援分散式事務的框架,目前有OceanBase、TiDB框架,這些框架將可伸縮特定和分散式事務的實現包裝到了分散式資料庫內部實現,對使用者透明,使用者不需要直接控制這些特性,但是對事務的支援不如關係型資料,適合大資料日誌系統、統計系統、查詢系統、社交網站等。

2。4說明

支援事務的分散式資料庫算另一種選型了,和MySQL已經沒有關係。

對於客戶端分片和代理分片,目前工作過的兩家公司用的都是代理方式,一家用的是MyCAT,一家用的Dbatman。客戶端分片方式沒有接觸過。這兩種的區別為:

一文搞懂MySQL資料庫分庫分表

3。分散式事務

分片意味資料分佈在多臺物理機器上,引入分散式事務問題。我們將單表的資料切片後儲存在多個數據庫甚至是多個數據庫例項中,所以依靠資料庫本身的事務機制不能滿足需要,這時就需要用到分散式事務來解決。關於分散式事務的相關內容可以看分散式系統與一致性協議。

這裡不細講分散式事務如何處理,後面會單獨寫篇文章。我們聊一下分散式事務會對操作MySQL產生什麼影響。

既然知道引入了分散式事務問題,那麼操作MySQL的時候,肯定不能和單表一樣進行操作。不同中介軟體能力不一樣,所以需要單獨分析,我以Dbatman為例,闡述使用上的區別。

1。分片版本不維護自增與主鍵唯一,業務可自行維護唯一鍵

意味不同分片的主鍵id會重複

2。不支援跨分片事務寫,可以跨分片事務讀

如果確保事務操作的內容在一個分片內,就不是分散式事務,和單機行為一致

一個事務涉及多個分片叫跨節點事務,單分片事務支援

3。update和insert必須帶分片列

總結一下就是操作同一個分片沒影響,操作不同分片需要看中介軟體支援不支援。

如果使用中介軟體,即使同一個分片,儘量不要用特殊的SQL,有些中介軟體可能無法支援,如insert not exists。

4。是否選擇分庫分表

選擇做分庫分表,考慮的幾個要素是:

空間方面:單個物理例項無法支撐資料儲存需求,單臺物理機無法繼續透過加盤的方式擴容

主庫效能:受限於單個主庫的CPU/記憶體/磁碟IOPS的影響,接近或者達到上限後,需要拆分

容災方面:減少單個主庫宕機對於寫入的影響。

針對以上3點,我們還可以多考慮一下,有沒有更合適的方案

1。空間方面:

刪除歷史資料清空空間

修改儲存模型降低對於MySQL磁碟的佔用

改用空間壓縮比更高的儲存引擎

2。主庫效能:

可以透過讀寫分離的方式,降低對於寫庫的讀請求量,從而提升對於寫入的支撐。

最佳化資料寫入模型,減少批次寫入(削峰)

3。容災方面:

如果業務對於讀高可用要求比較高,一般建議是做讀寫分離,將重要的請求路由至讀庫。讀庫數量一般會比寫庫多N個,在代理層面會做容災的自動切換。

從叢集整體的角度看,分庫分表實際上是會擴大故障率,假設單臺物理機的SLA是99。99%,那麼2臺物理機的SLA就是99。98(約數), 10臺物理機的SLA就只剩下99。90%了。平均每年的故障時間也會從52分鐘提升到525分鐘。所以在有些場景下,單個節點故障可能會導致代理整個不可用,從而放大故障的影響範圍。

5。設計

現在專案需求為:

生成唯一碼,碼值為整數

碼值需要批次插入資料庫

對碼的更新操作都是單條處理,而且對碼值進行操作需要進行記錄

最終數量不定,長遠看資料量會很大

基於上面的需求,做如下設計:

以碼值為主鍵,自己控制主鍵唯一

碼錶使用range進行分片,如分片範圍為01億,1億2億

碼錶的操作記錄表同樣使用range進行分片,分片範圍和碼錶一致

透過這種設計能夠實現需求。

但計算後發現,單表能存百億條資料,而且索引設計比較合理,業務邏輯相對簡單,無高併發請求,單表好像也可以搞。

總結

正常情況下,我們一般需要做水平分庫分表,這就涉及到分散式事務,一定要考慮清楚是否能滿足自己的需求、想用的SQL語句是否都能支援,考慮一下是否還有別的方案。

關於中介軟體的實現原理,瞭解的不是很深,後面有時間的話,可以學習一下。

資料

MySQL 分庫分表方案,總結的非常好!

MySQL之分庫分表(MyCAT實現)

Mysql分庫分表實戰(一)——一文搞懂Mysql資料庫分庫分表

MySql分表、分庫、分片和分割槽知識

資料庫分片(Sharding)與分割槽(Partition)的區別(轉)

資料庫分庫分表中介軟體對比(很全)

分庫分表中介軟體

分庫分表:中介軟體方案對比

XA 分散式事務原理

最後

大家如果喜歡我的文章,可以關注我的公眾號(程式設計師麻辣燙)

我的個人部落格為:https://shidawuhen。github。io/

往期文章回顧:

招聘

位元組跳動|內推大放送

位元組跳動|今日頭條廣州服務端研發工程師內推

位元組跳動|抖音電商急招上海前端開發工程

位元組跳動|抖音電商上海資深服務端開發工程師-交易

位元組跳動|抖音電商武漢服務端(高階)開發工程師

位元組跳動|飛書大客戶產品經理內推咯

位元組跳動|抖音電商服務端技術崗位虛位以待

位元組跳動招聘專題

設計模式

Go設計模式(15)-門面模式

Go設計模式(14)-介面卡模式

Go設計模式(13)-裝飾器模式

Go設計模式(12)-橋接模式

Go設計模式(11)-代理模式

Go設計模式(10)-原型模式

Go設計模式(9)-建造者模式

Go設計模式(8)-抽象工廠

Go設計模式(7)-工廠模式

Go設計模式(6)-單例模式

Go設計模式(5)-類圖符號表示法

Go設計模式(4)-程式碼編寫最佳化

Go設計模式(4)-程式碼編寫

Go設計模式(3)-設計原則

Go設計模式(2)-面向物件分析與設計

Go設計模式(1)-語法

語言

再也不怕獲取不到Gin請求資料了

一文搞懂pprof

Go工具之generate

Go單例實現方案

Go通道實現原理

Go定時器實現原理

Beego框架使用

Golang原始碼BUG追查

Gin框架簡潔版

Gin原始碼剖析

架構

分頁複選設計的坑

支付接入常規問題

限流實現2

秒殺系統

分散式系統與一致性協議

微服務之服務框架和註冊中心

淺談微服務

限流實現1

CDN請求過程詳解

常用快取技巧

如何高效對接第三方支付

演算法總結

儲存

MySQL開發規範

Redis實現分散式鎖

事務原子性、一致性、永續性的實現原理

InnoDB鎖與事務簡析

網路

HTTP2。0基礎教程

HTTPS配置實戰

HTTPS連線過程

TCP效能最佳化

工具

GoLand實用技巧

根據mysql表自動生成go struct

Markdown編輯器推薦-typora

讀書筆記

《毛選》推薦

原則

資治通鑑

敏捷革命

如何鍛鍊自己的記憶力

簡單的邏輯學-讀後感

熱風-讀後感

論語-讀後感

孫子兵法-讀後感

思考

對寫部落格的一些思考

晚上打119的經歷

為動員一切力量爭取勝利而鬥爭

反對自由主義

實踐論

評價自己的標準

2020部落格總結

服務端團隊假期值班方案

專案流程管理

對專案管理的一些看法

對產品經理的一些思考

關於程式設計師職業發展的思考

關於程式碼review的思考