繞過條件競爭多次領(lǐng)取優(yōu)惠卷,這種問題出現(xiàn)的原理是:多個線程同時訪問同一個共享代碼、變量、文件等沒有進行鎖操作或者同步操作的場景中。通常的web處理方式是通過單線程線性完成的,如果出現(xiàn)多線程并發(fā)請求的情況,數(shù)據(jù)處理邏輯就可能出現(xiàn)異常。
接口:/api/coupon/receive
修復(fù)建議:
一般是使用mysql的鎖機制、或者使用redis的原子性、單線程特性來解決。
本次修復(fù)采用了限制接口請求頻率的方案來解決,因為我們在遇到這個bug之前已經(jīng)實現(xiàn)了限制接口頻率的功能,另外急于工期,所以臨時這樣解決。最終還是計劃使用redis來從根源解決這個問題。
該問題可延伸出秒殺場景下的庫存超賣、簽到場景下的多次簽到領(lǐng)取獎勵等。大家可以測試排查下相關(guān)場景是否存在該問題。
修復(fù)方法:
1:安裝 composer安裝 topthink/think-throttle 依賴;
composer require topthink/think-throttle
注意:執(zhí)行composer 安裝依賴命令的時候最好先git提交一下代碼,或者備份一下, 因為依稀記得當時安裝這個依賴的時候?qū)е马椖刻峤籫it的時候出現(xiàn)了一個關(guān)于git子模塊的問題,當時排查出來是因為composer更新了一個名為alipaysdk/easysdk的依賴,這個依賴又依賴于xin/container這個,然而這個xin/container依賴文件夾內(nèi)部有.git的文件夾,因為我對git子模塊不太熟悉,所以當時git提交報錯后,我直接將xin/container文件夾內(nèi)的兩個子目錄里的.git刪掉即可。
2:對領(lǐng)取優(yōu)惠券接口使用頻率限制配置(也可以對任意想要限制頻率的接口進行設(shè)置)
說明:
1. 對相關(guān)接口配置\think\middleware\Throttle中間件,1/10表示10秒內(nèi)僅允許一個請求;
2. key中一定要使用到用戶的唯一uid;
3. 另外就是這個中間件一定要放在認證中間件AuthTokenMiddleware后面,否則request中獲取不到用戶的uid信息。