1. 程式人生 > >抄答案就是了,兩套詳細的設計方案,解決頭疼的支付掉單問題

抄答案就是了,兩套詳細的設計方案,解決頭疼的支付掉單問題

Hello,大家好,我是樓下小黑哥~ 好久沒寫支付相關的文章了,今天繼續從事老本行~ 上次在文章[錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案](https://studyidea.cn/drop-order.html)提到,支付過程會出現**掉單、卡單**的情況,這種情況對於使用者來講,體驗非常差,明明自己付了錢,扣了款,但是訂單卻未成功。 上篇文章我們簡單說了下解決方案,這次小黑哥就結合生產實際碰到的情況,給出兩種詳細設計的方案: - 定時輪詢補償方案 - 延遲訊息補償方案 大家可以根據自己系統的實際情況,選擇性參考。 **當然了,以下設計方案可能並不完美,如果各位讀者還有其他解決方案,歡迎留言指出,一起討論,一起成長~** > 歡迎關注我的公眾號:小黑十一點半,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關注我的部落格:[studyidea.cn](https://studyidea.cn) ## 定時輪詢補償方案 ### 整體流程 這個方案主要採用定時任務,批量查詢掉單記錄,從而驅動查詢具體支付支付結果,然後更新內部訂單。 整體方案流程圖如下: ![定時任務補償](https://img2020.cnblogs.com/other/1419561/202101/1419561-20210107083620714-1094767745.jpg) 前三步流程沒什麼好說的,正常的支付流程,咱們針對後面幾步具體詳細說下。 第三步呼叫支付通道之後,如果支付通道端返回**支付受理成功或者支付處理中**,我們就需要呼叫第四步,將這類訂單插入掉單表。 如果支付直接成功了,那就正常流程返回即可。 > 複習一下,閘道器類支付,比如支付寶、微信支付、網銀支付,這種支付模式,支付通道僅僅返回支付受理成功,具體支付結果需要接收支付通道端的支付通知,這類支付我們將其稱為非同步支付。 > > 相應的還有同步支付,比如銀行卡支付,微信、支付寶代扣類支付,這類支付,同步就能返回支付結果。 第五步,補單應用將會定時查詢資料庫,批量查詢掉單記錄。 第六步,補單應用使用執行緒池,多執行緒非同步的方式發起掉單查詢。 第七步,呼叫支付通道支付查詢介面。 重點來了,如果第七步支付結果查詢為以下狀態: - **支付結果為扣款成功** - **支付結果為明確失敗** - **掉單記錄查詢達到最大次數** **第八步就會刪除掉單記錄。** 最後,如果掉單查詢依舊還是處理中,那麼經過一定的延時之後,重複第五步,再次重新掉單補償,直到成功或者查詢到達最大次數。 ### 相關問題 **為什麼需要新建一張掉單表?不能直接使用支付訂單表,查詢未成功的訂單嗎?** 這個問題,實際上確實可以直接使用的支付訂單表,然後批量查詢當天未成功的訂單,補單程式發起支付查詢。 *那為什麼需要新建一張掉單表?* 主要是因為資料庫查詢效率問題,因為支付訂單表每天都會大量記錄新增,隨著時間,這張表記錄將會越來越多,越來越大。 **支付記錄越多,批量範圍查詢效率就會變低,查詢速度將會變慢。** 所以為了查詢效率,新建一張掉單表。 這張表裡僅記錄支付未成功的訂單,所以資料量就會很小,那麼查詢效率就會很高。 另外,掉單表裡的記錄,不會被永久儲存,只是臨時性。當支付結果查詢成功,或者支付結果明確失敗,再或者查詢次數到達規定最大次數,就會刪除掉單記錄。 **這就是第八步為什麼需要刪除掉單表的原因。** 如果需要儲存每次掉單表查詢詳情,那麼這裡建議再新增一張掉單查詢記錄表,儲存每一次的查詢記錄。 針對這個方案,如果還有其他問題,歡迎留言。 ### 方案優缺點 定時輪詢補償方案,最大的優點可能就是系統架構方案比較簡單,比較容易實施。 那麼這個方案的缺點主要在於**定時任務**上。 定時任務輪詢方案天然會存在以下不足: 1. **輪詢效率稍低** 2. 每次查詢資料庫,已經被執行過記錄,仍然會被掃描(補單程式將會根據一定策略決定是否發起支付通道查詢),有**重複計算**的嫌疑 3. **時效性不夠好**,如果每小時輪詢一次,最差的情況下,時間誤差會達到1小時 4. 如果為了解決時效性問題,增加定時任務查詢效率,那麼 1 中查詢效率跟 2 的重複計算問題將會更加明顯。 ## 延遲訊息補償方案 下面介紹另外一種掉單補償方案,延遲訊息補償方案,這個方案整體流程與定時任務方案類似,最大區別可能在於,從一種**拉模式**變成一種**推模式**。 整體方案流程圖如下: ![](https://img2020.cnblogs.com/other/1419561/202101/1419561-20210107083620916-1904350166.jpg) 這個方案主要流程跟定時方案類似,主要區別在於第四步,第五步,第八步。 第四步的流程從插入掉單表變更為往**延遲佇列傳送掉單訊息**。 第五步,補單程式接收掉單訊息,然後觸發支付掉單查詢。 第八步,如果第七步支付結果查詢為以下狀態: - 支付結果為扣款成功 - 支付結果為明確失敗 - 掉單記錄查詢達到最大次數 補單程式將會告知延遲佇列消費成功,延遲佇列將會刪除這條掉單訊息。 其他狀態將會告知消費失效,延遲佇列將會在一定延時之後,再次傳送掉單訊息,然後繼續重複第五步。 ### 延遲佇列 這裡的延遲佇列需要自己實現,複雜度還是比較高的,這裡給大家推薦幾種實現方案: 第一種,基於 **Redis SortedSet** 實現延遲佇列。可以參考一下有讚的實現方案[https://tech.youzan.com/queuing_delay/](https://tech.youzan.com/queuing_delay/) 第二種,基於時間輪演算法(**TimingWheel**)實現延遲佇列,具體可以參考 Kafka 延時佇列。 第三種,基於 **RocketMQ** 延遲訊息。 前兩種方案說起來還需要再開發,所以還是比較複雜的。 這裡重點說下第三種方案,該方案是 **RocketMQ** 已經支援的特性,開箱即用,使用起來還是比較簡單的。 RocketMQ 延遲訊息支援 18 個等級,分別如下: ```shell 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h ``` 訊息傳送方可以通過以下方式指定延遲等級,對應上方的延遲時間。 ```java Message#setDelayTimeLevel ``` 訊息消費方,如果消費失敗,預設將會在訊息傳送方的的延遲等級基礎上加 1。如果訊息消費方需要指定其他的延遲等級,可以使用如下方式: ```java ConsumeConcurrentlyContext#setDelayLevelWhenNextConsume ``` RocketMQ 延遲訊息,支援的特性還是比較基礎、簡單,不支援自定義延遲時間。不過對於掉單補償的這個場景剛好夠用,但是如果需要自定義延遲的,那還是得采用其他的方案。 ### 方案優缺點 延遲訊息的方案相對於定時輪詢方案來講: - 無需再查詢全部訂單,效率高 - 時效性較好 不過延遲訊息這種方案,需要基於**延遲佇列**,實現起來比較複雜,目前開源實現也比較少。 ## 小結 支付掉單、卡單是支付過程中經常會碰到的事,我們可以採用非同步補償的方案,解決該問題。 非同步補償方案可以採用如下兩種: - 定時輪詢補償方案 - 延遲訊息補償方案 定時輪詢補償方案實現起來比較簡單,但是時效性稍差。 而延遲訊息補償方案總體來說比較優秀,但是實現起來比較複雜。如果沒有自定義的延遲時間的需求,可以直接採用 RocketMQ 延遲訊息,簡單快捷。 另外**延遲佇列**使用場景還是比較多,不僅僅能用在掉單補償上,還可以用於支付關單等場景。所以有能力開發的團隊,可以開發一個通用的延遲佇列、 好了,今天的文章就到這裡了。 我是樓下小黑哥,下篇文章再見,886~ > 歡迎關注我的公眾號:小黑十一點半,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關注我的部落格:[studyidea.cn](https://studyidea.cn) ## 歷史支付文章推薦 1. [錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案](https://studyidea.cn/drop-order.html) 2. [一筆訂單,但是誤付了兩筆錢!這種重複付款異常到底該如何解決?](https://studyidea.cn/repeat-pay-error) 3. [收款神器!解讀聚合收款碼背後的原理|原創](https://studyidea.cn/more-pay) 4. [手機沒網了,卻還能支付,這是什麼原理?|原創](https://studyidea.cn/offline-pay) 5. [輕輕一掃,立刻扣款,付款碼背後的原理你不想知道嗎?|原創](https://studyidea.cn/barcodepay) 6. [支付渠道路由系統進化史](https://studyidea.cn/articles/2019/08/26/1566790579930.html) 6. [從零開始設計對賬系統](https://studyidea.cn/articles/2019/08/26/1566790305561.html) 7. [微信支付寶接入大全](https://studyidea.cn/alipay_wechatpay) 8. [多支付通道路由閘道器設計](https://studyidea.cn/pay-route) 9. [銀行卡支付,背後到底發生了什麼?](https://studyidea.cn/onlinepay-bankCard) > 歡迎關注我的公眾號:小黑十一點半,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關注我的部落格:[studyidea.cn](https://studyi