偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

RocketMQ 事務(wù)消息初體驗(yàn)

開發(fā) 前端
假如先發(fā)送消息,后修改訂單狀態(tài),消息發(fā)送成功,訂單沒有執(zhí)行成功,需要回滾整個(gè)事務(wù)(訂單數(shù)據(jù)事務(wù)回滾,積分服務(wù)消費(fèi)時(shí),需要先反查事務(wù)狀態(tài),若事務(wù)提交,才能插入積分記錄)。

事務(wù)消息是 RocketMQ 的高級(jí)特性之一 。這篇文章,筆者會(huì)從應(yīng)用場(chǎng)景、功能原理、實(shí)戰(zhàn)例子三個(gè)模塊慢慢為你揭開事務(wù)消息的神秘面紗。

1 應(yīng)用場(chǎng)景

舉一個(gè)電商場(chǎng)景的例子:用戶購(gòu)物車結(jié)算時(shí),系統(tǒng)會(huì)創(chuàng)建支付訂單。

用戶支付成功后支付訂單的狀態(tài)會(huì)由未支付修改為支付成功,然后系統(tǒng)給用戶增加積分。

通常我們會(huì)使用普通消費(fèi)方案,該方案能夠發(fā)揮 MQ 的優(yōu)勢(shì):異步和解耦 ,  同時(shí)架構(gòu)設(shè)計(jì)非常簡(jiǎn)單。

圖片圖片

  1. 用戶購(gòu)物車結(jié)算時(shí),系統(tǒng)創(chuàng)建支付訂單;
  2. 支付成功后,更新訂單的狀態(tài)從未支付修改為支付成功;
  3. 發(fā)送一條普通消息到消息隊(duì)列服務(wù)端;
  4. 積分服務(wù)消費(fèi)消息,添加積分記錄。

但該方案有個(gè)非常直觀的缺點(diǎn):容易出現(xiàn)不一致的現(xiàn)象。

  1. 假如先發(fā)送消息,后修改訂單狀態(tài),消息發(fā)送成功,訂單沒有執(zhí)行成功,需要回滾整個(gè)事務(wù)(訂單數(shù)據(jù)事務(wù)回滾,積分服務(wù)消費(fèi)時(shí),需要先反查事務(wù)狀態(tài),若事務(wù)提交,才能插入積分記錄)。
  2. 假如先修改訂單狀態(tài),后發(fā)送消息,訂單狀態(tài)修改成功,但消息發(fā)送失敗,需要補(bǔ)償操作才能保持最終一致。
  3. 假如先修改訂單,后發(fā)送消息,訂單狀態(tài)修改成功,但消息發(fā)送超時(shí),此時(shí)無法判斷需要回滾訂單還是提交訂單變更。

我們看到,為了完善普通消費(fèi)方案,業(yè)務(wù)層還需要做到兩點(diǎn):補(bǔ)償機(jī)制和提供事務(wù)狀態(tài)查詢接口。

要做到這兩點(diǎn),難不難呢?

不難,但是業(yè)務(wù)層代碼會(huì)比較混亂,更優(yōu)的方案還是得從中間件層面解決。

2 功能原理

RocketMQ 事務(wù)消息是支持在分布式場(chǎng)景下保障消息生產(chǎn)和本地事務(wù)的最終一致性。交互流程如下圖所示:

圖片圖片

1、生產(chǎn)者將消息發(fā)送至 Broker 。

2、Broker 將消息持久化成功之后,向生產(chǎn)者返回 Ack 確認(rèn)消息已經(jīng)發(fā)送成功,此時(shí)消息被標(biāo)記為"暫不能投遞",這種狀態(tài)下的消息即為半事務(wù)消息。

3、生產(chǎn)者開始執(zhí)行本地事務(wù)邏輯。

