MQ 分散式事務 -- 微服務應用

来源:https://www.cnblogs.com/zjtao/archive/2019/07/17/11199533.html
-Advertisement-
Play Games

1、背景 友情鏈接:https://www.cnblogs.com/Agui520/p/11187972.html https://blog.csdn.net/fd2025/article/details/79863390 以支付、電商下單為例子。一個電商系統包含了好幾大類模塊,就比如有用戶模塊、商 ...


1、背景

友情鏈接:https://www.cnblogs.com/Agui520/p/11187972.html

    https://blog.csdn.net/fd2025/article/details/79863390

以支付、電商下單為例子。一個電商系統包含了好幾大類模塊,就比如有用戶模塊、商品模塊、庫存模塊、訂單模塊、支付模塊、物流模塊,活動模塊等,以下就先列舉幾個最基礎常見的模塊(用戶模塊、商品模塊、庫存模塊、訂單模塊、支付模塊)。

用戶流程如下:

 

2、問題

如果系統規模較小,數據表都在一個資料庫實例上,項目服務端也都在同一個項目,那上面的問題基本不是問題,直接用本地事務(一致性,原子性、隔離性、持久性)解決,比如支付轉賬(A->B)模塊肯定會出現A賬戶減少,B賬戶增加,程式操作加個事務管理就解決。但是如果系統規模較大,比如支付寶賬戶表和餘額寶賬戶表顯然不會在同一個資料庫實例上,他們往往分佈在不同的物理節點上,又比如商品模塊,訂單模塊不會在同一個資料庫中或是在同一個項目中,這時本地事務就已經失去用武之地了。

3、場景

1.場景1

支付寶轉1萬元到餘額寶,如果支付寶扣除1萬後,如果系統掛掉了,餘額寶並沒有增加1萬,數據出現不一致情況。

2.場景2

電商系統中,當有用戶下單後,除了在訂單表插入一條記錄外,對應商品表的這個商品數量必須 減1,怎麼保證??在 搜索廣告系統中,當用戶點擊某廣告後,除了在點擊事件表中 增加一條
記錄外 ,還得去商家賬戶表中找到這個商家扣除廣告費吧,怎麼保證??

不拆分服務最常見的解決方案:

本地事務:

Begin transaction
update A set amount = amount - 10000 where userId = 1
update B set amount = amount + 10000 where userId = 1
End transaction
commit;

4、MQ實現分散式事務

當 支付寶賬戶扣除1萬後,我們只要生成一個憑證(消息)即可,這個憑證(消息)上寫著“讓餘額寶賬戶增加一萬”,只要這個憑證(消息)能可靠保證,我們最終是可以拿著這個憑證(消息)讓餘額寶賬戶 增加1萬的,即我們能依靠這個憑證(消息)完成最終一致性。

4.1 如何可靠保存憑證

業務與消息耦合的方式

支付寶在完成扣款的同時,同時記錄消息數據,這個消息數據與業務數據保存在同一資料庫實例里(消息記錄表名為message).

Begin transtration

update A set amount = amount -10000 where userId = 1;

insert into message(userId,amount,status) values (1,10000,1);

End transaction

commit;
上述事務能保證只要支付寶賬戶里被扣了錢,消息一定能保存下來。

當上述事務提交成功後,我們通過實時消息服務將此消息通知餘額寶,餘額寶處理成功後發送回覆成功消息後,支付寶收到回覆後刪除該條消息數據。

業務與消息解耦

為瞭解耦,可以採取以下方式:

1、支付寶在扣款事務提交之前,向實時消息服務請求發送消息,實時消息服務只記錄消息數據,而不真正發送(只是知道有這一條消息),只有消息發送成功後才會提交事務。

 

//支付寶 - 10000 (業務需求)

//先把(支付寶-10000)封裝成一個消息(new Message()))

//然後把這個消息提交到MQ伺服器上send(producer.send(new Message(),callback(裡面處理本地事務)))

//在callback處理本地事務:在callback方法里:

update A set amount = amount - 10000 where userId = 1;

..............

//當本地事務操作完成了以後

1.要麼成功:(給MQ一個標識:COMMIT)

2.要麼失敗:(給MQ一個標識:ROLLBACK)
2. 當支付寶扣款事務被提交成功後,向實時 消息服務確認發送,只有在得到確認發送指令後,實時消息服務才真正發送該消息。

3. 當支付寶扣款事務提交失敗回滾後,向實時 消息服務取消發送。在得到取消發送指令後, 該消息將不會被髮送。

4. 對於那些未確認的消息或者取消的消息,需要有一個消息狀態確認系統定時去支付寶系統查詢這個消息的 狀態進行更新。為什麼需要這一個步驟:假設在支付寶扣款事務被成功提交後,系統掛了,此時消息狀態並未被更新為“確認發送”,從而導致消息不能被髮送。

優點:消息數據獨立存儲 ,降低業務系統與消息系統之間的耦合。

缺點:一次消息發送需要兩次請求;業務處理服務需要實現消息狀態回查介面

 

 

 綜合上述的描述,RabbitMQ 做了這麼三件事:

