精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

国产成人女人毛片视频在线| 爽爽爽爽爽爽爽成人免费观看| 大陆极品少妇内射aaaaa| 欧美无人区码suv| 麻豆免费在线| 中文字幕欧美区| 国产69精品久久久久99| 香蕉视频黄色在线观看| 久久不卡日韩美女| 亚洲国产综合91精品麻豆| 欧美一区二区三区在线播放| 99精品视频在线播放免费| 国产农村妇女精品一二区| 最新的欧美黄色| 国产精品久久AV无码| 农村妇女一区二区| 亚洲高清中文字幕| 亚洲影视九九影院在线观看| 午夜影院在线看| 91亚洲国产成人久久精品| 色香色香欲天天天影视综合网| 亚洲在线播放电影| 特黄视频在线观看| 另类调教123区| 2019av中文字幕| 欧美卡一卡二卡三| 波多野结衣在线播放一区| 亚洲精品99久久久久| 激情文学亚洲色图| 日韩经典一区| 日韩欧美在线国产| 拔插拔插海外华人免费| 高h震动喷水双性1v1| 看电视剧不卡顿的网站| 日本成人免费在线| 国产稀缺真实呦乱在线| 欧美jjzz| 欧美成人免费一级人片100| 中文字幕网站在线观看| 香蕉久久精品日日躁夜夜躁| 欧美成人一区二区三区| xxxx在线免费观看| 国语自产精品视频在线看抢先版结局| 欧美日韩在线免费| 青青艹视频在线| 白浆在线视频| 亚洲国产精品麻豆| 欧美日韩福利在线| 77thz桃花论族在线观看| 成人免费高清视频在线观看| 亚洲精品免费一区二区三区| 91久久精品无码一区二区| 日本亚洲三级在线| 国产精品美女免费| 91精品一区二区三区蜜桃| 日韩理论在线| 日韩视频―中文字幕| 少妇献身老头系列| 亚洲免费一区三区| 精品国产免费人成电影在线观看四季 | 无码av中文一区二区三区桃花岛| 轻点好疼好大好爽视频| 欧美寡妇性猛交xxx免费| 亚洲永久精品大片| av免费观看国产| 日本不良网站在线观看| 日韩欧美国产视频| 国产精品乱码久久久久| 欧美a一级片| 日韩亚洲电影在线| 人妻激情偷乱频一区二区三区| 成人免费直播在线| 日韩电影视频免费| 人妻aⅴ无码一区二区三区| 青草国产精品| 久精品免费视频| 在线观看免费国产视频| 日韩福利电影在线观看| 国产欧美中文字幕| 亚洲精品无码久久久| 久久狠狠婷婷| 成人精品网站在线观看| 懂色av成人一区二区三区| 91在线精品一区二区三区| 欧美日产一区二区三区在线观看| 中文日本在线观看| 亚洲男人天堂一区| 69堂免费视频| 3d动漫一区二区三区在线观看| 日韩一区二区电影在线| 日本黄色特级片| 97在线精品| 97在线观看免费| 激情综合五月网| 中文国产一区| 色综合久综合久久综合久鬼88| 国产一级淫片免费| 日韩一区欧美二区| 3d动漫精品啪啪一区二区三区免费| 高h震动喷水双性1v1| 国产女同互慰高潮91漫画| 日本a级片在线播放| 粉嫩一区二区三区| 亚洲成人亚洲激情| 中国1级黄色片| 国产欧美日韩在线一区二区| 欧美成人激情在线| 日韩欧美国产另类| jlzzjlzz亚洲日本少妇| 亚洲美女自拍偷拍| 亚洲va中文在线播放免费| 日韩精品最新网址| 天堂资源在线视频| 老鸭窝毛片一区二区三区| 91精品天堂| 日本免费视频在线观看| 欧美午夜电影在线| 久久久久亚洲av无码网站| 日韩中文首页| 国产成人精品免高潮在线观看| 精品久久国产视频| 亚洲欧洲韩国日本视频| 黑人粗进入欧美aaaaa| 亚洲精品动漫| 精品乱码亚洲一区二区不卡| 中文字幕91视频| 日韩激情一二三区| 久久亚洲高清| аⅴ资源天堂资源库在线| 欧美一区二区精品| 亚洲熟女毛茸茸| 美女视频免费一区| 性刺激综合网| 青青热久免费精品视频在线18| 日韩成人网免费视频| 久久久久久免费观看| 一本久道久久综合婷婷鲸鱼| 91传媒视频在线观看| 老司机午夜在线视频| 欧美日韩一区二区在线观看| 国产激情在线免费观看| 日韩一区二区在线| 国产成人在线播放| 欧美日本网站| 一本一本久久a久久精品综合麻豆| 97精品人妻一区二区三区蜜桃| 欧美福利视频| 51成人做爰www免费看网站| 成人在线观看亚洲| 欧美一区二区在线免费观看| 国产高清在线免费观看| 国产精品一区二区不卡| 黄网站色视频免费观看| 91蝌蚪精品视频| 久久全球大尺度高清视频| 日本xxxx人| 国产精品入口麻豆九色| 亚洲综合日韩欧美| 亚洲精品一区二区在线看| 成人免费福利视频| av在线app| 精品久久久久99| 色播视频在线播放| 久久女同精品一区二区| 18岁视频在线观看| 色综合天天综合网中文字幕| 国产日韩在线播放| 色a资源在线| 亚洲精品美女网站| 午夜精品久久久久久久蜜桃| 中文字幕一区二区在线播放| 少妇性l交大片7724com| 亚洲视频大全| 视频一区视频二区视频| 久久久久久久久久久久电影| 久久噜噜噜精品国产亚洲综合| 日韩欧美亚洲系列| 欧美猛男男办公室激情| 久久久精品视频免费| 久久久久高清精品| 亚洲第一天堂久久| 亚洲精品美女91| 亚洲成色www久久网站| 日韩精品免费视频一区二区三区| 国内成人精品一区| 成人jjav| 亚洲国产精品小视频| 在线免费观看国产精品| 中文字幕亚洲成人| 国产中文字幕一区二区| 亚洲一级二级| 日本欧美色综合网站免费| 国产精品日韩精品在线播放| 欧美亚洲国产视频小说| 久草中文在线| 亚洲欧美成人精品| 国产激情视频在线播放| 一本在线高清不卡dvd| 91精品国产高清一区二区三蜜臀| 91香蕉视频污| 91av免费观看| 日本aⅴ免费视频一区二区三区| 中文字幕在线中文| 不卡在线一区| 久久综合狠狠综合久久综青草| 国产精一区二区| 国产成人+综合亚洲+天堂| 丝袜国产在线| 色青青草原桃花久久综合 | 亚洲成av在线| 久久免费精品视频| 黄色在线免费| 色综合影院在线| 青青草在线播放| 精品国精品自拍自在线| 国产亲伦免费视频播放| 欧美中文字幕一区二区三区| 亚洲免费在线视频观看| 亚洲午夜免费电影| 澳门黄色一级片| 中文字幕中文字幕一区| 制服 丝袜 综合 日韩 欧美| 99久久精品一区二区| 亚洲成人精品在线播放| 成人a'v在线播放| 精品福利影视| 豆花视频一区二区| 成人蜜桃视频| 日韩中文在线| 亚洲一区国产精品| 中文字幕日韩亚洲| 国产在线久久久| 欧美国产视频| 国产欧美va欧美va香蕉在| 欧美色网在线| 国产精品大陆在线观看| 高清不卡亚洲| 日韩中文娱乐网| av在线天堂播放| 国产一区二区三区在线观看视频 | 亚洲精品高清无码视频| 日韩一区二区久久| 妞干网在线视频观看| 亚洲激情一区| 九色在线视频观看| 久久精品人人| 色婷婷狠狠18| 久久精品国产99久久6| 五月婷婷之婷婷| 国内外成人在线| 亚洲一级片av| 国产精品1区2区3区在线观看| 黄色一级片免费播放| 国产一区二区在线看| 无码人妻一区二区三区精品视频| 成人国产精品免费观看视频| 88av在线播放| 91亚洲精华国产精华精华液| 国产熟妇久久777777| 欧美精彩视频一区二区三区| 五月婷婷综合激情网| 亚洲久草在线视频| 国产一国产二国产三| 色诱亚洲精品久久久久久| 中文av免费观看| 欧美一区二区三区精品| 欧美一级特黄aaaaaa大片在线观看| 亚洲国产精彩中文乱码av在线播放| 人成在线免费视频| 中文字幕免费国产精品| 午夜影院免费在线| 欧美中在线观看| 久久久久久久性潮| 国产91精品入口17c| 美女久久99| 中国成人亚色综合网站| 三级精品视频| 水蜜桃亚洲精品| 欧美在线首页| 国产极品美女高潮无套久久久| 六月丁香综合在线视频| 中文视频在线观看| 国产精品视频你懂的| 久久99久久98精品免观看软件| 欧美日韩在线视频首页| 一级片视频网站| 亚洲精品福利在线| 午夜不卡视频| 日本午夜人人精品| 精品视频一区二区三区在线观看| 精品国产综合久久| 久久精品亚洲人成影院| 国产成人黄色片| 国产中文字幕精品| 精品人妻互换一区二区三区| 亚洲女同ⅹxx女同tv| 国产又粗又爽视频| 日韩欧美成人一区| 91社区在线观看播放| 97精品伊人久久久大香线蕉| 日本欧美在线| 奇米影视首页 狠狠色丁香婷婷久久综合 | 国产一区二区三区精品视频| 熟女俱乐部一区二区视频在线| 亚洲美女偷拍久久| 正在播放木下凛凛xv99| 亚洲精品美女在线观看播放| 黄色网页在线播放| 国产成人精品在线视频| 粉嫩的18在线观看极品精品| 一区二区三区在线视频看| 丝瓜av网站精品一区二区| 欧美熟妇精品一区二区| 中文字幕一区二区三区在线播放 | 岛国毛片av在线| 91精品久久久久久久久久入口 | www.亚洲人| 五月天丁香激情| 91麻豆精品国产91久久久| 国产最新视频在线观看| 欧美亚洲在线观看| 黑人久久a级毛片免费观看| 欧美一级黄色录像片| 蓝色福利精品导航| 日韩影视一区二区三区| 一本到不卡免费一区二区| 午夜在线视频观看| 久久久欧美一区二区| 日韩三级不卡| 日韩成人三级视频| 国产宾馆实践打屁股91| 日本中文字幕免费在线观看| 91精品在线免费观看| 欧美一区二区三区在线观看免费| 国产欧美精品xxxx另类| 日韩毛片视频| 岛国毛片在线播放| 国产精品电影一区二区| ,一级淫片a看免费| 久久人人爽人人爽爽久久| 日韩一区二区三区四区五区 | 激情欧美国产欧美| 国产吃瓜黑料一区二区| 一区二区三区精品在线| www.黄色一片| 久久91亚洲人成电影网站| 日韩精品一级| 丁香六月激情网| 成人av先锋影音| 特黄视频免费看| 亚洲图片制服诱惑| 欧美v亚洲v综合v国产v仙踪林| 天天成人综合网| 国产很黄免费观看久久| 久久精品这里只有精品| 亚洲成人免费网站| 日本免费一区二区六区| 欧美乱偷一区二区三区在线| 久久成人国产| 天天爽天天爽天天爽| 欧美一二三区在线观看| 888av在线视频| 牛人盗摄一区二区三区视频 | 美女网站视频在线观看| 亚洲va欧美va人人爽| 青青艹在线观看| 视频直播国产精品| 一区二区三区国产好| 欧美精品一区免费| 国产精品美女久久久久久| 精品人妻aV中文字幕乱码色欲| 久久久在线视频| 成人在线国产| 性感美女一区二区三区| 欧美性猛交xxxx黑人猛交| 午夜激情在线观看| 国产伦精品一区二区三区视频孕妇| 日韩中文在线电影| 男插女视频网站| 中文字幕中文在线不卡住| 亚洲成人一二三区| 日av在线播放中文不卡| 久久久五月天| 三级男人添奶爽爽爽视频| 欧美日韩视频专区在线播放| av免费在线免费| 成人国产精品一区二区| 1024日韩| 激情五月深爱五月| 亚洲精品一线二线三线无人区| 最新日韩一区| 真人抽搐一进一出视频| 中文字幕成人在线观看| 日韩在线观看视频一区| 国产情人节一区| 国产精品日韩| 成人在线观看小视频| 亚洲人成自拍网站| 成人午夜大片| 国产又粗又长又爽又黄的视频|