日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Re:从 0 开始的微服务架构--(四)如何保障微服务架构下的数据一致性--转

發(fā)布時間:2025/4/5 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Re:从 0 开始的微服务架构--(四)如何保障微服务架构下的数据一致性--转 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址:http://mp.weixin.qq.com/s/eXvoJew3bjFKzLLJpS0Otg

隨著微服務架構的推廣,越來越多的公司采用微服務架構來構建自己的業(yè)務平臺。就像前邊的文章說的,微服務架構為業(yè)務開發(fā)帶來了諸多好處的同時,例如單一職責、獨立開發(fā)部署、功能復用和系統(tǒng)容錯等等,也帶來一些問題。

例如上手難度變大,運維變得更復雜,模塊之間的依賴關系更復雜,數(shù)據(jù)一致性難以保證,等等。但是辦法總是比問題多,本篇文章就來介紹一下我們是如何保障微服務架構的數(shù)據(jù)一致性的。

微服務架構的數(shù)據(jù)一致性問題

以電商平臺為例,當用戶下單并支付后,系統(tǒng)需要修改訂單的狀態(tài)并且增加用戶積分。由于系統(tǒng)采用的是微服務架構,分離出了支付服務、訂單服務和積分服務,每個服務都有獨立數(shù)據(jù)庫做數(shù)據(jù)存儲。當用戶支付成功后,無論是修改訂單狀態(tài)失敗還是增加積分失敗,都會 造成數(shù)據(jù)的不一致

為了解決例子中的數(shù)據(jù)一致性問題,一個最直接的辦法就是考慮數(shù)據(jù)的 強一致性。那么如何保證數(shù)據(jù)的強一致性呢?我們從關系型數(shù)據(jù)庫的 ACID 理論說起。

?ACID

關系型數(shù)據(jù)庫具有解決復雜事務場景的能力,關系型數(shù)據(jù)庫的事務滿足 ACID 的特性。

  • Atomicity:原子性(要么都做,要么都不做)

  • Consistency:一致性(數(shù)據(jù)庫只有一個狀態(tài),不存在未確定狀態(tài))

  • Isolation:隔離性(事務之間互不干擾)

  • Durability: 永久性(事務一旦提交,數(shù)據(jù)庫記錄永久不變)

具有 ACID 特性的數(shù)據(jù)庫支持數(shù)據(jù)的強一致性,保證了數(shù)據(jù)本身不會出現(xiàn)不一致。

然而微服務架構下,每個微服務都有自己的數(shù)據(jù)庫,導致微服務架構的系統(tǒng)不能簡單地滿足 ACID,我們就需要尋找微服務架構下的數(shù)據(jù)一致性解決方案。

微服務架構的系統(tǒng)本身是一種分布式系統(tǒng),而本文討論的問題其實也就是分布式事務之數(shù)據(jù)一致性的問題,我們來聊聊分布式系統(tǒng)的 CAP 理論和 BASE 理論。

?CAP

CAP 是指在一個分布式系統(tǒng)下, 包含三個要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分區(qū)容錯性),并且 三者不可得兼

  • C:Consistency,一致性,所有數(shù)據(jù)變動都是同步的。

  • A:Availability,可用性,即在可以接受的時間范圍內正確地響應用戶請求。

  • P:Partition tolerance,分區(qū)容錯性,即某節(jié)點或網(wǎng)絡分區(qū)故障時,系統(tǒng)仍能夠提供滿足一致性和可用性的服務。

關系型數(shù)據(jù)庫 單節(jié)點 保證了數(shù)據(jù)強一致性(C)和可用性(A),但是卻無法保證分區(qū)容錯性(P)。

然而在分布式系統(tǒng)下,為了保證模塊的分區(qū)容錯性(P),只能在數(shù)據(jù)強一致性(C)和可用性(A)之間做平衡。具體表現(xiàn)為在一定時間內,可能模塊之間數(shù)據(jù)是不一致的,但是通過自動或手動補償后能夠達到最終的一致。

?BASE

BASE 理論主要是解決 CAP 理論中分布式系統(tǒng)的可用性和一致性不可兼得的問題。BASE 理論包含以下三個要素:

  • BA:Basically Available,基本可用。

  • S:Soft State,軟狀態(tài),狀態(tài)可以有一段時間不同步。

  • E:Eventually Consistent,最終一致,最終數(shù)據(jù)是一致的就可以了,而不是時時保持強一致。

