第01章 高性能架構模式
網際網路業務興起之後,海量使用者加上海量資料的特點,單個資料庫伺服器已經難以滿足業務需要,必須考慮資料庫叢集的方式來提升性能。高性能資料庫叢集的
第一種方式是“讀寫分離”
,
第二種方式是“資料庫分片”
。
1、讀寫分離架構
讀寫分離原理: 讀寫分離的基本原理是将資料庫讀寫操作分散到不同的節點上,下面是其基本架構圖:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CO0EzMhNDZ1UmM2gTOkVjN0QWY4M2N3ImMkhTZkFzM28CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
讀寫分離的基本實作:
-
,能夠有效的避免由資料更新導緻的行鎖,使得整個系統的查詢性能得到極大的改善。主庫負責處理事務性的增删改操作,從庫負責處理查詢操作
- 讀寫分離是
,根據 SQL 語義的分析
。将讀操作和寫操作分别路由至主庫與從庫
- 通過
的配置方式,可以将查詢請求均勻的分散到多個資料副本,能夠進一步的提升系統的處理能力。一主多從
- 使用
的方式,不但能夠提升系統的吞吐量,還能夠提升系統的可用性,可以達到在任何一個資料庫當機,甚至磁盤實體損壞的情況下仍然不影響系統的正常運作。多主多從
下圖展示了根據業務需要,将使用者表的寫操作和讀操路由到不同的資料庫的方案:
CAP 理論:
CAP 定理(CAP theorem)又被稱作布魯爾定理(Brewer’s theorem),是加州大學伯克利分校的計算機科學家埃裡克·布魯爾(Eric Brewer)在 2000 年的 ACM PODC 上提出的一個猜想。
對于設計分布式系統的架構師來說,CAP 是必須掌握的理論。
在一個
分布式系統中
,當涉及讀寫操作時,隻能保證一緻性(Consistence)、可用性(Availability)、分區容錯性(Partition Tolerance)三者中的兩個,另外一個必須被犧牲。
- C 一緻性(Consistency):對某個指定的用戶端來說,讀操作保證能夠傳回最新的寫操作結果
- A 可用性(Availability):非故障的節點在合理的時間内傳回合理的響應
(不是錯誤和逾時的響應)
- P 分區容忍性(Partition Tolerance):當出現網絡分區後
,系統能夠繼續“履行職責”(可能是丢包,也可能是連接配接中斷,還可能是擁塞)
CAP特點:
- 在實際設計過程中,每個系統不可能隻處理一種資料,而是包含多種類型的資料,
有的資料必須選擇 CP,有的資料必須選擇 AP,分布式系統理論上不可能選擇 CA 架構。
- CP:如下圖所示,
,當發生分區現象後,N1 節點上的資料已經更新到 y,但由于 N1 和 N2 之間的複制通道中斷,資料 y 無法同步到 N2,N2 節點上的資料還是 x。為了保證一緻性
這種處理方式這時用戶端 C 通路 N2 時,N2 需要傳回 Error,提示用戶端 C“系統現在發生了錯誤”,
(Availability)的要求,是以 CAP 三者隻能滿足 CP。違背了可用性
- CP:如下圖所示,
- AP:如下圖所示,
,當發生分區現象後,N1 節點上的資料已經更新到 y,但由于 N1 和 N2 之間的複制通道中斷,資料 y 無法同步到 N2,N2 節點上的資料還是 x。為了保證可用性
,而實際上目前最新的資料已經是 y 了,這就這時用戶端 C 通路 N2 時,N2 将目前自己擁有的資料 x 傳回給用戶端 C 了
(Consistency)的要求了,是以 CAP 三者隻能滿足 AP。注意:這裡 N2 節點傳回 x,雖然不是一個“正确”的結果,但是一個“合理”的結果,因為 x 是舊的資料,并不是一個錯亂的值,隻是不是最新的資料而已。不滿足一緻性
- CAP 理論中的
,在資料複制的過程中,節點N1 和節點 N2 的資料并不一緻(強一緻性)。即使無法做到C 在實踐中是不可能完美實作的
,但應用可以采用适合的方式達到強一緻性
。具有如下特點:最終一緻性
- 基本可用(Basically Available):分布式系統在出現故障時,允許損失部分可用性,即保證核心可用。
- 軟狀态(Soft State):允許系統存在中間狀态,而該中間狀态不會影響系統整體可用性。這裡的中間狀态就是 CAP 理論中的資料不一緻。
-
最終一緻性(Eventual Consistency):系統中的所有資料副本經過一定時間後,最終能夠達到一緻的狀态。
2、資料庫分片架構
讀寫分離的問題:
讀寫分離分散了資料庫讀寫操作的壓力,但沒有分散存儲壓力,為了滿足業務資料存儲的需求,就需要
将存儲分散到多台資料庫伺服器上
。
資料分片:
将存放在單一資料庫中的資料分散地存放至多個資料庫或表中,以達到提升性能瓶頸以及可用性的效果。 資料分片的有效手段是對關系型資料庫進行
分庫和分表
。資料分片的拆分方式又分為
垂直分片和水準分片
。
2.1、垂直分片
垂直分庫:
按照業務拆分的方式稱為垂直分片,又稱為縱向拆分
,它的核心理念是專庫專用。 在拆分之前,一個資料庫由多個資料表構成,每個表對應着不同的業務。而拆分之後,則是按照業務将表進行歸類,分布到不同的資料庫中,進而将壓力分散至不同的資料庫。
下圖展示了根據業務需要,将使用者表和訂單表垂直分片到不同的資料庫的方案:
垂直拆分可以緩解資料量和通路量帶來的問題,但無法根治。
如果垂直拆分之後,表中的資料量依然超過單節點所能承載的門檻值,則需要水準分片來進一步處理。
垂直分表:
垂直分表适合将表中某些不常用的列,或者是占了大量空間的列拆分出去。
假設我們是一個婚戀網站,使用者在篩選其他使用者的時候,主要是用 age 和 sex 兩個字段進行查詢,而 nickname 和 description 兩個字段主要用于展示,一般不會在業務查詢中用到。description 本身又比較長,是以我們可以将這兩個字段獨立到另外一張表中,這樣在查詢 age 和 sex 時,就能帶來一定的性能提升。
垂直分表引入的複雜性主要展現在表操作的數量要增加。例如,原來隻要一次查詢就可以擷取 name、age、sex、nickname、description,現在需要兩次查詢,一次查詢擷取 name、age、sex,另外一次查詢擷取 nickname、description。
水準分表适合表行數特别大的表,水準分表屬于水準分片
。
2.2、水準分片
水準分片又稱為橫向拆分。
相對于垂直分片,它不再将資料根據業務邏輯分類,而是通過某個字段(或某幾個字段),根據某種規則将資料分散至多個庫或表中,每個分片僅包含資料的一部分。 例如:根據主鍵分片,偶數主鍵的記錄放入 0 庫(或表),奇數主鍵的記錄放入 1 庫(或表),如下圖所示。
單表進行切分後,是否将多個表分散在不同的資料庫伺服器中,可以根據實際的切分效果來确定。
- **水準分表:**單表切分為多表後,新的表即使在同一個資料庫伺服器中,也可能帶來可觀的性能提升,如果性能能夠滿足業務要求,可以不拆分到多台資料庫伺服器,畢竟業務分庫也會引入很多複雜性;
- **水準分庫:**如果單表拆分為多表後,單台伺服器依然無法滿足性能要求,那就需要将多個表分散在不同的資料庫伺服器中。
阿裡巴巴Java開發手冊:
【推薦】單表行數超過 500 萬行或者單表容量超過 2GB,才推薦進行分庫分表。
說明:如果預計三年後的資料量根本達不到這個級别,
。
請不要在建立表時就分庫分表
3、讀寫分離和資料分片架構
下圖展現了将資料分片與讀寫分離一同使用時,應用程式與資料庫叢集之間的複雜拓撲關系。
4、實作方式
讀寫分離和資料分片具體的實作方式一般有兩種:
程式代碼封裝
和
中間件封裝
。
4.1、程式代碼封裝
程式代碼封裝指在代碼中抽象一個
資料通路層(或中間層封裝)
,實作讀寫操作分離和資料庫伺服器連接配接的管理。
其基本架構是: 以讀寫分離為例
4.2、中間件封裝
中間件封裝指的是
獨立一套系統出來
,實作讀寫操作分離和資料庫伺服器連接配接的管理。對于業務伺服器來說,通路中間件和通路資料庫沒有差別,在業務伺服器看來,中間件就是一個資料庫伺服器。
基本架構是: 以讀寫分離為例
4.3、常用解決方案
Apache ShardingSphere(程式級别和中間件級别)
MyCat(資料庫中間件)