在給客戶做二開的時(shí)候增加了一個(gè)抽獎(jiǎng)?lì)愋?,最后客戶發(fā)現(xiàn)如果頻繁點(diǎn)擊理解請(qǐng)求會(huì)出現(xiàn)多次請(qǐng)求的實(shí)際返回一個(gè)的中獎(jiǎng)信息問題,經(jīng)過排查測(cè)試發(fā)現(xiàn)原本程序的積分抽獎(jiǎng)功能也存在,然后做了一下優(yōu)化,增加了一個(gè)鎖進(jìn)行限制,然后發(fā)現(xiàn)解決問題了。
解決方法:
1.修改app/services/activity/lottery/LuckLotteryServices.php 文件中的 public function luckLottery(int $uid, int $lottery_id) 方法代碼,增加如下代碼:
// 使用更嚴(yán)格的鎖機(jī)制
$lockKey = 'lottery_lock_' . $uid . '_' . $lottery_id;
$cache = CacheService::redisHandler();
// 增加日志,記錄請(qǐng)求信息
Log::info('開始抽獎(jiǎng),檢查鎖', [
'uid' => $uid,
'lottery_id' => $lottery_id,
'lockKey' => $lockKey,
'exists' => $cache->get($lockKey),
'time' => date('Y-m-d H:i:s'),
'request_id' => uniqid()
]);
// 先嘗試設(shè)置鎖
$isLocked = $cache->setnx($lockKey, 1);
// 如果設(shè)置失敗,說明鎖已存在
if (!$isLocked) {
Log::info('抽獎(jiǎng)鎖已存在,禁止重復(fù)抽獎(jiǎng)', [
'uid' => $uid,
'lottery_id' => $lottery_id,
'time' => date('Y-m-d H:i:s'),
'request_id' => uniqid()
]);
throw new ValidateException('抽獎(jiǎng)處理中,請(qǐng)勿重復(fù)點(diǎn)擊');
}
// 設(shè)置成功后設(shè)置過期時(shí)間
$cache->expire($lockKey, 120);
try {
} catch (\Exception $e) {
$cache->delete($lockKey);
throw $e;
} finally {
// 釋放鎖前記錄日志
Log::info('抽獎(jiǎng)完成,釋放鎖', [
'uid' => $uid,
'lottery_id' => $lottery_id,
'exists' => $cache->get($lockKey),
'time' => date('Y-m-d H:i:s'),
'request_id' => uniqid()
]);
$cache->delete($lockKey);
}
自己看這截圖 及代碼 自己修改,當(dāng)然我不確定其他版本有這個(gè)問題,我這邊客戶使用的是3.0.1版本。
修改完以后記得重啟swoole,并且代碼如果正常生效會(huì)輸出出來響應(yīng)的日志如:
[2024-12-12T15:41:28+08:00][info] 開始抽獎(jiǎng),檢查鎖
[2024-12-12T15:41:28+08:00][info] 抽獎(jiǎng)鎖已存在,禁止重復(fù)抽獎(jiǎng)
[2024-12-12T15:41:32+08:00][info] 開始抽獎(jiǎng),檢查鎖
[2024-12-12T15:41:32+08:00][info] 抽獎(jiǎng)鎖已存在,禁止重復(fù)抽獎(jiǎng)
[2024-12-12T15:41:37+08:00][info] 開始抽獎(jiǎng),檢查鎖
[2024-12-12T15:41:37+08:00][info] 抽獎(jiǎng)鎖已存在,禁止重復(fù)抽獎(jiǎng)
[2024-12-12T15:42:11+08:00][info] 開始抽獎(jiǎng),檢查鎖
[2024-12-12T15:42:11+08:00][info] 抽獎(jiǎng)鎖已存在,禁止重復(fù)抽獎(jiǎng)
[2024-12-12T15:45:39+08:00][info] 開始抽獎(jiǎng),檢查鎖
[2024-12-12T15:45:39+08:00][info] 抽獎(jiǎng)完成,釋放鎖