日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
事務(wù)消息應(yīng)用場(chǎng)景、實(shí)現(xiàn)原理與項(xiàng)目實(shí)戰(zhàn)

1、活動(dòng)中心場(chǎng)景介紹

創(chuàng)新互聯(lián)是一家專注于網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作與策劃設(shè)計(jì),茶陵網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:茶陵等地區(qū)。茶陵做網(wǎng)站價(jià)格咨詢:18982081108

在電商系統(tǒng)上線初期,往往會(huì)進(jìn)行一些“拉新”活動(dòng),例如活動(dòng)部門提出新用戶注冊(cè)送積分、送優(yōu)惠券活動(dòng)。

基于分布式、微服務(wù)的設(shè)計(jì)理念,通常的架構(gòu)設(shè)計(jì)(子系統(tǒng)交互)如下圖所示:

其核心系統(tǒng)介紹如下:

  • 賬戶中心

提供用戶登錄、用戶注冊(cè)等服務(wù),一個(gè)新用戶注冊(cè)時(shí),向MQ服務(wù)器中的USER_REGISTER主題發(fā)送一條消息,主流程結(jié)束,與送積分,送優(yōu)惠券等過程解耦。

  • 優(yōu)惠券(券系統(tǒng))

提供發(fā)放優(yōu)惠券、使用優(yōu)惠券等與券相關(guān)的基礎(chǔ)服務(wù)。

  • 積分中心

提供積分相關(guān)的服務(wù),例如積分贈(zèng)送、積分消費(fèi)、積分查詢等基礎(chǔ)服務(wù)。

  • 送積分服務(wù)(消費(fèi)者)

訂閱MQ,按照規(guī)則決定是否需要贈(zèng)送積分,如果需要?jiǎng)t調(diào)用積分相關(guān)的基礎(chǔ)接口,完成積分的發(fā)放。

  • 送優(yōu)惠券(消費(fèi)者)

訂閱MQ,按照規(guī)則決定是否需要贈(zèng)送優(yōu)惠券,如果需要?jiǎng)t調(diào)用券系統(tǒng)相關(guān)的基礎(chǔ)接口,完成優(yōu)惠券的發(fā)放。

上面的架構(gòu)設(shè)計(jì)非常優(yōu)雅,但并不是無懈可擊,讀者們肯定會(huì)想到如果新用戶注冊(cè)成功,但消息發(fā)送到MQ失敗,或者消息成功發(fā)送到MQ,但發(fā)送完MQ后系統(tǒng)出現(xiàn)異常導(dǎo)致用戶注冊(cè)失敗又該如何呢?

上面的問題其實(shí)就是典型的分布式事務(wù)問題:即如何保證用戶注冊(cè)(數(shù)據(jù)庫(kù)操作)與MQ消息發(fā)送這兩個(gè)分布式操作的一致性。

RocketMQ事務(wù)消息閃亮登場(chǎng)。

2、事務(wù)消息實(shí)現(xiàn)原理

一言以蔽之:RocketMQ事務(wù)消息要解決的問題是消息發(fā)送與業(yè)務(wù)的一致性,其解決思路:二階段提交與事務(wù)狀態(tài)回查,其具體實(shí)現(xiàn)流程如下圖所示:

