靈魂拷問*5: 從實戰角度看分佈式事務

不少時候,咱們談概念,會感受看的時候很明白,過幾天就忘光了,緣由就是缺少對應的場景。php


mysql

沒有落地支撐的PPT都是耍流氓;sql

沒有代碼支撐的架構是耍流氓;數據庫

沒有業務場景支撐的應用方案是耍流氓;緩存

服務器

----大魏語
微信



本篇咱們從實戰角度分析分佈式事務,因此本文會所有用大白話說清楚。網絡


拷問1:爲何要用分佈式事務?架構

首先,若是一次請求只涉及一個數據庫的表,那麼不存在分佈式的問題。那都叫本地事務(LT)。
app

若是一次請求涉及到兩個DB的表,這時候就要用到分佈式事務(DT)。主流數據庫都支持事務管理。



拷問2:分佈式事務的針對對象是什麼?

DB?

錯,是數據,data。


數據包括:DB、Cache、搜索(ES)。但不少時候,咱們在分佈式事務操做最多的是DB。


拷問3:分佈式事務(DT)使用什麼模型?

CAP是最常被提到的模型。

CAP 理論的定義很簡單,CAP 三個字母分別表明了分佈式系統中三個相互矛盾的屬性:

  • Consistency (一致性):CAP 理論中的副本一致性特指強一致性;

  • Availiablity(可用性):指系統在出現異常時已經能夠提供服務;

  • Tolerance to the Partition of network (分區容忍):指系統能夠對網絡分區。這種異常情 況進行容錯處理;

在真實的業務場景中,CAP沒法同時知足,可以知足兩個就很不錯了。所以,仨字母組合,會有:

CA、AP、CP。在實際業務場景中,只有AP和CP。

分佈式事務選擇AP仍是CP,取決於業務特色,取決於業務容忍度。


網上購物場景用CP。關於這個場景,我仍是用紅帽測試代碼:coolstore:

圖片


若是要購物,會涉及到幾個業務模塊呢?大體順序是這樣的:

    


也就是說,咱們在電商的一次操做,會涉及:看目錄、評分、購物車、減庫存、下單等多個功能模塊操做。不一樣的功能模塊由不一樣的微服務支撐,有不一樣的數據庫。這就要保證CP,即數據一致性和分區容忍性。


咱們再看看一個AP模型的分佈式事務。

大魏常常寫公衆號、發公衆號。這裏面涉及到:

新建圖文消息:

寫公衆號內容:

圖片

而後推送給幾千人:

圖片

在這個分佈式事務中,其實更強調吞吐量。不少時候大魏晚上發blog後,都須要10分鐘blog才能推送給全部訂閱者,就是由於晚上發blog的太多,吞吐量成了瓶頸。



拷問4:分佈式事務(DT)必定是異步的麼?


錯!


同步異步的都有,不少時候是二者混合的場景。

大魏仍是從實踐角度舉例。在京東買大魏的書100本,選完了下單支付,付錢,那麼買書這件事用的就是同步模型。

圖片

圖片

圖片

在上圖的同步模型中,設計到的模塊至少有:減小商品庫存、創建訂單、前臺支付。


若是到支付頁面,一看:須要這麼多錢,猶豫了,暫時先不支付了。可能過了一個小時候想清楚了,才支付,那這就變成了異步事務。咱們在京東退出支付頁面時,也會提示若是24個小時未支付的話(截圖的時候,已通過了幾分鐘),訂單會自動取消。

圖片

若是咱們3個小時以後支付,確定也能支付成功。那這三個小時的時間裏,事務是被保存在消息隊列裏了(MQ)。


因此說,分佈式事務不少時候是同步和異步混合的場景。並且咱們在設計這種場景時,還須要保證業務的吞吐量和相應延遲。


因此說,分佈式事務,有CP和AP兩種常見模型。典型的CP如電商購物,強調一致性。典型的AP模型如發blog、發微信朋友圈。而AP和CP這兩種模型,既有異步,又有同步的。


拷問5:分佈式事務設計的核心要點是什麼?

分佈式事務設計的問題,自己是架構設計的問題。架構設計,分爲:服務和數據兩大塊。不少時候,數據和服務是緊耦合的。所以須要進行拆分。


在微服務架構中,每一個微服務都有本身的DB,其實就是爲了把分佈式事務拆分紅本地事務。


針對紅帽coolstore的demo而言,咱們就是將長事務拆分紅短事務,將短事務拆分紅本地事務。


圖片

這樣,每一個本地事務都只操做本身的數據,也就是說DB/緩存/MQ必需要有事務管理能力(這個後面講),本地事務才能實現。但每一個本地事務之間是有關聯的。例如:A(下訂單)->B(減庫存)->C(發貨)。若是A成功,B成功,C成功,那麼整個分佈式事務成功。

那麼,若是C失敗呢?

C會發生回滾,B、A會發生補償。C不須要補償,由於本地事務能夠直接rollback。