4、生產(chǎn)者根據(jù)本地事務(wù)執(zhí)行結(jié)果向服務(wù)端提交二次確認(rèn)結(jié)果( Commit 或是 Rollback ),Broker 收到確認(rèn)結(jié)果后處理邏輯如下:

  • 二次確認(rèn)結(jié)果為 Commit :Broker 將半事務(wù)消息標(biāo)記為可投遞,并投遞給消費(fèi)者。
  • 二次確認(rèn)結(jié)果為 Rollback :Broker 將回滾事務(wù),不會(huì)將半事務(wù)消息投遞給消費(fèi)者。

5、在斷網(wǎng)或者是生產(chǎn)者應(yīng)用重啟的特殊情況下,若 Broker 未收到發(fā)送者提交的二次確認(rèn)結(jié)果,或 Broker 收到的二次確認(rèn)結(jié)果為 Unknown 未知狀態(tài),經(jīng)過固定時(shí)間后,服務(wù)端將對(duì)消息生產(chǎn)者即生產(chǎn)者集群中任一生產(chǎn)者實(shí)例發(fā)起消息回查。

  1. 生產(chǎn)者收到消息回查后,需要檢查對(duì)應(yīng)消息的本地事務(wù)執(zhí)行的最終結(jié)果。
  2. 生產(chǎn)者根據(jù)檢查到的本地事務(wù)的最終狀態(tài)再次提交二次確認(rèn),服務(wù)端仍按照步驟4對(duì)半事務(wù)消息進(jìn)行處理。

筆者認(rèn)為事務(wù)消息的精髓在于:

  1. 本地事務(wù)執(zhí)行成功,消費(fèi)者才能消費(fèi)事務(wù)消息;
  2. 消息回查本身就是補(bǔ)償機(jī)制的實(shí)現(xiàn),事務(wù)生產(chǎn)者需提供了事務(wù)狀態(tài)查詢接口。

3 實(shí)戰(zhàn)例子

為了便于大家理解事務(wù)消息 ,筆者新建一個(gè)工程用于模擬支付訂單創(chuàng)建、支付成功、贈(zèng)送積分的流程。

首先,我們創(chuàng)建一個(gè)真實(shí)的訂單主題:order-topic 。

圖片圖片

然后在數(shù)據(jù)庫(kù)中創(chuàng)建三張表 訂單表、事務(wù)日志表、積分表。

圖片圖片

最后我們創(chuàng)建一個(gè) Demo 工程,生產(chǎn)者模塊用于創(chuàng)建支付訂單、修改支付訂單成功,消費(fèi)者模塊用于新增積分記錄。

圖片圖片

接下來,我們展示事務(wù)消息的實(shí)現(xiàn)流程。

1、創(chuàng)建支付訂單

調(diào)用訂單生產(chǎn)者服務(wù)創(chuàng)建訂單接口 ,在 t_order 表中插入一條支付訂單記錄。

圖片圖片

2、調(diào)用生產(chǎn)者服務(wù)修改訂單狀態(tài)接口

接口的邏輯就是執(zhí)行事務(wù)生產(chǎn)者的 sendMessageInTransaction  方法。

圖片圖片

生產(chǎn)者端需要配置事務(wù)生產(chǎn)者和事務(wù)監(jiān)聽器。

圖片圖片

發(fā)送事務(wù)消息的方法內(nèi)部包含三個(gè)步驟 :

圖片圖片

事務(wù)生產(chǎn)者首先發(fā)送半事務(wù)消息,發(fā)送成功后,生產(chǎn)者才開始執(zhí)行本地事務(wù)邏輯。

事務(wù)監(jiān)聽器實(shí)現(xiàn)了兩個(gè)功能:執(zhí)行本地事務(wù)和供 Broker 回查事務(wù)狀態(tài) 。

圖片圖片

執(zhí)行本地事務(wù)的邏輯內(nèi)部就是執(zhí)行 orderService.updateOrder 方法。

方法執(zhí)行成功則返回 LocalTransactionState.COMMIT_MESSAGE , 若執(zhí)行失敗則返回 LocalTransactionState.ROLLBACK_MESSAGE 。

圖片圖片

需要注意的是: orderService.updateOrder 方法添加了事務(wù)注解,并將修改訂單狀態(tài)和插入事務(wù)日志表放進(jìn)一個(gè)事務(wù)內(nèi),避免訂單狀態(tài)和事務(wù)日志表的數(shù)據(jù)不一致。