BASE 模型與 ACID 不同,滿足 CAP 理論,通過 犧牲強一致性來保證系統(tǒng)可用性。由于犧牲了強一致性,系統(tǒng)在處理請求的過程中,數(shù)據(jù)可以存在短時的不一致。

系統(tǒng)在處理業(yè)務時,記錄每一步的臨時狀態(tài)。當出現(xiàn)異常時,根據(jù)狀態(tài)判斷是否繼續(xù)處理請求或者退回原始狀態(tài),從而達到數(shù)據(jù)的最終一致。

例如,在上面的案例中,支付成功,訂單也成功,但增加積分失敗,此時,不應回滾支付和訂單,而應通過一些 補償方法 來讓積分得以正確地增加。后面會講到具體的實現(xiàn)方法。

在分享我們的分布式事務實踐方案之前,先看看早期解決分布式事務問題的二階段提交協(xié)議。

二階段提交協(xié)議

X/Open DTP(Distributed Transaction Process)是一個分布式事務模型,此模型主要使用二階段提交(2PC,Two-Phase-Commit)來保證分布式事務的完整性。在這個模型里面,有三個角色:

  • AP:Application,應用程序,業(yè)務層。

  • RM:Resource Manager,資源管理器,關系型數(shù)據(jù)庫或支持 XA 接口(XA 規(guī)范是 X/Open 組織定義的分布式事務規(guī)范)的組件。

  • TM: Transaction Manager ,事務管理器,負責各個 RM 的提交和回滾。

當應用程序(AP)調用了事務管理器(TM)的提交方法時,事務的提交分為兩個階段實行

?第一階段(準備階段)

TM 通知所有參與事務的各個 RM,給每個 RM 發(fā)送 prepare 消息。

RM 接收到消息后進入準備階段后,要么直接返回失敗,要么創(chuàng)建并執(zhí)行本地事務,寫本地事務日志(redo 和 undo 日志),但是 不提交(此處只保留最后一步耗時最少的提交操作給第二階段執(zhí)行)。

?第二階段(提交 / 回滾階段)

TM 收到 RM 準備階段的失敗消息或者獲取 RM 返回消息超時,則直接給 RM 發(fā)送回滾(rollback)消息,否則發(fā)送提交(commit)消息。

RM 根據(jù) TM 的指令執(zhí)行提交或者回滾,執(zhí)行完成后釋放所有事務處理過程中使用的鎖(最后階段釋放鎖)。

?二階段提交的利弊

優(yōu)點

2PC 提供了一套完整的分布式事務的解決方案,遵循事務嚴格的 ACID 特性。

缺點

  • TM 通過 XA 接口與各個 RM 之間進行數(shù)據(jù)交互,從第一階段的準備階段,業(yè)務所涉及的數(shù)據(jù)就被鎖定,并且鎖定跨越整個提交流程。在高并發(fā)和涉及業(yè)務模塊較多的情況下 對數(shù)據(jù)庫的性能影響較大

  • 二階段是 反可伸縮模式 的,業(yè)務規(guī)模越大,涉及模塊越多,局限性越大,系統(tǒng)可伸縮性越差。

  • 在技術棧比較雜的分布式應用中,存儲組件有很多 不支持 XA 協(xié)議

二階段的諸多弊端,導致分布式系統(tǒng)下無法直接使用此方案來解決數(shù)據(jù)一致性問題,但它提供了解決分布式系統(tǒng)下數(shù)據(jù)一致性問題的思路。。

下面就通過案例來分享我們是如何保證微服務架構的數(shù)據(jù)一致性的。

可靠消息最終一致性

可靠消息最終一致性方案本質上是 利用 MQ 組件實現(xiàn)的二階段提交。此方案涉及 3 個模塊:

  • 上游應用,執(zhí)行業(yè)務并發(fā)送 MQ 消息。

  • 可靠消息服務和 MQ 消息組件,協(xié)調上下游消息的傳遞,并確保上下游數(shù)據(jù)的一致性。

  • 下游應用,監(jiān)聽 MQ 的消息并執(zhí)行自身業(yè)務。

?上游應用執(zhí)行業(yè)務并發(fā)送 MQ 消息(第一階段)

上游應用將本地業(yè)務執(zhí)行和消息發(fā)送綁定在同一個本地事務中,保證要么本地操作成功并發(fā)送 MQ 消息,要么兩步操作都失敗并回滾。

