亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何防訂單重復提交策略

發布時間:2020-10-28 14:16:59 來源:億速云 閱讀:148 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關如何防訂單重復提交策略的內容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。

背景

在業務開發中,我們常會面對防止重復請求的問題。當服務端對于請求的響應涉及數據的修改,或狀態的變更時,可能會造成極大的危害。重復請求的后果在交易系統、售后維權,以及支付系統中尤其嚴重。

前臺操作的抖動,快速操作,網絡通信或者后端響應慢,都會增加后端重復處理的概率。前臺操作去抖動和防快速操作的措施,我們首先會想到在前端做一層控制。當前端觸發操作時,或彈出確認界面,或disable入口并倒計時等等,此處不細表。但前端的限制僅能解決少部分問題,且不夠徹底,后端自有的防重復處理措施必不可少,義不容辭。

在接口實現中,我們常要求接口要滿足冪等性,來保證多次重復請求時只有一次有效。

查詢類的接口幾乎總是冪等的,但在包含諸如數據插入,多模塊數據更新時,達到冪等性會比較難,尤其是高并發時的冪等性要求。比如第三方支付前臺回調和后臺回調,第三方支付批量回調,慢性能業務邏輯(如用戶提交退款申請,商家同意退貨/退款等)或慢網絡環境時,是重復處理的高發場景。

嘗試

這里針對“用戶提交退款申請”的例子,說明一下嘗試過的防重復處理方法的效果。后端防重復處理的方式,我們先后嘗試了三種:

(1)基于DB中退款訂單狀態的驗證

這種方式簡單直觀,從DB查詢出來的退款詳情(包括狀態)往往還可以用在后續邏輯中,沒有花額外的工作專門應對重復請求的問題。

這種查詢狀態后進行驗證的邏輯,從代碼上線后就一直存在于所有含狀態的業務邏輯處理中,必不可少。但對于防重復處理效果并不好:在前端添加防重復提交前,每周平均在25筆;前端優化后,每周降到7筆。這個數量占總退款申請數的3%%,一個仍然無法接受的比例。

理論上,任意次請求只要在數據狀態更新之前都完成了查詢操作,則業務邏輯的重復處理就會發生。如下圖所示。優化的方向是減少查詢到更新之間業務處理時間,可降低空檔期的并發影響。極致情況下如果查詢和更新變成了原子操作,則就不存在我們當前的問題。

如何防訂單重復提交策略

(2)基于緩存數據狀態的驗證

Redis存儲查詢輕量快速。在request進來的時候,可以先記錄在緩存中。后續進來的request每次進行驗證。整個流程處理完成,清除緩存。以退款為例子:

  • I. 每次退款發起申請,讀取緩存中是否有以orderId為key的值
  • II. 沒有,則往緩存中寫入以orderId為key的value
  • III.有,則說明有該訂單的退款正在進行。
  • IV. 操作完清緩存,或者緩存存值的時候設置生命周期

與1)的發放相比,數據庫換成響應更快的緩存。但是仍然不是原子操作。插入和讀取緩存還是有時間間隔。在極致的情況下還是存在重復操作的情況。此方法優化后,每周1筆重復操作。

如何防訂單重復提交策略

(3)利用唯一索引機制的驗證

需要原子性操作,想到了數據庫的唯一索引。新建一個TradeLock表:

CREATE TABLE `TradeLock` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`type` int(11) NOT NULL COMMENT '鎖類型',
`lockId` int(11) NOT NULL DEFAULT '0' COMMENT '業務ID',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '鎖狀態',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Trade鎖機制';

● 每次request進來則往表里面插入數據:

成功,則可以繼續操作(相當于獲取鎖);
失敗,則說明有操作在進行。

● 操作完成后,刪除此條記錄。(相當于釋放鎖)。

目前已經上線,等待下周的數據統計。

如何防訂單重復提交策略

(4)基于緩存的計數器驗證

由于數據庫的操作比較消耗性能,了解到redis的計數器也是原子性操作。果斷采用計數器。既可以提高性能,還不用存儲,而且能提升qps的峰值。

還是以訂單退款為例子:

● 每次request進來則新建一個以orderId為key的計數器,然后+1。

如果>1(不能獲得鎖): 說明有操作在進行,刪除。
如果=1(獲得鎖): 可以操作。

● 操作結束(刪除鎖):刪除這個計數器。

要了解計數器,可以參考:http://www.redis.cn/commands/incr.html

如何防訂單重復提交策略

總結:

PHP語言自身沒有提供進程互斥和鎖定機制。因此才有了我們上面的嘗試。網上也有文件鎖機制,但是考慮到我們的分布式部署,建議還是用緩存。在大并發的情況下,程序各種情況的發生。特別是涉及到金額操作,不能有一分一毫的差距。所以在大并發要互斥的情況下可以考慮3、4兩種方案。

愛迪生嘗試了1600多種材料選擇了鎢絲發明了燈泡,實踐出真知。遇到問題,和問題斗爭,最后解決問題是一個最大提升自我的過程,不但加寬自己的知識廣度,更加深了自己的技能深度。達到目標之后的成就感更是不言而喻。

感謝各位的閱讀!關于如何防訂單重復提交策略就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

定南县| 宝兴县| 泽普县| 玉林市| 博野县| 红安县| 栖霞市| 罗江县| 长沙县| 新丰县| 修水县| 休宁县| 达拉特旗| 湘西| 墨江| 应城市| 都昌县| 左云县| 景东| 广德县| 西丰县| 哈密市| 五大连池市| 大庆市| 乐至县| 达尔| 闸北区| 景德镇市| 陆川县| 康马县| 宜兰市| 兴和县| 南召县| 南乐县| 云梦县| 文成县| 黔东| 米林县| 巴东县| 西乌珠穆沁旗| 龙游县|