1,先發送需要發送的消息到消息中間件broker,並獲取到該message的transactionId。在第一次發送的時候,該消息的狀態為LocalTransactionState.UNKNOW
2,處理本地事物。
3,根據本地事物的執行結果,結合transactionId,找到該消息的位置,在mq中標誌該消息的最終處理結果。  

5、Rabbit MQ 介紹

相關鏈接:https://www.cnblogs.com/duanxz/p/3542320.html

 

RabbitMQ的結構圖如下:

 

1、幾個概念說明:

Broker:簡單來說就是消息隊列伺服器實體。
Exchange:消息交換機,它指定消息按什麼規則,路由到哪個隊列。

    Exchange類型

    A. direct exchange:將與routing key 比配的消息,直接推入相對應的隊列,創建隊列時,預設就創建同名的routing key。

    B. fanout exchange:是一種廣播模式,忽略routingkey的規則。

    C. topic exchange:應用主題,根據key進行模式匹配路由,例如:若為abc*則推入到所有abc*相對應的queue;若為abc.#則推入到abc.xx.one ,abc.yy.two對應的queue。


Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列。
Binding:綁定,它的作用就是把exchange和queue按照路由規則綁定起來。
Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞。
vhost:虛擬主機,一個broker里可以開設多個vhost,用作不同用戶的許可權分離。
producer:消息生產者,就是投遞消息的程式。
consumer:消息消費者,就是接受消息的程式。
channel:消息通道,在客戶端的每個連接里,可建立多個channel,每個channel代表一個會話任務。是基於Connection之上建立通信通道,因為每次Connection建立TCP協議通信開銷及性能消耗較大,所以一次建立Connection後,使用多個Channel通道通信減少開銷和提高性能。

 

2、消息隊列的使用過程大概如下:

(1)客戶端連接到消息隊列伺服器,打開一個channel。
(2)客戶端聲明一個exchange,並設置相關屬性。
(3)客戶端聲明一個queue,並設置相關屬性。
(4)客戶端使用routing key,在exchange和queue之間建立好綁定關係。
(5)客戶端投遞消息到exchange。

exchange接收到消息後,就根據消息的key和已經設置的binding,進行消息路由,將消息投遞到一個或多個隊列里。

exchange也有幾個類型,完全根據key進行投遞的叫做Direct交換機,例如,綁定時設置了routing key為”abc”,那麼客戶端提交的消息,只有設置了key為”abc”的才會投遞到隊列。對key進行模式匹配後進行投遞的叫做Topic交換機,符 號”#”匹配一個或多個詞,符號”*”匹配正好一個詞。例如”abc.#”匹配”abc.def.ghi”,”abc.*”只匹配”abc.def”。還 有一種不需要key的,叫做Fanout交換機,它採取廣播模式,一個消息進來時,投遞到與該交換機綁定的所有隊列。

 

 

 

6、代碼實現

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • wxss文件樣式 .item-image{ width: 80px; height: 80px; margin-right: 2px; } .item-image{ width: 80px; height: 80px; margin-right: 2px; } wxml 佈局 ...
  • 設置錨點的兩種方式 1.設置一個錨點鏈接<a href="#wang">去找汪星人</a> 在頁面中需要的位置設置錨點<a name="wang">汪星人基地</a> 2.設置一個錨點鏈接<a href="#miao">去找喵星人</a> 在頁面中需要的位置設置錨點<h3 id="miao">喵星人 ...
  • 主要介紹了一些數據保存在本地中的一些處理方法,包括cookie和webSrorage的保存優缺點介紹,以及簡單介紹cookie中的坑 ...
  • 我們定義一個組件的時候,可以在組件的某個節點內預留一個位置,當父組件調用該組件的時候可以指定該位置具體的內容,這就是插槽的用法,子組件模板可以通過slot標簽(插槽)規定對應的內容放置在哪裡,比如: 渲染結果為: 對應的html節點如下: 引用AppLayout這個組件時,我們指定了header和f ...
  • 最近在研究慢請求監控的問題,寫了一個簡單的測試代碼:在網頁端( )通過 函數向服務端獲取數據,然後列印請求耗時。 在服務端通過 延時 才返回數據(服務端使用 "ExpressJS" )。 不出所料, 數據都略微大於 1500。 而後,我突發奇想,假設我同時發送多個請求會怎麼樣呢?於是有瞭如下代碼: ...
  • JQuery本質上還是JavaScript,是JavaScript的一個框架,可以讓我們更簡潔地去使用JavaScript 使用之前,記得在html頭部引用JQuery 通過選擇器獲得JQuery對象 id element class selector1,selector2... 層級 attrib ...
  • 快速熱門指導,櫥窗註意細節 雙語字幕添加,資源對接擔保 全國抖音聯盟內部唯一官網 : http://douyinlianmeng.tk ...
  • 接上篇內容描述談談平臺設計思路及方法。前一篇簡單的介紹了一下整體的實現思路。那從本節開始開始說明如何引入資料庫表視圖等,因為我們不管做什麼項目軟體,設計的時候能直接將頁面控制項綁定到指定的欄位,那樣後續的操作就會很方便。至於實現的方法,有很多種,每個人可能有各自不同的思路,我不去評價別人是怎麼做的,僅 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...