精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

訂單系統中的數據一致性方案及RocketMQ事務消息詳解

開發 架構
生產中存在兩種常用的解決方案:TCC和可靠消息最終一致性。前者要求強一致,后者要求最終一致。強一致主要用于核心模塊,例如交易/訂單等。最終一致一般用于邊緣模塊例如庫存,通過mq去通知,保證最終一致性,也可以業務解耦。

數據一致性是確保業務操作正確執行的基礎,本文將以電商系統為例,詳細分析其分布式系統中的一致性問題。訂單核心流程:

訂單服務 -> 創建訂單 -> 庫存服務 -> 扣減庫存 -> 積分服務 -> 增加積分 -> 倉儲服務 -> 通知發貨

分布式一致性技術方案

生產中存在兩種常用的解決方案:TCC和可靠消息最終一致性。前者要求強一致,后者要求最終一致。

強一致主要用于核心模塊,例如交易/訂單等。最終一致一般用于邊緣模塊例如庫存,通過mq去通知,保證最終一致性,也可以業務解耦。

TCC:

訂單服務、庫存服務、積分服務 -> 綁定為一個TCC事務;

撤銷訂單時,回滾扣減庫存和增加積分。

可靠消息最終一致性:

可以去發送一個請求給消息中間件,由中間件保證一定會把消息交給下游的庫存服務去扣減庫存,倉儲服務去通知發貨等;

如果這個過程中有消息發送失敗,則可靠消息中間件應該保證不停的重試投遞消息。

本文重點分析如何利用RocketMQ的事務消息實現最終一致性,TCC事務將在另外一篇文章分享。

事務消息

RocketMQ的事務消息有兩個核心概念(流程):

  • Half Message,半消息

暫時不能被 Consumer消費的消息。Producer已經把消息發送到 Broker端,但是此消息的狀態被標記為不能投遞,處于這種狀態下的消息稱為半消息。事實上,該狀態下的消息會被放在一個叫做 RMQ_SYS_TRANS_HALF_TOPIC的主題下。

當 Producer端對它二次確認后,也就是 Commit之后,Consumer端才可以消費到;那么如果是Rollback,該消息則會被刪除,永遠不會被消費到。

  • 事務狀態回查

可能會因為網絡原因、應用問題等,導致Producer端一直沒有對這個半消息進行確認,那么這時候 Broker服務器會定時掃描這些半消息,主動找Producer端查詢該消息的狀態。

簡而言之,RocketMQ事務消息的實現原理就是基于兩階段提交和事務狀態回查,來決定消息最終是提交還是回滾的。

核心流程

結合整個訂單接口服務,分為兩個支付鏈路,一個是核心鏈路(訂單業務),一個是非核心鏈路(wms) 整個流程。

先向RocketMQ發送half msg,然后調用核心鏈路。核心鏈路要是返回失敗,就會走失敗的邏輯:退款,更改訂單狀態為取消,再給rocketmq發送callback廢棄掉剛才的消息。

如果成功,就commit msg讓消費者可以消費。如果在等待期間,一直沒有callback/commit那么mq就會走回調查詢具體的狀態。

消費者接收到消息后,消費完成就回復mq一個ack, 如果消費失敗了,mq就會重新投遞或者換一個服務投遞。使用rocketmq的half msg機制,可以實現這一套固定模式的最終一致性。

代碼實現

【核心鏈路-訂單、庫存、積分】

核心業務流程

