java掉单_【Java】抄答案就是了,两套详细的设计方案,解决头疼的支付掉单问题...
Hello,大家好,我是樓下小黑哥~
好久沒寫支付相關(guān)的文章了,今天繼續(xù)從事老本行~
上次在文章錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案提到,支付過程會出現(xiàn)掉單、卡單的情況,這種情況對于用戶來講,體驗(yàn)非常差,明明自己付了錢,扣了款,但是訂單卻未成功。
上篇文章我們簡單說了下解決方案,這次小黑哥就結(jié)合生產(chǎn)實(shí)際碰到的情況,給出兩種詳細(xì)設(shè)計(jì)的方案:
定時(shí)輪詢補(bǔ)償方案
延遲消息補(bǔ)償方案
大家可以根據(jù)自己系統(tǒng)的實(shí)際情況,選擇性參考。
當(dāng)然了,以下設(shè)計(jì)方案可能并不完美,如果各位讀者還有其他解決方案,歡迎留言指出,一起討論,一起成長~
定時(shí)輪詢補(bǔ)償方案
整體流程
這個(gè)方案主要采用定時(shí)任務(wù),批量查詢掉單記錄,從而驅(qū)動查詢具體支付支付結(jié)果,然后更新內(nèi)部訂單。
整體方案流程圖如下:
前三步流程沒什么好說的,正常的支付流程,咱們針對后面幾步具體詳細(xì)說下。
第三步調(diào)用支付通道之后,如果支付通道端返回支付受理成功或者支付處理中,我們就需要調(diào)用第四步,將這類訂單插入掉單表。
如果支付直接成功了,那就正常流程返回即可。
第五步,補(bǔ)單應(yīng)用將會定時(shí)查詢數(shù)據(jù)庫,批量查詢掉單記錄。
第六步,補(bǔ)單應(yīng)用使用線程池,多線程異步的方式發(fā)起掉單查詢。
第七步,調(diào)用支付通道支付查詢接口。
重點(diǎn)來了,如果第七步支付結(jié)果查詢?yōu)橐韵聽顟B(tài):
支付結(jié)果為扣款成功
支付結(jié)果為明確失敗
掉單記錄查詢達(dá)到最大次數(shù)
第八步就會刪除掉單記錄。
最后,如果掉單查詢依舊還是處理中,那么經(jīng)過一定的延時(shí)之后,重復(fù)第五步,再次重新掉單補(bǔ)償,直到成功或者查詢到達(dá)最大次數(shù)。
相關(guān)問題
為什么需要新建一張掉單表?不能直接使用支付訂單表,查詢未成功的訂單嗎?
這個(gè)問題,實(shí)際上確實(shí)可以直接使用的支付訂單表,然后批量查詢當(dāng)天未成功的訂單,補(bǔ)單程序發(fā)起支付查詢。
那為什么需要新建一張掉單表?
主要是因?yàn)閿?shù)據(jù)庫查詢效率問題,因?yàn)橹Ц队唵伪砻刻於紩罅坑涗浶略?#xff0c;隨著時(shí)間,這張表記錄將會越來越多,越來越大。
支付記錄越多,批量范圍查詢效率就會變低,查詢速度將會變慢。
所以為了查詢效率,新建一張掉單表。
這張表里僅記錄支付未成功的訂單,所以數(shù)據(jù)量就會很小,那么查詢效率就會很高。
另外,掉單表里的記錄,不會被永久保存,只是臨時(shí)性。當(dāng)支付結(jié)果查詢成功,或者支付結(jié)果明確失敗,再或者查詢次數(shù)到達(dá)規(guī)定最大次數(shù),就會刪除掉單記錄。
這就是第八步為什么需要刪除掉單表的原因。
如果需要保存每次掉單表查詢詳情,那么這里建議再新增一張掉單查詢記錄表,保存每一次的查詢記錄。
針對這個(gè)方案,如果還有其他問題,歡迎留言。
方案優(yōu)缺點(diǎn)
定時(shí)輪詢補(bǔ)償方案,最大的優(yōu)點(diǎn)可能就是系統(tǒng)架構(gòu)方案比較簡單,比較容易實(shí)施。
那么這個(gè)方案的缺點(diǎn)主要在于定時(shí)任務(wù)上。
定時(shí)任務(wù)輪詢方案天然會存在以下不足:
輪詢效率稍低
每次查詢數(shù)據(jù)庫,已經(jīng)被執(zhí)行過記錄,仍然會被掃描(補(bǔ)單程序?qū)鶕?jù)一定策略決定是否發(fā)起支付通道查詢),有重復(fù)計(jì)算的嫌疑
時(shí)效性不夠好,如果每小時(shí)輪詢一次,最差的情況下,時(shí)間誤差會達(dá)到1小時(shí)
如果為了解決時(shí)效性問題,增加定時(shí)任務(wù)查詢效率,那么 1 中查詢效率跟 2 的重復(fù)計(jì)算問題將會更加明顯。
延遲消息補(bǔ)償方案
下面介紹另外一種掉單補(bǔ)償方案,延遲消息補(bǔ)償方案,這個(gè)方案整體流程與定時(shí)任務(wù)方案類似,最大區(qū)別可能在于,從一種拉模式變成一種推模式。
整體方案流程圖如下:
這個(gè)方案主要流程跟定時(shí)方案類似,主要區(qū)別在于第四步,第五步,第八步。
第四步的流程從插入掉單表變更為往延遲隊(duì)列發(fā)送掉單消息。
第五步,補(bǔ)單程序接收掉單消息,然后觸發(fā)支付掉單查詢。
第八步,如果第七步支付結(jié)果查詢?yōu)橐韵聽顟B(tài):
支付結(jié)果為扣款成功
支付結(jié)果為明確失敗
掉單記錄查詢達(dá)到最大次數(shù)
補(bǔ)單程序?qū)嬷舆t隊(duì)列消費(fèi)成功,延遲隊(duì)列將會刪除這條掉單消息。
其他狀態(tài)將會告知消費(fèi)失效,延遲隊(duì)列將會在一定延時(shí)之后,再次發(fā)送掉單消息,然后繼續(xù)重復(fù)第五步。
延遲隊(duì)列
這里的延遲隊(duì)列需要自己實(shí)現(xiàn),復(fù)雜度還是比較高的,這里給大家推薦幾種實(shí)現(xiàn)方案:
第一種,基于 Redis SortedSet 實(shí)現(xiàn)延遲隊(duì)列。可以參考一下有贊的實(shí)現(xiàn)方案https://tech.youzan.com/queuing_delay/
第二種,基于時(shí)間輪算法(TimingWheel)實(shí)現(xiàn)延遲隊(duì)列,具體可以參考 Kafka 延時(shí)隊(duì)列。
第三種,基于 RocketMQ 延遲消息。
前兩種方案說起來還需要再開發(fā),所以還是比較復(fù)雜的。
這里重點(diǎn)說下第三種方案,該方案是 RocketMQ 已經(jīng)支持的特性,開箱即用,使用起來還是比較簡單的。
RocketMQ 延遲消息支持 18 個(gè)等級,分別如下:
1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
消息發(fā)送方可以通過以下方式指定延遲等級,對應(yīng)上方的延遲時(shí)間。
Message#setDelayTimeLevel
消息消費(fèi)方,如果消費(fèi)失敗,默認(rèn)將會在消息發(fā)送方的的延遲等級基礎(chǔ)上加 1。如果消息消費(fèi)方需要指定其他的延遲等級,可以使用如下方式:
ConsumeConcurrentlyContext#setDelayLevelWhenNextConsume
RocketMQ 延遲消息,支持的特性還是比較基礎(chǔ)、簡單,不支持自定義延遲時(shí)間。不過對于掉單補(bǔ)償?shù)倪@個(gè)場景剛好夠用,但是如果需要自定義延遲的,那還是得采用其他的方案。
方案優(yōu)缺點(diǎn)
延遲消息的方案相對于定時(shí)輪詢方案來講:
無需再查詢?nèi)坑唵?#xff0c;效率高
時(shí)效性較好
不過延遲消息這種方案,需要基于延遲隊(duì)列,實(shí)現(xiàn)起來比較復(fù)雜,目前開源實(shí)現(xiàn)也比較少。
小結(jié)
支付掉單、卡單是支付過程中經(jīng)常會碰到的事,我們可以采用異步補(bǔ)償?shù)姆桨?#xff0c;解決該問題。
異步補(bǔ)償方案可以采用如下兩種:
定時(shí)輪詢補(bǔ)償方案
延遲消息補(bǔ)償方案
定時(shí)輪詢補(bǔ)償方案實(shí)現(xiàn)起來比較簡單,但是時(shí)效性稍差。
而延遲消息補(bǔ)償方案總體來說比較優(yōu)秀,但是實(shí)現(xiàn)起來比較復(fù)雜。如果沒有自定義的延遲時(shí)間的需求,可以直接采用 RocketMQ 延遲消息,簡單快捷。
另外延遲隊(duì)列使用場景還是比較多,不僅僅能用在掉單補(bǔ)償上,還可以用于支付關(guān)單等場景。所以有能力開發(fā)的團(tuán)隊(duì),可以開發(fā)一個(gè)通用的延遲隊(duì)列、
好了,今天的文章就到這里了。
我是樓下小黑哥,下篇文章再見,886~
歷史支付文章推薦
錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案
一筆訂單,但是誤付了兩筆錢!這種重復(fù)付款異常到底該如何解決?
收款神器!解讀聚合收款碼背后的原理|原創(chuàng)
手機(jī)沒網(wǎng)了,卻還能支付,這是什么原理?|原創(chuàng)
輕輕一掃,立刻扣款,付款碼背后的原理你不想知道嗎?|原創(chuàng)
支付渠道路由系統(tǒng)進(jìn)化史
從零開始設(shè)計(jì)對賬系統(tǒng)
微信支付寶接入大全
多支付通道路由網(wǎng)關(guān)設(shè)計(jì)
銀行卡支付,背后到底發(fā)生了什么?
總結(jié)
以上是生活随笔為你收集整理的java掉单_【Java】抄答案就是了,两套详细的设计方案,解决头疼的支付掉单问题...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原始人java生存游戏_原始人人生模拟器
- 下一篇: java redis 商品秒杀_redi