其核心設(shè)計(jì)理念:

  • 應(yīng)用程序開啟一個(gè)數(shù)據(jù)庫(kù)事務(wù),進(jìn)行數(shù)據(jù)庫(kù)操作,并且在事務(wù)中發(fā)送一條PREPARE消息,PREPARE消息發(fā)送成功后通知應(yīng)用程序記錄本地事務(wù)狀態(tài),然后提交本地事務(wù)。
  • RocketMQ在收到類型為PREPARE的消息時(shí),首先備份消息的原主題與原消息消費(fèi)隊(duì)列,然后將消息存儲(chǔ)在主題為RMQ_SYS_TRANS_HALF_TOPIC的消息隊(duì)列中,故PREPARE的消息是不會(huì)被客戶端消費(fèi)的。
  • Broker消息服務(wù)器開啟一個(gè)定時(shí)任務(wù)處理RMQ_SYS_TRANS_HALF_TOPIC中的消息,會(huì)每隔指定時(shí)間向消息發(fā)送者發(fā)起事務(wù)狀態(tài)查詢請(qǐng)求 ,詢問消息發(fā)送者客戶端本地事務(wù)是否成功,然后根據(jù)回查狀態(tài)決定是提交還是回滾,即對(duì)處于PREPARE狀態(tài)進(jìn)行提交或回滾操作。
  • 發(fā)送者如果明確得知事務(wù)成功,則可以返回COMMIT,服務(wù)端會(huì)提交該條消息,具體操作是恢復(fù)原消息的主題與隊(duì)列,重新發(fā)送到Broker,消費(fèi)端感知后消費(fèi)。
  • 發(fā)送者如果無法明確得知事務(wù)狀態(tài),則返回UNOWN,此時(shí)服務(wù)端會(huì)等待一定時(shí)間后再次向發(fā)送者詢問,默認(rèn)詢問15次。
  • 發(fā)送者如果非常明確得知事務(wù)失敗,則可以返回ROLLBACK。

在具體實(shí)踐中,消息發(fā)送者在無法獲取事務(wù)狀態(tài)時(shí)不要武斷的返回ROLLBACK,而是要返回UNOWN,讓服務(wù)端定時(shí)重試回查,說明如下:

在將PREPARE消息發(fā)送到Broker后,服務(wù)端發(fā)起事務(wù)查詢時(shí)本地事務(wù)可能還未提交,為了避免無效的事務(wù)回查機(jī)制,RocketMQ通常至少在收到PREPARE消息6s后才會(huì)發(fā)起第一次事務(wù)回查,可通過 transactionTimeOut 配置。故客戶端在實(shí)現(xiàn)事務(wù)回查時(shí)無法證明事務(wù)狀態(tài)時(shí)不應(yīng)該返回ROLLBACK,而是返回UNOWN。

3、事務(wù)消息實(shí)戰(zhàn)

光說不練假把式,接下來以一個(gè)新用戶注冊(cè)送優(yōu)惠券的場(chǎng)景來詳細(xì)介紹如何使用事務(wù)消息。

項(xiàng)目模塊職責(zé)說明如下:

事務(wù)消息的核心代碼組裝在transaction-service,其核心類圖如下:

其中核心要點(diǎn)如下:

  • UserServiceImpl

Dubbo接口業(yè)務(wù)實(shí)現(xiàn)類,類似MVC的控制層,在這里做一些參數(shù)驗(yàn)證,但不執(zhí)行具體的業(yè)務(wù)邏輯,只是發(fā)送一條事務(wù)消息到MQ。

  • UserRegTransactionListener

事務(wù)監(jiān)聽器,在 executeLocalTransaction 方法中執(zhí)行業(yè)務(wù)邏輯,數(shù)據(jù)庫(kù)本地事務(wù)加在該方法。

溫馨提示:之所以不在UserServicveImpl中執(zhí)行本地事務(wù),是因?yàn)?executeLocalTransaction 中拋出的異常會(huì)被RocketMQ框架捕捉,及異常無法被UserServiceImpl感知,即無法實(shí)現(xiàn)其事務(wù)的一致性。

接下來展示其核心代碼,全部源碼已上傳到github倉(cāng)庫(kù)。

倉(cāng)庫(kù)地址:https://github.com/dingwpmz/rocketmq-learning

3.1 UserServiceImpl 核心實(shí)現(xiàn)

