消息隊(duì)列:第四章:延遲檢查隊(duì)列

分布式事務(wù)的異步通信問題

使用分布式事務(wù)異步通信的結(jié)構(gòu),一個(gè)很大的問題就是不確定性。一個(gè)消息發(fā)送過去了,不管結(jié)果如何發(fā)送端都不會(huì)原地等待接收端。直到接收端再推送回來回執(zhí)消息,發(fā)送端才直到結(jié)果。但是也有可能發(fā)送端消息發(fā)送后,石沉大海,杳無(wú)音信。這時(shí)候就需要一種機(jī)制能夠?qū)@種不確定性進(jìn)行補(bǔ)充。

比如你給有很多筆友,平時(shí)寫信一去一回,但是有時(shí)候會(huì)遇到遲遲沒有回信的情況。那么針對(duì)這種偶爾出現(xiàn)的情況,你可以選擇兩種策略。一種方案是你發(fā)信的時(shí)候用定個(gè)鬧鐘,設(shè)定1天以后去問一下對(duì)方收沒收到信。另一種方案就是每天夜里定個(gè)時(shí)間查看一下所有發(fā)過信但是已經(jīng)一天沒收到回復(fù)的信。然后挨個(gè)打個(gè)電話問一下。

第一種策略就是實(shí)現(xiàn)起來就是延遲隊(duì)列,第二種策略就是定時(shí)輪詢掃描。

二者的區(qū)別是延遲隊(duì)列更加精準(zhǔn),但是如果周期太長(zhǎng),任務(wù)留在延遲隊(duì)列中時(shí)間的就會(huì)非常長(zhǎng),會(huì)把隊(duì)列變得冗長(zhǎng)。比如用戶幾天后待辦提醒,生日提醒。

那么如果遇到這種長(zhǎng)周期的事件,而且并不需要精確到分秒級(jí)的事件,可以利用定時(shí)掃描來實(shí)現(xiàn),尤其是比較消耗性能的大范圍掃描,可以安排到夜間執(zhí)行。

 
延遲隊(duì)列
什么是延遲隊(duì)列?

一般的隊(duì)列,消息一旦入隊(duì)了之后就會(huì)被消費(fèi)者馬上消費(fèi)。

延遲隊(duì)列就是進(jìn)入該隊(duì)列的消息會(huì)被延遲消費(fèi)。
可以做什么?

1、延遲消費(fèi)。比如:

    用戶生成訂單之后,需要過一段時(shí)間校驗(yàn)訂單的支付狀態(tài),如果訂單仍未支付則需要及時(shí)地關(guān)閉訂單。
    用戶注冊(cè)成功之后,需要過一段時(shí)間比如一周后校驗(yàn)用戶的使用情況,如果發(fā)現(xiàn)用戶活躍度較低,則發(fā)送郵件或者短信來提醒用戶使用。

2、延遲重試。比如消費(fèi)者從隊(duì)列里消費(fèi)消息時(shí)失敗了,但是想要延遲一段時(shí)間后自動(dòng)重試。

如果不使用延遲隊(duì)列,那么我們只能通過一個(gè)輪詢掃描程序去完成。這種方案既不優(yōu)雅,也不方便做成統(tǒng)一的服務(wù)便于開發(fā)人員使用。但是使用延遲隊(duì)列的話,我們就可以輕而易舉地完成。
 應(yīng)用場(chǎng)景

當(dāng)用戶選擇支付后,通常來說用戶都會(huì)在支付寶正常支付,支付寶轉(zhuǎn)賬成功后,通過后臺(tái)異步發(fā)送成功的請(qǐng)求到電商支付模塊。

但是如果用戶點(diǎn)擊支付后,支付模塊可能會(huì)長(zhǎng)時(shí)間沒有收到支付寶的支付成功通知。這種情況會(huì)‘有兩種可能性,一種是用戶在彈出支付寶付款界面時(shí)沒有繼續(xù)支付,另一種就是用戶支付成功了,但是因?yàn)榫W(wǎng)絡(luò)等各種問題,支付模塊沒有收到通知。

如果是上述第二種可能性,對(duì)于用戶來說體驗(yàn)是非常糟糕的,甚至?xí)岩善脚_(tái)的誠(chéng)信。

所以為了盡可能避免第二種情況,在用戶點(diǎn)擊支付后一段時(shí)間后,不管用戶是否付款,都要去主動(dòng)詢問支付寶,該筆單據(jù)是否付款。

 

圖中紫線部分,就是支付模塊一旦幫助用戶重定向到支付寶后,就要每隔一段時(shí)間詢問支付寶用戶是否支付成功,直到收到支付寶的回復(fù),或者超過了詢問次數(shù)。

 
2  實(shí)現(xiàn)思路

   首先,需要知道如何主動(dòng)查詢支付寶中某筆交易的狀態(tài)。

支付寶查詢接口文檔:https://docs.open.alipay.com/api_1/alipay.trade.query

   其次,利用延遲隊(duì)列反復(fù)調(diào)用。