咱們看一下MySQL如何實現事務管理(BEGIN ROLLBACKCOMMIT):


<?php$dbhost = 'localhost:3306';  // mysql服務器主機地址$dbuser = 'root';            // mysql用戶名$dbpass = '123456';          // mysql用戶名密碼$conn = mysqli_connect($dbhost, $dbuser, $dbpass);if(! $conn ){die('鏈接失敗: ' . mysqli_error($conn));}// 設置編碼,防止中文亂碼mysqli_query($conn, "set names utf8");mysqli_select_db( $conn, 'RUNOOB' );mysqli_query($conn, "SET AUTOCOMMIT=0"); // 設置爲不自動提交,由於MYSQL默認當即執行mysqli_begin_transaction($conn);            // 開始事務定義
if(!mysqli_query($conn, "insert into runoob_transaction_test (id) values(8)")){    mysqli_query($conn, "ROLLBACK");     // 判斷當執行失敗時回滾}
if(!mysqli_query($conn, "insert into runoob_transaction_test (id) values(9)")){    mysqli_query($conn, "ROLLBACK");      // 判斷執行失敗時回滾}mysqli_commit($conn);            //執行事務mysqli_close($conn);?>

而Redis事務管理的基礎是:MULTI 、 EXEC 、 DISCARD 和 WATCH。

關於Redis的事務管理,能夠參照這篇文章:

https://cloud.tencent.com/developer/article/1798560


圖片



拷問5:分佈式事務框架不少,實際到底哪一種用的多。

談到分佈式事務的架構,有不少:XA、 TCC 、SAGA、 事務消息。咱們不談概念,哪一種用的多呢?

實際應用中,同步主要用saga、異步主要使用事務消息。

saga就是事務補償,這上文已經有所介紹。


MQ事務消息重點再也不是保證全部子事務的原子性,而是保證本地事務和發送MQ消息的原子性。相對於saga,MQ事務消息不用提供補償接口)。


須要注意的是,不是全部的MQ都支持事務消息,目前只有RocketMQ支持。

如下內容節選自:https://juejin.cn/post/6844903951448408071


普通MQ的消息處理流程:

圖片

  • 消息生成者發送消息

  • MQ收到消息,將消息進行持久化,在存儲中新增一條記錄

  • 返回ACK給生產者

  • MQ push 消息給對應的消費者,而後等待消費者返回ACK

  • 若是消息消費者在指定時間內成功返回ack,那麼MQ認爲消息消費成功,在存儲中刪除消息,即執行第6步;若是MQ在指定時間內沒有收到ACK,則認爲消息消費失敗,會嘗試從新push消息,重複執行四、五、6步驟

  • MQ刪除消息


事務消息處理的流程

圖片

  • 事務消息與普通消息的區別就在於消息生產環節,生產者首先預發送一條消息到MQ(這也被稱爲發送half消息)

  • MQ接受到消息後,先進行持久化,則存儲中會新增一條狀態爲待發送的消息

  • 而後返回ACK給消息生產者,此時MQ不會觸發消息推送事件

  • 生產者預發送消息成功後,執行本地事務

  • 執行本地事務,執行完成後,發送執行結果給MQ

  • MQ會根據結果刪除或者更新消息狀態爲可發送

  • 若是消息狀態更新爲可發送,則MQ會push消息給消費者,後面消息的消費和普通消息是同樣的


RocketMQ的模式有利於異步解耦。


咱們想象一個場景-秒殺系統。

如下內容節選自:https://www.jianshu.com/p/06e9a1d75bd5

圖片

流程說明以下:

  1. 註冊系統向消息隊列 RocketMQ 發送半事務消息。
    1.1 半事務消息發送成功,進入 2。
    1.2 半事務消息發送失敗,註冊系統不進行註冊,流程結束。(最終註冊系統與郵件通知系統數據一致

  2. 註冊系統開始註冊。
    2.1 註冊成功,進入 3.1。
    2.2 註冊失敗,進行 3.2。

  3. 註冊系統向消息隊列 RocketMQ 發送半消息狀態。
    3.1 提交半事務消息,產生註冊成功消息,進入 4。
    3.2 回滾半事務消息,未產生註冊成功消息,流程結束。(最終註冊系統與郵件通知系統數據一致)

  4. 郵件通知系統接收消息隊列 RocketMQ 的註冊成功消息。

  5. 郵件通知系統發送註冊成功郵件。(最終註冊系統與郵件通知系統數據一致)


總結:

  1. 分佈式事務針對的對象是data,它能夠在DB/緩存/ES/MQ中.

  2. CAP模型中,CP、AP較多。前者強調一致性,後者強調吞吐量。而AP和CP這兩種模型,既有異步,又有同步的。

  3. 分佈式事務設計的核心要點是:解耦拆分。將分佈式事務拆成本地事務。

  4. 在分佈式系統設計中:同步主要用saga、異步主要使用事務消息。事務消息不須要寫補償接口,所以代碼侵入低。RocketMQ支持事務消息。

相關文章
相關標籤/搜索