訂單超時(shí)自動(dòng)取消3種方案—我們用這種!
大家好,我是老三,大家對(duì)電商購(gòu)物應(yīng)該都比較熟悉了,我們應(yīng)該注意到,在下單之后,通常會(huì)有一個(gè)倒計(jì)時(shí),如果超過(guò)支付時(shí)間,訂單就會(huì)被自動(dòng)取消。

下單
今天,我們來(lái)聊聊訂單超時(shí)未支付自動(dòng)取消的幾種方案。
1.定時(shí)任務(wù)
這是最容易想到的辦法,定時(shí)任務(wù)去輪詢(xún)數(shù)據(jù)庫(kù),取消即將超時(shí)的訂單。

訂單輪詢(xún)
定時(shí)任務(wù)實(shí)現(xiàn)方式有很多種,大概可以分為兩類(lèi):本地定時(shí)任務(wù)和分布式定時(shí)任務(wù)。

定時(shí)任務(wù)實(shí)現(xiàn)
本地定時(shí)任務(wù),適用于單機(jī)版的業(yè)務(wù)系統(tǒng),實(shí)現(xiàn)方式非常多樣:
- 永動(dòng)機(jī)線(xiàn)程:開(kāi)啟一個(gè)線(xiàn)程,通過(guò)sleep去完成定時(shí),一些開(kāi)源中間件的某些定時(shí)任務(wù)是通過(guò)這種方式實(shí)現(xiàn)的。
 - JDK Timer:JDK提供了Timer API,也提供了很多周期性的方法。
 - 延遲線(xiàn)程池:JDK還提供了延遲線(xiàn)程池ScheduledExecutorService,API和Timer類(lèi)似。
 - Spring Task:Sprig框架也提供了一些定時(shí)任務(wù)的實(shí)現(xiàn),使用起來(lái)更加簡(jiǎn)單。
 - Quartz:Quartz框架更進(jìn)一步,提供了可以動(dòng)態(tài)配置的線(xiàn)程池。
 
分布式定時(shí)任務(wù):適用于分布式的業(yè)務(wù)系統(tǒng),主要的實(shí)現(xiàn)框架有兩種:
- xxl-job:大眾點(diǎn)評(píng)的許雪里開(kāi)源的,一款基于MySQL的輕量級(jí)分布式定時(shí)任務(wù)框架。
 - elastic-job:當(dāng)當(dāng)開(kāi)發(fā)的彈性分布式任務(wù)調(diào)度系統(tǒng),功能很強(qiáng)大,相對(duì)重一些。
 
定時(shí)任務(wù)實(shí)現(xiàn)的優(yōu)點(diǎn)是開(kāi)發(fā)起來(lái)比較簡(jiǎn)單,但是它也有一些缺點(diǎn):
- 對(duì)數(shù)據(jù)庫(kù)的壓力很大,定時(shí)任務(wù)造成人為的波峰,執(zhí)行的時(shí)刻數(shù)據(jù)庫(kù)的壓力會(huì)陡增
 - 計(jì)時(shí)不準(zhǔn),定時(shí)任務(wù)做不到非常精確的時(shí)間控制,比如半小時(shí)訂單過(guò)期,但是定時(shí)任務(wù)很難卡準(zhǔn)這個(gè)點(diǎn)
 
2.被動(dòng)取消
在文章開(kāi)頭的那個(gè)倒計(jì)時(shí)器,大家覺(jué)得是怎么做的呢?一般是客戶(hù)端計(jì)時(shí)+服務(wù)端檢查。
什么意思呢?就是這個(gè)倒計(jì)時(shí)由客戶(hù)端去做,但是客戶(hù)端定時(shí)去服務(wù)端檢查,修正倒計(jì)時(shí)的時(shí)間。
那么,這個(gè)訂單超時(shí)自動(dòng)取消,也可以由客戶(hù)端去做:
- 用戶(hù)留在收銀臺(tái)的時(shí)候,客戶(hù)端倒計(jì)時(shí)+主動(dòng)查詢(xún)訂單狀態(tài),服務(wù)端每次都去檢查一下訂單是否超時(shí)、剩余時(shí)間
 - 用戶(hù)每次進(jìn)入訂單相關(guān)的頁(yè)面,查詢(xún)訂單的時(shí)候,服務(wù)端也檢查一下訂單是否超時(shí)
 

被動(dòng)取消
這種方式實(shí)現(xiàn)起來(lái)也比較簡(jiǎn)單,但是它也有缺點(diǎn):
- 依賴(lài)客戶(hù)端,如果客戶(hù)端不發(fā)起請(qǐng)求,訂單可能永遠(yuǎn)沒(méi)法過(guò)期,一直占用庫(kù)存
 
當(dāng)然,也可以被動(dòng)取消+定時(shí)任務(wù),通過(guò)定時(shí)任務(wù)去做兜底的操作。
3.延時(shí)消息
第三種方案,就是利用延時(shí)消息了,可以使用RocketMQ、RabbitMQ、Kafka的延時(shí)消息,消息發(fā)送后,有一定延時(shí)才會(huì)投遞。

延時(shí)消息
我們用的就是這種,消息隊(duì)列采用的是RocketMQ,其實(shí)RocketMQ延時(shí)也是利用定時(shí)任務(wù)實(shí)現(xiàn)的。
使用延時(shí)消息的優(yōu)點(diǎn)是比較高效、好擴(kuò)展,缺點(diǎn)是引入了新的技術(shù)組件,增加了復(fù)雜度。
除了上面的三種,其實(shí)還有一些其它的方式,例如本地延遲隊(duì)列、時(shí)間輪算法、Redis過(guò)期監(jiān)聽(tīng)……
但是我覺(jué)得,應(yīng)該不會(huì)有人真考慮過(guò)在生產(chǎn)上使用這些方法。
這里再給大家提個(gè)小問(wèn)題,假如我們接入了一種支付方式,支付的周期非常長(zhǎng),我們需要延長(zhǎng)訂單的有效時(shí)間,這種情況下,大家會(huì)怎么實(shí)現(xiàn)訂單超時(shí)未支付自動(dòng)取消呢?
參考:
[1].Java中定時(shí)任務(wù)的6種實(shí)現(xiàn)方式,你知道幾種?:https://juejin.cn/post/6992719702032121864
[2].訂單超時(shí)未支付自動(dòng)取消8種實(shí)現(xiàn)方案:https://blog.csdn.net/Anenan/article/details/126368753:?















 
 
 
















 
 
 
 