他們常說的「分庫分表」是怎麼回事?

他們常說的「分庫分表」是怎麼回事?

寫在前面
爲了提高數據庫的處理能力,咱們把單庫擴展成多庫,並經過更新同步機制(即Replication)來保證多份數據的一致性。如此這般,數據庫的擴展難題彷佛已經順利解決了數據庫

然而,在 Replication 方案下,每一個數據庫都持有一份完整數據,基於全量數據提供增刪改查服務,單庫的性能瓶頸仍然存在,並將成爲限制系統擴展性的關鍵因素緩存

一.單庫的性能瓶頸
單機的硬件資源是有限的,所以單庫的處理能力也是有限的:安全

容量有限:數據量可能大到單庫沒法容納架構

性能有限:單庫的讀寫性能一樣受數據量影響,查詢/更新愈來愈慢併發

單靠加機器/加庫顯然沒法直接解決單機/單庫的性能問題,除非進一步打破庫的邊界,把單庫拆分紅多庫(而不僅是複製多份)app

P.S.理論上,Web 應用層也面臨一樣的問題,卻未曾據說過一個 Web 服務龐大到單機沒法部署,這是由於Web 服務在設計之初就會考慮職責劃分與解耦,以便各部分可以獨立部署、獨立擴展,從 20 年前的 SOA(即面向服務架構,包括微服務架構(Microservices)等變體)起即是如此ide

二.分區(Partitioning)
爲了不單庫性能成爲系統可擴展性的瓶頸,一般把邏輯數據庫(或其組成元素,例如數據表)拆分紅各個獨立部分,這種作法稱爲分區(Partitioning):微服務

A partition is a division of a logical database or its constituent elements into distinct independent parts.

(摘自Partition (database))性能

就像微服務架構中把單體應用(Monolithic application)拆分紅一組小型服務同樣,咱們經過分區把單庫拆分紅一組(數據規模)更小的庫,各自處理一部分數據,共同分擔流量,主要優點體如今:優化

可擴展性:把單庫數據拆分到多庫後,系統的可擴展性再也不受限於單庫性能,數據庫層「無限」擴展成爲了可能

性能:單庫數據量減小,數據操做更快,甚至容許多庫並行操做

安全性:能夠針對(拆出去的)敏感數據,採起更強的安全控制

靈活性:能夠對不一樣的庫(好比按數據重要性)採用不一樣的監控、備份策略,以縮減成本,提高管理效率。或者對不一樣類型的數據選用不一樣的存儲服務,好比大型二進制內容放到 blob 存儲中,更復雜的數據能夠存放在文檔數據庫中

可用性:把數據分散放到多個籃子裏,可以避免單點故障,而且單庫故障僅影響一部分數據

具體的,有 3 種拆分策略:

水平分區(Horizontal partitioning,也叫 Sharding):按行拆分,把不一樣的行放入不一樣的表中

垂直分區(Vertical partitioning):按列拆分,把一些列放到其它表中

按功能分區(Functional partitioning,有時也叫 Federation):按業務功能拆分,把業務領域中屬於相同界限上下文(Bounded Context)的數據放在一塊兒

固然,這 3 種策略並不衝突,能夠結合使用

P.S.關於領域驅動設計(Domain-Driven Design),以及界限上下文的更多信息,見去中心化數據管理(Decentralized Data Management)

三.水平分區
他們常說的「分庫分表」是怎麼回事?

水平分區,即分片(Sharding)。每片(shard)都是原數據的一個子集,共同構成完整的數據集:

A database shard is a horizontal partition of data in a database or search engine. Each individual partition (or server) acts as the single source for this subset of data.

(摘自Shard (database architecture))

與垂直分區相比,水平分區最大的特色是schema 保持不變:

Each partition is a separate data store, but all partitions have the same schema.

就像把一張表橫向切幾刀,分紅幾段小表,它們的表結構(字段等)徹底一致

這種橫向切分減小了單庫所需存儲的數據量,以及所需承載的流量/操做,另外一方面,還減小了資源爭用(contention),有助於提高性能

shard key 的選取
具體操做上,關鍵在於如何選取 shard key(按哪一個字段的什麼特徵來分片),儘量保證負載被均勻地分散到每一片上

注意,均勻並不意味着要求每一片的數據量均等,重點是均分流量(有些片可能數據量很大,但訪問量卻很低)

同時還要避免產生「熱點」,好比按姓氏首字母對用戶信息進行分片其實是不均勻的,由於有些字母更常見,此時按用戶 ID 哈希值來分片可能更均勻些

四.垂直分區
另外一種拆分方式是垂直分區,將一些列(字段)拆分到其它表中:
他們常說的「分庫分表」是怎麼回事?

多用於減小 I/O、下降性能成本,好比,按使用頻率把經常使用字段和不經常使用的字段分開

比起水平分區,垂直分區的關鍵優點在於把信息拆的更細,進而容許一些針對性的優化,好比把不常常變化的數據拆分出來,丟到緩存中,把照片等大型二進制內容拆出去單獨存放,或者對部分敏感數據進行鍼對性的安全控制,另外一方面,細粒度的數據劃分也可以消除一些併發訪問,下降併發訪問量

五.按功能分區
此外,還能夠結合具體應用場景,按業務功能拆分:

他們常說的「分庫分表」是怎麼回事?

把不相干的數據剔除出去(把緊密相關的數據放到一塊兒),有助於增強數據隔離,提高數據訪問性能,好比把客戶信息和商品庫存信息分開

六.分區的代價
把單庫拆成多庫,雖然可以解決數據庫的擴展性難題,但也引起了一些新問題:

連表查詢慢:儘可能避免跨分區 join、或者考慮並行查詢

全表查詢慢:對於須要掃描全量數據的查詢操做,即使有並行優化也慢,能夠經過垂直分區、按功能分區來定位目標分區,避免全表查詢,至於水平分區,能夠在應用層維護一張映射表,加快分區定位

不支持事務操做:將事務操做交由應用層來處理

負載不勻致使分區效果大打折扣:考慮增長監控,並根據分析預測按期調整

誠然,其中有些問題沒有很是漂亮的解決方案,實際應用中更多的是面向特定場景的權衡取捨

參考資料
Horizontal, vertical, and functional data partitioning

How Sharding Works

相關文章
相關標籤/搜索