【步驟一】:發送事務消息(half msg

springboot下,RocketMQ的集成還是很簡單的,引入
rocketmq-spring-boot-starter依賴、添加相關配置后,即可利用RocketMQTemplate的sendMessageInTransaction方法發送消息:

/**
 * 發送事務消息
 *
 * @param topic   topic
 * @param message 消息對象
 */
public void sendMessageInTransaction(String topic, Object message) {
    String transactionId = UUID.randomUUID().toString();
    TransactionSendResult result = this.rocketMQTemplate.sendMessageInTransaction(topic, MessageBuilder.withPayload(message)
            .setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
            .build(), message);
}

【步驟二】:broker回調,執行本地事務

消息發送成功之后,系統需要知道RocketMQ的broker是否成功收到了消息,這里主要借助
RocketMQTransactionListener注解實現。在成功收到回調后,會觸發executeLocalTransaction來
執行核心業務(訂單、庫存、積分等)。

@RocketMQTransactionListener
public class OrderTransactionListener implements RocketMQLocalTransactionListener {

    /**
     * 執行本地事務,即處理核心鏈路
     * @param msg
     * @param arg
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        try {
          	// 事務transactionId
            String transactionId = msg.getHeaders().get("rocketmq_TRANSACTION_ID").toString();
            // 本地事務,執行核心鏈路業務
            String payload = new String((byte[]) msg.getPayload());
            OrderTranscationMesageDTO data = JSONObject.parseObject(payload, OrderTranscationMesageDTO.class);
            orderService.executeCoreBusiness(data.getPayMoney(),data.getOrderDO(), data.getTransactionNo(),data.getPayType(),transactionId);
        } catch (Exception e) {
            log.error("本地事務執行異常:{}事務消息回滾", e.getMessage());
            return RocketMQLocalTransactionState.ROLLBACK;
        }
      	log.info("提交事務消息");
        return RocketMQLocalTransactionState.COMMIT;
    }

    /**
     * 校驗本地事務(broker未收到提交或回滾事務消息時主動回查)
     * @param msg
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        // 事務transactionId
        String transactionId = msg.getHeaders().get("rocketmq_TRANSACTION_ID").toString();
        // 數據庫能查到,說明本地事務執行失敗,需要回滾
        if (Objects.isNull(transcationLogDao.getById(transactionId))){
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        return RocketMQLocalTransactionState.COMMIT;
    }

}

執行核心業務的同時,還有一個很重要的環節,即記錄事務ID。為什么要記錄事務ID呢?假想這樣一種情況:我們本地事務即核心的業務都成功執行后,需要提交RocketMQ的事務消息,只有提交后,消息才能被消費者(即非核心業務系統,如倉儲)消費,但是如果提交時,網絡出現異常,broker一直未收到怎么辦呢,這時利用transactionId,也是RocketMA的回查機制了。

/**
  * 核心業務,并記錄RocketMQ事務ID
*/
@GlobalTransactional  // seata全局事務
public void executeCoreBusiness(BigDecimal payMoney, AppDerivativeGoodsOrderDO orderDO, String transactionNo, String payType,String transactionId) {
		// 核心業務偽代碼
    orderService.execute();
    storeFeign.execute();
    scoreFeign.execute();
    
    // 數據庫記錄rocket事務消息ID 用于異常情況下的回查
    if (Objects.nonNull(transactionId)){
        //寫入事務日志
        TransactionLogDO log = new TransactionLogDO();
        log.setId(transactionId);
        log.setBusiness("order");
        log.setForeignKey(String.valueOf(orderDO.getId()));
        transcationLogDao.save(log);
    }
}

本地事務執行成功之后,記錄事務ID,即便提交時,出現網絡異常,broker遲遲未收到,也可以利用回查機制,即checkLocalTransaction方法,得知本地事務是否執行成功。

用于記錄事務的表結構:

CREATE TABLE `transaction_log` (
  `id` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '事務ID',
  `business` varchar(32) COLLATE utf8mb4_bin NOT NULL COMMENT '業務標識',
  `foreign_key` varchar(32) COLLATE utf8mb4_bin NOT NULL COMMENT '對應業務表中的主鍵',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

【非核心鏈路-wms倉儲】

【步驟三】:消費消息,處理其他業務

上述的步驟保證了核心業務與RocketMQ消息的一致性,即核心業務成功,消息就一定會被發送到broker。接下來就是非核心業務(如倉儲物流)監聽消息,通過@RocketMQMessageListener實現:

@RocketMQMessageListener(topic = "order_topic",consumerGroup = "order_group")
public class TestListener implements RocketMQListener<MessageExt> {
    @Override
    public void onMessage(MessageExt messageExt) {
        if(messageExt.getReconsumeTimes() >= 3){
            log.error("消息重試已達最大次數,將通知業務人員排查問題。{}",messageExt.getMsgId());
            //消息處理,第3次處理失敗后,發送郵件通知人工介入
            sendMail(messageExt.getMsgId());
        }
        // 倉儲物流相關業務 
        wmsService.execute(messageExt.getBody());
    }
}

非核心業務,接受不了消息后,再處理相關業務,其實,此時已經與核心業務脫離了關聯,因此,不管它成功與否,核心業務都已經完成了,這也為何是最終一致性,而非強一致性。

最終一致性主要依賴的是RocketMQ的重試機制以及補償處理(比人工干預)。如上述代碼中,假若wmsService執行業務過程拋出了異常,即消息消費失敗,RocketMQ則會自動重發。默認16次,可以通過配置修改。另外,可以在重試一定次數后,做補償處理,例如,將執行失敗的任務記錄在數據庫,后續定時任務補償處理,抑或是像上述代碼,發送郵件通知相關人員。

冪等性消費

消息的重發,有可能帶來另外一個問題,重復消費。不做處理,就可能導致數據重復插入,倉儲系統就可能重復發貨。

冪等性:就是用戶對于同一操作發起的一次請求或者多次請求的結果是一致的,不會因為多次點擊而產生了副作用。

實現冪等性消費的方式有很多種,具體怎么做,根據自己的情況來看。一種常用的方式就是利用redis緩存,在執行操作之前,先到緩存中查詢,該操作是否已執行過。

總結

本文重點闡述了基于RocketMQ來實現最終一致性的分布式事務案例。

責任編輯:姜華 來源: 今日頭條
相關推薦

2021-03-04 06:49:53

RocketMQ事務

2023-12-01 13:51:21

數據一致性數據庫

2019-01-15 17:58:03

微服務架構數據

2019-12-17 08:40:33

微服務架構數據

2009-06-18 09:18:08

Oracle檢索數據數據一致性事務恢復

2021-11-01 21:15:54

微服務系統數據

2023-08-22 09:32:44

邊緣計算管理

2025-03-27 08:20:54

2023-11-22 12:55:59

微服務架構數據庫

2022-07-21 06:54:28

微服務系統RocketMQ

2018-09-11 10:46:10

緩存數據庫一致性

2024-12-26 15:01:29

2023-09-07 08:11:24

Redis管道機制

2021-12-05 21:06:27

軟件

2021-06-16 08:33:02

分布式事務ACID

2021-10-18 10:30:59

流計算阿里云

2021-10-13 09:55:11

流計算引擎數據

2023-06-07 08:10:29

2023-12-27 14:23:10

微服務數據存儲

2023-06-29 08:00:59

redis數據MySQL
點贊
收藏

51CTO技術棧公眾號

在线观看a视频| 羞羞色院91蜜桃| 欧美1区二区| 在线观看免费成人| 特级黄色录像片| 污污视频在线免费看| 视频一区欧美日韩| 欧美裸身视频免费观看| 国产精品久久不卡| 91麻豆精品国产综合久久久| 香蕉加勒比综合久久| 四虎永久在线精品免费一区二区| 国产日韩精品suv| 美女国产一区| 欧美极品在线播放| 日本美女黄色一级片| 久久99国产精品久久99大师| 欧美日韩一区久久| 爱福利视频一区二区| 黄色在线视频网站| 国产亚洲一二三区| 精品国产_亚洲人成在线| 一区不卡在线观看| 久久蜜桃资源一区二区老牛| 欧美风情在线观看| 三级黄色在线观看| 欧美自拍偷拍| 日韩久久精品成人| 成年人性生活视频| 伊人久久精品| 欧美午夜寂寞影院| 黄色a级片免费| а√天堂中文在线资源8| 亚洲欧美激情在线| 一区不卡字幕| 北岛玲一区二区三区| 337p粉嫩大胆噜噜噜噜噜91av| 97人摸人人澡人人人超一碰| 在线免费观看一级片| 久久蜜桃精品| 国产mv久久久| 黄色污污视频软件| 久久人人精品| 国产不卡精品视男人的天堂| 日韩中文字幕在线观看视频| 99综合视频| 性欧美视频videos6一9| 国产无套在线观看| 亚洲第一黄色| 国内自拍欧美激情| 日本一二三区不卡| 亚洲另类自拍| 78色国产精品| av网站中文字幕| 香蕉久久国产| 国产精品第10页| 中文字幕一区二区三区免费看 | 成人一区二区三区视频在线观看 | 欧美日韩在线中文| 麻豆蜜桃在线观看| 精品福利视频导航| 成人在线免费播放视频| 午夜日韩成人影院| 精品1区2区3区| 色网站在线视频| 视频精品二区| 亚洲精品wwww| 公侵犯人妻一区二区三区| 免费国产自久久久久三四区久久| 国产一区二区三区视频| 中文字幕黄色网址| 久久久久国产精品| 欧美激情免费在线| 久久青青草原亚洲av无码麻豆| 久久一区二区三区超碰国产精品| 国产成人综合精品在线| 91在线视频国产| 国产91精品一区二区麻豆亚洲| 国产日韩久久| 男人的天堂在线免费视频| 国产精品无遮挡| 欧美在线观看黄| 中文字幕在线官网| 欧美日韩一区小说| 成熟妇人a片免费看网站| 亚洲精品国产动漫| 久久久国产精品视频| 日韩xxx高潮hd| 日韩高清不卡一区二区| 7777精品久久久大香线蕉小说| 色噜噜一区二区三区| 国产色91在线| 日韩不卡视频一区二区| 裤袜国产欧美精品一区| 欧美久久久久中文字幕| 99re久久精品国产| 色综合咪咪久久网| 97福利一区二区| 91精品中文字幕| 99精品视频一区二区| 在线免费观看成人| 性国裸体高清亚洲| 日韩欧美成人一区二区| 久久只有这里有精品| 欧美不卡在线| 国产精品入口夜色视频大尺度 | 国产亚洲视频在线观看| 久久午夜无码鲁丝片午夜精品| 久久综合图片| 国产伦理久久久| 成人午夜在线影视| 欧美三区在线观看| 久久中文字幕人妻| 在线国产精品一区| 亚洲自拍偷拍区| freemovies性欧美| 一本色道亚洲精品aⅴ| 亚洲美女精品视频| 国产精品99久久| 国产精品欧美日韩久久| 午夜av免费在线观看| 一区二区三区在线观看动漫| 韩国视频一区二区三区| 亚州av一区| 欧美精品videos另类日本| 一区不卡在线观看| 中文无字幕一区二区三区| 欧美色图另类小说| 免费看久久久| 国内揄拍国内精品| 农村少妇久久久久久久| 亚洲精品国产精华液| 91亚洲一区二区| 色婷婷亚洲mv天堂mv在影片| 国产成一区二区| 九色视频在线播放| 日韩欧美国产视频| 国产男女猛烈无遮挡a片漫画 | 你懂的一区二区三区| 午夜精品久久17c| 蜜桃91麻豆精品一二三区| 综合激情成人伊人| 超碰在线免费av| 欧美91视频| 99热国产免费| 成人在线高清免费| 亚洲成人在线视频播放| 日韩欧美亚洲国产| av资源站一区| 欧美色图另类小说| 国产成人一区| 国产精品一区二区三区成人| 中文字幕在线播放| 欧美日韩和欧美的一区二区| 国产视频123区| 久久精品99国产精品| 久久99国产精品一区| www.久久99| 九九久久国产精品| 熟妇人妻中文av无码| 精品久久久久久中文字幕一区奶水| 中文成人无字幕乱码精品区| 一区二区日韩免费看| 看欧美日韩国产| 黄色成人在线视频| 超薄丝袜一区二区| 后进极品白嫩翘臀在线视频| 午夜精品久久久久久久99水蜜桃| 国产精品无码一区二区三| 欧美专区在线| 伊人久久大香线蕉av一区| 91精品入口| 3344国产精品免费看| av成人手机在线| 欧美一卡二卡三卡四卡| 国产无码精品视频| 欧美激情一区三区| 中文字幕在线播放一区二区| 国产精品久久久久久久久久妞妞 | 在线视频欧美精品| sm捆绑调教视频| 成人av网在线| 午夜免费高清视频| 国产精品videossex久久发布| 久久天天狠狠| 先锋影音一区二区| 性色av一区二区三区免费| 北岛玲一区二区三区| 欧美成人一区二区三区片免费| 欧美激情亚洲综合| 中文字幕在线不卡| 亚洲国产果冻传媒av在线观看| 奇米一区二区三区av| 国产一级大片免费看| 亚洲亚洲免费| yellow视频在线观看一区二区 | 欧美人xxx| 日韩av在线免费看| 国产伦精品一区二区三区视频痴汉| 一区二区三区在线免费视频| 国产一区二区三区四区五区六区| 国产综合久久久久影院| 四虎永久在线精品无码视频| 午夜日本精品| 五月天婷亚洲天综合网鲁鲁鲁| 91精品国产乱码久久久竹菊| 国产精品欧美亚洲777777| 17videosex性欧美| 久久国产精品久久久久久| 国产在线91| 亚洲精品suv精品一区二区| 国产精品无码在线播放| 一本一道久久a久久精品综合蜜臀| 欧产日产国产v| 日本一二三不卡| 丰满少妇在线观看资源站| 国产99久久久国产精品免费看 | av电影一区二区| 亚洲综合123| 另类人妖一区二区av| 久久久噜噜噜www成人网| 韩国av一区| 国产免费xxx| 天天射成人网| 亚洲精品高清视频| 欧美色就是色| 日本一区二区视频| 九九综合九九| 欧美日韩国产三区| 校园春色另类视频| 国产精品亚洲不卡a| 欧美激情三级| 亚洲bt天天射| 国产精品久久久久久久久久久久久久久 | 毛片久久久久久| 久久精品人人做人人爽人人| 日韩精品人妻中文字幕有码| 国产乱理伦片在线观看夜一区| www.色欧美| 久久国产精品99精品国产| 色乱码一区二区三区在线| 日本系列欧美系列| 国产真人无码作爱视频免费| 日韩国产欧美三级| 在线免费观看视频黄| 奇米亚洲午夜久久精品| 91欧美视频在线| 久久99热国产| 18深夜在线观看免费视频| 国产一区二区三区在线观看精品| 一级黄色片在线免费观看| 国产一区二三区| 日本少妇一级片| av一区二区三区在线| 精品无码一区二区三区 | 视频三区二区一区| 日韩欧美国产精品综合嫩v| 一区二区在线不卡| 欧美日韩三级| www.99热这里只有精品| 午夜亚洲精品| 国产自偷自偷免费一区| 国内久久精品视频| 亚洲性图第一页| 久久综合九色综合97婷婷女人| 亚洲最大成人网站| 国产精品久久久久影视| 国产精品 欧美激情| 亚洲福中文字幕伊人影院| 99热国产在线观看| 欧洲色大大久久| 国产熟女精品视频| 亚洲国产欧美久久| 自拍视频在线网| 欧美高清视频免费观看| 欧美成人黑人| 91久久久久久久久久久| 成人知道污网站| 欧美日韩国产高清视频| 香蕉久久网站| 国产精品网站免费| 另类欧美日韩国产在线| 国产伦精品一区二区三区88av| 国产校园另类小说区| fc2ppv在线播放| 黄色成人av在线| 国产精品特级毛片一区二区三区| 亚洲精品美女在线观看播放| 2019中文字幕在线视频| 久久久女女女女999久久| 日本综合视频| 国产精品福利视频| 久久社区一区| 国产二区视频在线播放| 国产美女精品在线| 亚洲一区视频在线播放| 亚洲综合一二三区| 亚洲视频在线观看免费视频| 亚洲国产高潮在线观看| 免费av在线播放| 热re99久久精品国产66热| 国产在线视频欧美一区| 日韩精品欧美专区| 亚洲黄色精品| 樱花草www在线| 国产午夜精品一区二区| 麻豆一区二区三区精品视频| 欧美日韩国产一区| 手机福利在线| 欧美黄色性视频| 国产激情综合| 亚洲欧美日韩在线综合| 亚洲综合不卡| 亚洲成年人在线观看| 亚洲欧美日韩一区二区三区在线观看| 国产伦精品一区二区三区视频我| 日韩视频一区二区在线观看| 第一福利在线| 欧洲成人午夜免费大片| 久久精品亚洲成在人线av网址| 欧洲美女和动交zoz0z| 欧美aaaaaa午夜精品| 亚欧洲乱码视频| 午夜精品一区二区三区电影天堂 | 日韩一区二区欧美| 精品免费av一区二区三区| 欧美极品视频一区二区三区| 伊人蜜桃色噜噜激情综合| 亚欧精品在线视频| 亚洲天堂2014| 国产精品无码专区av免费播放| 永久免费毛片在线播放不卡 | 99pao成人国产永久免费视频| 熟妇无码乱子成人精品| 中文字幕一区二区在线观看| 中文字幕乱码人妻二区三区| 亚洲美女喷白浆| 色网在线免费观看| 蜜桃网站成人| 亚洲欧美bt| 久久久久亚洲av无码专区桃色| 天天做天天摸天天爽国产一区| 日韩一级片免费观看| 欧美精品xxx| 香港久久久电影| www插插插无码免费视频网站| 韩国av一区二区三区四区| 午夜国产小视频| 9191成人精品久久| 久操免费在线| 97伦理在线四区| 亚洲人体偷拍| 国产黄色网址在线观看| 欧美日韩免费在线| 男同在线观看| 国产精品久久一| 日韩精品中文字幕第1页| 国产精欧美一区二区三区白种人| 日韩一区在线看| 精品久久久中文字幕人妻| 久久免费国产视频| 亚洲电影一级片| 婷婷免费在线观看| 亚洲欧美日韩国产综合| 粉嫩av一区二区夜夜嗨| 26uuu另类亚洲欧美日本老年| 国产调教一区二区三区| 亚洲视频第二页| 又紧又大又爽精品一区二区| 视频二区在线观看| 国产精品偷伦一区二区| 午夜日韩视频| 少妇特黄一区二区三区| 欧美在线视频不卡| 在线免费观看污| 久久久综合亚洲91久久98| 热久久国产精品| 国内偷拍精品视频| 亚洲免费伊人电影在线观看av| 91精品国产66| 日韩一级特黄毛片| 国产欧美日韩一区二区三区在线观看 | 欧洲女同同性吃奶| 欧美精品久久99久久在免费线| h片在线观看| 亚洲精品一品区二品区三品区| 国产高清视频一区| 国产精华7777777| 欧美激情三级免费| 欧美mv日韩| 亚洲精品中文字幕在线播放| 欧美日韩国产影片| 色网在线免费观看| 可以在线看黄的网站| 久久免费偷拍视频| 风流少妇一区二区三区91| 国产精品美女久久久久久免费| 亚洲午夜激情在线| 国产免费嫩草影院| 日韩经典第一页|