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