UserServiceImpl 的核心要點(diǎn)如下:

  • 首先應(yīng)該對(duì)參數(shù)進(jìn)行校驗(yàn)、業(yè)務(wù)邏輯進(jìn)行校驗(yàn),如果不滿足業(yè)務(wù)條件,會(huì)發(fā)送一些無效消息到MQ,雖然不會(huì)造成業(yè)務(wù)異常,但會(huì)消耗性能
  • 發(fā)送事務(wù)消息,建議對(duì)消息設(shè)置Key,Key的值可以用業(yè)務(wù)處理流水號(hào)(可唯一表示該業(yè)務(wù)操作)或者核心業(yè)務(wù)字段(例如訂單編號(hào))
  • 業(yè)務(wù)入口類可通過事務(wù)消息發(fā)送狀態(tài)來判斷業(yè)務(wù)是否失敗。

3.2 UserRegTransactionListener 核心實(shí)現(xiàn)

事務(wù)監(jiān)聽器需要實(shí)現(xiàn)執(zhí)行本地事務(wù)與事務(wù)回查兩個(gè)接口。

3.2.1 實(shí)現(xiàn) executeLocalTransaction

首先需要實(shí)現(xiàn) executeLocalTransaction 方法,執(zhí)行本地事務(wù),其代碼如下圖所示:

其中幾個(gè)關(guān)鍵點(diǎn)說明如下:

  • 在該方法上添加數(shù)據(jù)庫(kù)事務(wù)標(biāo)簽。
  • 執(zhí)行業(yè)務(wù)邏輯,示例Demo只是將用戶數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)。
  • 如果業(yè)務(wù)執(zhí)行失敗,可明確告知需要回滾,上層調(diào)用方也可根據(jù)ROLLBACK_MESSAGE進(jìn)行相應(yīng)的處理。
  • 如果業(yè)務(wù)成功,不建議直接返回COMMIT,而是建議返回UNKNOW,因?yàn)樵摲椒ūM管在方法最后一行,但可能發(fā)生斷電等異常情況,數(shù)據(jù)庫(kù)并沒有成功。

3.2.2 實(shí)現(xiàn) checkLocalTransaction

其次需要實(shí)現(xiàn)事務(wù)狀態(tài)回查,用來RocketMQ服務(wù)端感知事務(wù)是否成功,其實(shí)現(xiàn)原理如下圖所示:

其實(shí)現(xiàn)關(guān)鍵點(diǎn)如下:

  • 如果能明確得知本地事務(wù)成功,則返回COMMIT_MESSAGE
  • 如該不能明確得知本地事務(wù)成功,不能返回ROLLBACK_MESSAGE,而是返回UNKNOW,等待服務(wù)端下一次事務(wù)回查(不會(huì)立即觸發(fā)),服務(wù)端默認(rèn)回查15次,如果15次都得到UNKNOW,則會(huì)回滾該消息。

3.3 代碼獲取

上文只是將事務(wù)消息的核心代碼加以解讀,并重點(diǎn)闡述每個(gè)步驟的實(shí)現(xiàn)關(guān)鍵點(diǎn),筆者基于SpringBoot,嘗試結(jié)合場(chǎng)景學(xué)習(xí)RocketMQ的使用技巧,其代碼上傳到了github倉(cāng)庫(kù)。

https://github.com/dingwpmz/rocketmq-learning

丁威,《RocketMQ技術(shù)內(nèi)幕》作者,RocketMQ社區(qū)優(yōu)秀布道師,主打成體系分享JAVA主流中間件,打造完備的互聯(lián)網(wǎng)架構(gòu)體系,目前涵蓋Java并發(fā)、微服務(wù)、消息、調(diào)度、數(shù)據(jù)異構(gòu)等領(lǐng)域,未來繼續(xù)關(guān)注監(jiān)控、在線診斷等領(lǐng)域。

本文轉(zhuǎn)載自微信公眾號(hào)「中間件興趣圈」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系中間件興趣圈公眾號(hào)。


網(wǎng)站標(biāo)題:事務(wù)消息應(yīng)用場(chǎng)景、實(shí)現(xiàn)原理與項(xiàng)目實(shí)戰(zhàn)
分享路徑:http://www.dlmjj.cn/article/cdjscch.html