上游應用和可靠消息之間的業(yè)務交互圖如下:

  • 上游應用發(fā)送待確認消息到可靠消息系統(tǒng)

  • 可靠消息系統(tǒng)保存待確認消息并返回

  • 上游應用執(zhí)行本地業(yè)務

  • 上游應用通知可靠消息系統(tǒng)確認業(yè)務已執(zhí)行并發(fā)送消息。

  • 可靠消息系統(tǒng)修改消息狀態(tài)為發(fā)送狀態(tài)并將消息投遞到 MQ 中間件。

  • 以上每一步都可能出現(xiàn)失敗情況,分析一下這 5 步出現(xiàn)異常后上游業(yè)務和消息發(fā)送是否一致:

    上游應用執(zhí)行完成,下游應用尚未執(zhí)行或執(zhí)行失敗時,此事務即處于 BASE 理論的 Soft State 狀態(tài)。

    ?下游應用監(jiān)聽 MQ 消息并執(zhí)行業(yè)務(第二階段)

    下游應用監(jiān)聽 MQ 消息并執(zhí)行業(yè)務,并且將消息的消費結果通知可靠消息服務。

    可靠消息的狀態(tài)需要和下游應用的業(yè)務執(zhí)行保持一致,可靠消息狀態(tài)不是已完成時,確保下游應用未執(zhí)行,可靠消息狀態(tài)是已完成時,確保下游應用已執(zhí)行。

    下游應用和可靠消息服務之間的交互圖如下:

  • 下游應用監(jiān)聽 MQ 消息組件并獲取消息

  • 下游應用根據(jù) MQ 消息體信息處理本地業(yè)務

  • 下游應用向 MQ 組件自動發(fā)送 ACK 確認消息被消費

  • 下游應用通知可靠消息系統(tǒng)消息被成功消費,可靠消息將該消息狀態(tài)更改為已完成。

  • 以上每一步都可能出現(xiàn)失敗情況,分析一下這 4 步出現(xiàn)異常后下游業(yè)務和消息狀態(tài)是否一致:

    通過分析以上兩個階段可能失敗的情況,為了確保上下游數(shù)據(jù)的最終一致性,在可靠消息系統(tǒng)中,需要開發(fā) 消息狀態(tài)確認消息重發(fā) 兩個功能以實現(xiàn) BASE 理論的 Eventually Consistent 特性。

    ?消息狀態(tài)確認

    可靠消息服務定時監(jiān)聽消息的狀態(tài),如果存在狀態(tài)為待確認并且超時的消息,則表示上游應用和可靠消息交互中的步驟 4 或者 5 出現(xiàn)異常。

    可靠消息則攜帶消息體內的信息向上游應用發(fā)起請求查詢該業(yè)務是否已執(zhí)行。上游應用提供一個可查詢接口供可靠消息追溯業(yè)務執(zhí)行狀態(tài),如果業(yè)務執(zhí)行成功則更改消息狀態(tài)為已發(fā)送,否則刪除此消息確保數(shù)據(jù)一致。具體流程如下:

  • 可靠消息查詢超時的待確認狀態(tài)的消息

  • 向上游應用查詢業(yè)務執(zhí)行的情況

  • 業(yè)務未執(zhí)行,則刪除該消息,保證業(yè)務和可靠消息服務的一致性。業(yè)務已執(zhí)行,則修改消息狀態(tài)為已發(fā)送,并發(fā)送消息到 MQ 組件。

  • ?消息重發(fā)

    消息已發(fā)送則表示上游應用已經(jīng)執(zhí)行,接下來則確保下游應用也能正常執(zhí)行。

    可靠消息服務發(fā)現(xiàn)可靠消息服務中存在消息狀態(tài)為已發(fā)送并且超時的消息,則表示可靠消息服務和下游應用中存在異常的步驟,無論哪個步驟出現(xiàn)異常,可靠消息服務都將此消息重新投遞到 MQ 組件中供下游應用監(jiān)聽。

    下游應用監(jiān)聽到此消息后,在保證冪等性的情況下重新執(zhí)行業(yè)務并通知可靠消息服務此消息已經(jīng)成功消費,最終確保上游應用、下游應用的數(shù)據(jù)最終一致性。具體流程如下:

  • 可靠消息服務定時查詢狀態(tài)為已發(fā)送并超時的消息

  • 可靠消息將消息重新投遞到 MQ 組件中

  • 下游應用監(jiān)聽消息,在滿足冪等性的條件下,重新執(zhí)行業(yè)務。

  • 下游應用通知可靠消息服務該消息已經(jīng)成功消費。

  • 通過消息狀態(tài)確認和消息重發(fā)兩個功能,可以確保上游應用、可靠消息服務和下游應用數(shù)據(jù)的最終一致性。

    當然在實際接入過程中,需要引入 人工干預 功能。比如引入重發(fā)次數(shù)限制,超過重發(fā)次數(shù)限制的將消息修改為死亡消息,等待人工干預。

    代入開篇案例,通過可靠消息最終一致性方案,第一階段,訂單狀態(tài)更改之前,訂單服務向可靠消息服務請求保存待確認消息。可靠消息服務保存消息并返回。

    訂單服務接收到返回信息后執(zhí)行本地業(yè)務并通知可靠消息服務業(yè)務已執(zhí)行。消息服務更改消息狀態(tài)并將消息投遞到 MQ 中間件。

    第二階段,積分系統(tǒng)監(jiān)聽到 MQ 消息,查看積分是否已增加,如果沒有增加則修改積分,然后請求可靠消息服務。可靠消息服務接收到積分系統(tǒng)的請求,將消息狀態(tài)更改為已完成。

    到這里,已經(jīng)介紹完如何通過可靠消息服務來保證數(shù)據(jù)的一致性。但由于引入了可靠消息服務和消息隊列,帶來了一定的 復雜性,所以,它更 適用于跨平臺技術棧不統(tǒng)一的場景

    下面再來介紹在技術棧統(tǒng)一的情況下,如何通過 TCC 來解決數(shù)據(jù)一致的方法。

    TCC(Try-Confirm-Cancel)

    TCC 方案是二階段提交的 另一種實現(xiàn)方式,它涉及 3 個模塊,主業(yè)務從業(yè)務活動管理器(協(xié)作者)

    下面這張圖是互聯(lián)網(wǎng)上關于 TCC 比較經(jīng)典的圖示:

    第一階段:主業(yè)務服務分別調用所有從業(yè)務服務的 try 操作,并在活動管理器中記錄所有從業(yè)務服務。當所有從業(yè)務服務 try 成功或者某個從業(yè)務服務 try 失敗時,進入第二階段。

    第二階段:活動管理器根據(jù)第一階段從業(yè)務服務的 try 結果來執(zhí)行 confirm 或 cancel 操作。如果第一階段所有從業(yè)務服務都 try 成功,則協(xié)作者調用所有從業(yè)務服務的 confirm 操作,否則,調用所有從業(yè)務服務的 cancel 操作。

    在第二階段中,confirm 和 cancel 同樣存在失敗情況,所以需要對這兩種情況做 異常處理以保證數(shù)據(jù)一致性。

  • Confirm 失敗:則回滾所有 confirm 操作并執(zhí)行 cancel 操作。

  • Cancel 失敗:從業(yè)務服務需要提供自動 cancel 機制,以保證 cancel 成功。

  • 目前有很多基于 RPC 的 TCC 框架,但是不適用于微服務架構下基于 HTTP 協(xié)議的交互模式。我們這次只討論基于 HTTP 協(xié)議的 TCC 實現(xiàn)。具體的實現(xiàn)流程如下:

  • 主業(yè)務服務調用從業(yè)務服務的 try 操作,并獲取 confirm/cancel 接口和超時時間。

  • 如果從業(yè)務都 try 成功,主業(yè)務服務執(zhí)行本地業(yè)務,并將獲取的 confirm/cancel 接口發(fā)送給活動管理器,活動管理器會順序調用從業(yè)務 1 和從業(yè)務 2 的 confirm 接口并記錄請求狀態(tài),如果請求成功,則通知主業(yè)務服務提交本地事務。如果 confirm 部分失敗,則活動管理器會順序調用從業(yè)務 1 和從業(yè)務 2 的 cancel 接口來取消 try 的操作。

  • 如果從業(yè)務部分或全部 try 失敗,則主業(yè)務直接回滾并結束,而 try 成功的從業(yè)務服務則通過定時任務來處理處于 try 完成但超時的數(shù)據(jù),將這些數(shù)據(jù)做回滾處理保證主業(yè)務服務和從業(yè)務服務的數(shù)據(jù)一致。

  • 代入開篇提到的案例,通過 TCC 方案,訂單服務在訂單狀態(tài)修改之前執(zhí)行預增積分操作(try),并從積分服務獲取 confirm/cancel 預增積分的請求地址。

    如果預增積分(try)成功,則訂單服務更改訂單狀態(tài)并通知活動管理器,活動管理器請求積分模塊的 confirm 接口來增加積分。

    如果預增積分(try)失敗,則訂單服務業(yè)務回滾。積分服務通過定時任務刪除預增積分(try)超時的數(shù)據(jù)。

    另外如果活動管理器調用積分服務的 confirm 接口失敗,則活動管理器調用積分服務 cancel 接口來取消預增積分,從而,保證訂單和積分數(shù)據(jù)的最終一致性。

    通過上面的對可靠消息服務和 TCC 方案的描述,我們 解決了技術棧一致和不一致的兩種情況下的數(shù)據(jù)一致性問題

    但是,通常在這些核心業(yè)務上有 很多附加業(yè)務,比如當用戶支付完成后,需要通過短信通知用戶支付成功。

    這一類業(yè)務的成功或者失敗不會影響核心業(yè)務,甚至很多大型互聯(lián)網(wǎng)平臺在并高并發(fā)的情況下會主動關閉這一類業(yè)務以保證核心業(yè)務的順利執(zhí)行。那么怎么處理這類情況呢,我們來看看最大努力通知方案。

    最大努力通知

    最大努力通知方案涉及三個模塊:

    • 上游應用,發(fā)消息到 MQ 隊列。

    • 下游應用(例如短信服務、郵件服務),接受請求,并返回通知結果。

    • 最大努力通知服務,監(jiān)聽消息隊列,將消息存儲到數(shù)據(jù)庫中,并按照通知規(guī)則調用下游應用的發(fā)送通知接口。

    具體流程如下:

  • 上游應用發(fā)送 MQ 消息到 MQ 組件內,消息內包含通知規(guī)則和通知地址

  • 最大努力通知服務監(jiān)聽到 MQ 內的消息,解析通知規(guī)則并放入延時隊列等待觸發(fā)通知

  • 最大努力通知服務調用下游的通知地址,如果調用成功,則該消息標記為通知成功,如果失敗則在滿足通知規(guī)則(例如 5 分鐘發(fā)一次,共發(fā)送 10 次)的情況下重新放入延時隊列等待下次觸發(fā)。

  • 最大努力通知服務表示在 不影響主業(yè)務 的情況下,盡可能地確保數(shù)據(jù)的一致性。它需要開發(fā)人員根據(jù)業(yè)務來指定通知規(guī)則,在滿足通知規(guī)則的前提下,盡可能的確保數(shù)據(jù)的一致,以盡到最大努力的目的。

    根據(jù)不同的業(yè)務可以定制不同的通知規(guī)則,比如通知支付結果等相對嚴謹?shù)臉I(yè)務,可以將通知頻率設置高一些,通知時間長一些,比如隔 5 分鐘通知一次,持續(xù)時間 1 小時。

    如果不重要的業(yè)務,比如通知用戶積分增加,則可以將通知頻率設置低一些,時間短一些,比如 10 分鐘通知一次,持續(xù) 30 分鐘。

    代入上面提到的支付成功短信通知用戶的案例,通過最大努力通知方案,當支付成功后,將消息發(fā)送到 MQ 中間件,在消息中,定義發(fā)送規(guī)則為 5 分鐘一次,最大發(fā)送數(shù)為 10 次。

    最大努力通知服務監(jiān)聽 MQ 消息并根據(jù)規(guī)則調用消息通知服務(短信服務)的消息發(fā)送接口,并記錄每次調用的日志信息。在通知成功或者已通知 10 次時,停止通知。

    總 ? 結

    上面通過案例詳細介紹了我們解決微服務之間數(shù)據(jù)不一致問題的三種方案,下面通過一張簡單的對比圖,為大家選擇合適的解決方案提供簡單依據(jù)。

    轉載于:https://www.cnblogs.com/davidwang456/p/7517358.html

    總結

    以上是生活随笔為你收集整理的Re:从 0 开始的微服务架构--(四)如何保障微服务架构下的数据一致性--转的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。