最后,生產(chǎn)者根據(jù)本地事務(wù)執(zhí)行結(jié)果向 Broker 提交二次確認(rèn)結(jié)果。

Broker 收到生產(chǎn)者確認(rèn)結(jié)果后處理邏輯如下:

  • 二次確認(rèn)結(jié)果為 Commit :Broker 將半事務(wù)消息標(biāo)記為可投遞,并投遞給消費(fèi)者。
  • 二次確認(rèn)結(jié)果為 Rollback :Broker 將回滾事務(wù),不會(huì)將半事務(wù)消息投遞給消費(fèi)者。

3、積分消費(fèi)者消費(fèi)消息,添加積分記錄

當(dāng) Broker 將半事務(wù)消息標(biāo)記為可投遞時(shí),積分消費(fèi)者就可以開始消費(fèi)主題 order-topic 的消息了。

圖片圖片

積分消費(fèi)者服務(wù),我們定義了消費(fèi)者組名,以及訂閱主題和消費(fèi)監(jiān)聽器。

圖片圖片

在消費(fèi)監(jiān)聽器邏輯里,冪等非常重要 。當(dāng)收到訂單信息后,首先判斷該訂單是否有積分記錄,若沒有記錄,才插入積分記錄。

而且我們?cè)趧?chuàng)建積分表時(shí),訂單編號(hào)也是唯一鍵,數(shù)據(jù)庫(kù)中也必然不會(huì)存在相同訂單的多條積分記錄。

4 總結(jié)

RocketMQ 事務(wù)消息是支持在分布式場(chǎng)景下保障消息生產(chǎn)和本地事務(wù)的最終一致性。

編寫一個(gè)實(shí)戰(zhàn)例子并不復(fù)雜,但使用事務(wù)消息時(shí)需要注意如下三點(diǎn):

1、事務(wù)生產(chǎn)者和消費(fèi)者共同協(xié)作才能保證業(yè)務(wù)數(shù)據(jù)的最終一致性;

2、事務(wù)生產(chǎn)者需要實(shí)現(xiàn)事務(wù)監(jiān)聽器,并且保存事務(wù)的執(zhí)行結(jié)果(比如事務(wù)日志表) ;

3、消費(fèi)者要保證冪等。消費(fèi)失敗時(shí),通過重試、告警+人工介入等手段保證消費(fèi)結(jié)果正確。

筆者會(huì)在后續(xù)的文章里,詳細(xì)解析事務(wù)消息的實(shí)現(xiàn)原理,敬請(qǐng)期待。

實(shí)戰(zhàn)代碼地址:

https://github.com/makemyownlife/rocketmq4-learning

責(zé)任編輯:武曉燕 來源: 勇哥java實(shí)戰(zhàn)分享
相關(guān)推薦

2024-10-29 08:34:27

RocketMQ消息類型事務(wù)消息

2021-10-03 21:41:13

RocketMQKafkaPulsar

2021-04-15 09:17:01

SpringBootRocketMQ

2009-08-01 09:06:35

UbuntuOneLinux開源操作系統(tǒng)

2009-03-09 15:12:39

XenServer安裝

2024-02-04 09:02:29

RocketMQ項(xiàng)目處理器

2023-07-15 08:01:38

2010-11-22 10:31:17

Sencha touc

2011-05-30 15:12:10

App Invento 初體驗(yàn)

2023-09-04 08:00:53

提交事務(wù)消息

2011-08-02 10:26:59

iOS 多線程 線程

2011-11-01 10:30:36

Node.js

2013-06-08 10:15:29

Outlook 201Outlook 201

2011-09-15 15:03:10

2010-12-13 11:39:39

2025-03-18 07:30:41

2009-11-30 10:09:02

谷歌Chrome OS

2017-09-05 05:55:24

AWS ES集群大數(shù)據(jù)

2011-09-05 10:20:21

Sencha ToucAPP

2009-07-21 13:08:08

iBATIS DAO
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)