2021-01-29 分類: 網站建設
隨著互聯網產業的蓬勃發展,在互聯網應用上產生的數據也是與日俱增。產生大量的交易記錄和行為記錄,它們的存放和分析是我們需要面對的問題。
用 ID 取模的分表方式分配記錄
ID 分別為 01-04 的四條記錄,如果分配到 3 個表中,那么對 3 取模得到的余數分別是:
當然這里只是一個例子,實際情況需要對 ID 做 Hash 之后再計算。同時還可以針對不同表所在的不同的數據庫的資源來設置存儲數據的多少。針對每個表所在的庫的資源設置權值。
用這種方式存放數據以后,在訪問具體數據的時候需要通過一個 Mapping Table 獲取對應要響應的數據來自哪個數據表。目前比較流行的數據庫中間件已經幫助我們實現了這部分的功能。
也就是說不用大家自己去建立這個 Mapping Table,在做查詢的時候中間件幫助你實現了 Mapping Table 的功能。所以,我們這里只需要了解其實現原理就可以了。
按照時間做的數據分表
需要注意的是由于分表造成一系列記錄級別的問題,例如 Join 和 ID 生成,事務處理,同時存在這些表需要跨數據庫的可能性:
Snowflake 示意圖
排序/分頁:數據分配到水平的幾個表中的時候,做排序和分頁或者一些集合操作是不容易的。
這里根據經驗介紹兩種方法。對分表的數據先進行排序/分頁/聚合,再進行合并。對分表的數據先進行合并再做排序/分頁/聚合。
事務:存在分布式事務的可能,需要考慮補償事務或者用 TCC(Try Confirm Cancel)協助完成,這部分的內容我們下面會為大家介紹。
數據分庫
說完了分表,再來談談分庫。每個物理數據庫支持數據都是有限的,每一次的數據庫請求都會產生一次數據庫鏈接,當一個庫無法支持更多訪問的時候,我們會把原來的單個數據庫分成多個,幫助分擔壓力。
這里有幾類分庫的原則,可以根據具體場景進行選擇:
單個表會分到不同的數據庫中
通常數據分庫之后,每一個數據庫包含多個數據表,多個數據庫會組成一個 Cluster/Group,提高了數據庫的可用性,并且可以把讀寫做分離。
Master 庫主要負責寫操作,Slave 庫主要負責讀操作。在應用訪問數據庫的時候會通過一個負載均衡代理,通過判斷讀寫操作把請求路由到對應的數據庫。
如果是讀操作,也會根據數據庫設置的權重或者平均分配請求。另外,還有數據庫健康監控機制,定時發送心跳檢測數據庫的健康狀況。
如果 Slave 出現問題,會啟動熔斷機制停止對其的訪問;如果 Master 出現問題,通過選舉機制選擇新的 Master 代替。
兩個集群中的兩個主從,分別擴展成四個集群中的四個
從兩個集群擴展成四個集群
雙寫數據庫擴容
在沒有數據庫主從配置的情況下的擴容,假設有數據庫 M1 M2 如下圖:
擴展前的兩個主庫
需要對目前的兩個數據庫做擴容,擴容之后是 4 個庫如下圖。新增的庫是 M3,M4 路由的方式分別是 ID%2=0 和 ID%2=1。
新增兩個主庫
這個時候新的數據會同時進入 M1 M2 M3 M4 四個庫中,而老數據的使用依舊從 M1 M2 中獲取。
與此同時,后臺服務對 M1 M3,M2 M4 做數據同步,建議先做全量同步再做數據校驗。
老庫給新庫做數據同步
當完成數據同步之后,四個庫的數據保持一致了,修改負載均衡代理的配置為 ID%4 的模式。此時擴容就完成了,從原來的 2 個數據庫擴展成 4 個數據庫。
當然會存在部分的數據冗余,需要像上面一個方案一樣通過后臺服務刪除這些冗余數據,刪除的過程不會影響業務。
數據同步以后做 Hash 切分
分布式事務原理
架構設計的分表分庫帶來的結果是我們不得不考慮分布式事務,今天創新互聯來看看分布式事務需要記住哪兩個原理。
CAP
互聯網應用大多會使用分表分庫的操作,這個時候業務代碼很可能會同時訪問兩個不同的數據庫,做不同的操作。同時這兩個操作有可能放在同一個事務中處理。
這里引出分布式系統的 CAP 理論,他包括以下三個屬性:
一致性(Consistency):分布式系統中的所有數據,同一時刻有同樣的值。
業務代碼往數據庫 01 這個節點寫入記錄 A,數據庫 01 把 A 記錄同步到數據庫 02,業務代碼再從數據庫 02 中讀出的記錄也是 A。那么兩個數據庫存放的數據就是一致的。
一致性簡圖
可用性(Availability):分布式系統中一部分節點出現故障,分布式系統仍舊可以響應用戶的請求。
假設數據庫 01 和 02 同時存放記錄 A,由于數據庫 01 掛掉了,業務代碼不能從中獲取數據。
那么業務代碼可以從數據庫 02 中獲取記錄 A。也就是在節點出現問題的時候,還保證數據的可用性。
可用性簡圖
分區容錯性(Partition tolerance):假設兩個數據庫節點分別在兩個區,而兩個區的通訊發生了問題。就不能達成數據一致,這就是分區的情況,我就需要從 C 和 A 之間做出選擇。
是選擇可用性(A),獲取其中一個區的數據。還是選擇一致性(C),等待兩個區的數據同步了再去獲取數據。
這種情況的前提是兩個節點的通訊失敗了,寫入數據庫 01 記錄的時候,需要鎖住數據庫 02 記錄不讓其他的業務代碼修改,直到數據庫 01 記錄完成修改。因此 C 和 A 在此刻是矛盾的。兩者不能兼得。
BASE
Base 原理廣泛應用在數據量大,高并發的互聯網場景。一起來看看都包含哪些:
基本可用(Basically Available): 不會因為某個節點出現問題就影響用戶的請求。
即使在流量激增的情況下,也會考慮通過限流降級的辦法保證用戶的請求是可用的。
比如,電商系統在流量激增的時候,資源會向核心業務傾斜,其他的業務降級處理。
軟狀態( Soft State):一條數據如果存在多個副本,允許副本之間同步的延遲,在較短時間內能夠容忍不一致。這個正在同步并且還沒有完成同步的狀態稱為軟狀態。
最終一致性( Eventual Consistency):最終一致性是相對于強一致性來說的,強一致性是要保證所有的數據都是一致的,是實時同步。
而最終一致性會容忍一小段時間數據的不一致,但過了這段時間以后數據會保證一致。其包含以下幾種“一致性”:
①因果一致性(Causal Consistency)
如果有兩個進程 1 和 2 都對變量 X 進行操作,“進程 1” 寫入變量 X,“進程 2”需要讀取變量 X,然后用這個 X 來計算 X+2。
這里“進程 1”和“進程 2” 的操作就存在因果關系。“進程 2” 的計算依賴于進程 1 寫入的 X,如果沒有 X 的值,“進程 2”無法計算。
②讀己之所寫(Read Your Writes)
“進程 1”寫入變量 X 之后,該進程可以獲取自己寫入的這個值。
進程寫入的值的同時獲取值
③會話一致性(Session Consistency)
如果一個會話中實現來讀己之所寫。一旦數據更新,客戶端只要在同一個會話中就可以看到這個更新的值。
④單調寫一致性(Monotonic Write Consistency)
“進程 1”如果有三個操作分別是 1,2,3。“進程 2”有兩個操作分別是 1,2。當進程請求系統時,系統會保證按照進程中操作的先后順序來執行。
分布式事務方案
說完了分布式的原理,再來提一下分布式的方案。由于所處場景不一樣,所以方案也各有不同,這里介紹兩種比較流行的方案,兩段式和 TCC(Try,Confirm,Cancel)。
兩階段提交
顧名思義,事務會進行兩次提交。這里需要介紹兩個概念,一個是事務協調者,也叫事物管理器。
它是用來協調事務的,所有事務什么時候準備好了,什么時候可以提交了,都由它來協調和管理。
另一個是參與者,也叫資源管理器。它主要是負責處理具體事務的,管理者需要處理的資源。例如:訂票業務,扣款業務。
第一階段(準備階段):事務協調者(事務管理器)給每個參與者(資源管理器)發送 Prepare 消息,發這個消息的目的是問“大家是不是都準備好了,我們馬上就要執行事務了”。
參與者會根據自身業務和資源情況進行檢查,然后給出反饋。這個檢查過程根據業務內容不同而不同。
例如:訂票業務,就要檢查是否有剩余票。扣款業務就要檢查,余額是否足夠。一旦檢查通過了才能返回就緒(Ready)信息。
否則,事務將終止,并且等待下次詢問。由于這些檢查需要做一些操作,這些操作可能再之后回滾時用到,所以需要寫 redo 和 undo 日志,當事務失敗重試,或者事務失敗回滾的時候使用。
第二階段(提交階段):如果協調者收到了參與者失敗或者超時的消息,會給參與者發送回滾(rollback)消息;否則,發送提交(commit)消息。兩種情況處理如下:
情況 1,當所有參與者均反饋 yes,提交事務:
情況 2,當有一個參與者反饋 no,回滾事務:
TCC(Try,Confirm,Cancel)
對于一些要求高一致性的分布式事務,例如:支付系統,交易系統,我們會采用 TCC。
它包括,Try 嘗試,Confirm 確認,Cancel 取消。看下面一個例子能否幫助大家理解。
假設我們有一個轉賬服務,需要把“A 銀行”“A 賬戶”中的錢分別轉到“B銀行”“B 賬戶”和“C 銀行”“C 賬戶”中去。
假設這三個銀行都有各自的轉賬服務,那么這次轉賬事務就形成了一次分布式事務。
我們來看看用 TCC 的方式如何解決:
首先是 Try 階段,主要檢測資源是否可用,例如檢查賬戶余額是否足夠,緩存,數據庫,隊列是否可用等等。
并不執行具體的邏輯。如上圖,這里從“A 賬戶”轉出之前要檢查,賬戶的總金額是否大于 100,并且記錄轉出金額和剩余金額。
對于“B 賬戶”和“C 賬戶”來說需要知道賬戶原有總金額和轉入的金額,從而可以計算轉入后的金額。
這里的交易數據庫設計除了有金額字段,還要有轉出金額或者轉入金額的字段,在 Cancel 回滾的時候使用。
如果 Try 階段成功,那么就進入 Confirm 階段,也就是執行具體的業務邏輯。
這里從“A 賬戶”轉出 100 元成功,剩余總金額=220-100=120,把這個剩余金額寫入到總金額中保存,并且把交易的狀態設置為“轉賬成功”。
“B 賬戶”和“C 賬戶”分別設置總金額為 80=50+30 和 130=60+70,也把交易狀態設置為“轉賬成功”。則整個事務完成。
如果 Try 階段沒有成功,那么服務 A B C 都要做回滾的操作。對于“A賬戶”來說需要把扣除的 100 元加回,所以總金額 220=120+100。
那么“B 服務”和“C 服務”需要把入賬的金額從總金額里面減去,也就是 50=80-30 和 60=130-70。
TCC 接口實現
這里需要注意的是,需要針對每個服務去實現 Try,Confirm,Cancel 三個階段的代碼。
例如上面所說的檢查資源,執行業務,回滾業務等操作。目前有很多開源的架構例如:ByteTCC、TCC-transaction 可以借鑒。
TCC 可靠性
TCC 通過記錄事務處理日志來保證可靠性。一旦 Try,Confirm,Cancel 操作的時候服務掛掉或者出現異常,TCC 會提供重試機制。另外如果服務存在異步的情況可以采用消息隊列的方式通信保持事務一致。
分庫表中間件介紹
如果覺得分表分庫之后,需要考慮的問題很多,可以使用市面上的現成的中間件幫我們實現。
這里介紹幾個比較常用的中間件:
另外著重介紹 Sharding-JDBC 的架構,它的構成和“服務注冊中心”很像。
Sharding-JDBC 會提供一個 Sharding-Proxy 做代理,他會連接一個注冊中心(registry center),一旦數據庫的節點掛接到系統中,會在這個中心注冊,同時也會監控數據庫的健康狀況做心跳檢測。
而 Sharding-Proxy 本身在業務代碼(Business Code)請求數據庫的時候可以協助做負載均衡和路由。
同時 Sharding-Proxy 本身也可以支持被 MySQL Cli 和 MySQL Workbench 查看。
實際上如果我們理解了分表分庫的原理之后,實現并不難,很多大廠都提供了產品。
總結
因為數據量的上升,為了提高性能會對系統進行分表分庫。從分表來說,有水平分表和垂直分表兩種方式。
可以根據業務,冷熱數據等來進行分庫,分庫以后通過主從庫來實現讀寫分離。
如果對分庫之后數據庫做擴容,有兩種方式,主從數據庫擴容和雙寫數據庫擴容。
分表分庫會帶來分布式事務,我們需要掌握 CAP 和 BASE 原理,同時介紹了兩階段提交和 TCC 兩個分布式事務方案。最后,介紹了流行的分表分庫中間件,以及其實現原理。
當前標題:終于明白為什么要“分庫分表”了!
網站路徑:http://m.newbst.com/news17/98067.html
成都網站建設公司_創新互聯,為您提供企業建站、網站內鏈、ChatGPT、關鍵詞優化、App開發、虛擬主機
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯
猜你還喜歡下面的內容