背景
最近公司出了一起故障,问题代码如下:
/**
* TRUE: 触发限流,FALSE:未触发限流
*/
public function acquire() {
try {
$redisHandler = $this->redisInstance->getHandler();
$redisHandler->set($this->rateLimitKey, $this->tokenNum, ['nx', 'ex' => $this->expireTime]);
$leftTokenNum = $redisHandler->decr($this->rateLimitKey);
if ($leftTokenNum < 0) {
return TRUE;
}
return FALSE;
} catch (\Exception $e) {
return FALSE;
}
}
作者的目的是针对爆款商品的购买,使用 redis 来起到一个限流的作用,1 秒钟只允许 1 人购买。
结果上线过后不久,运营就反馈线上出故障了,该爆款商品所有人都不能购买了。
分析
上面代码的思路很简单:通过 $redis->set('key', '1', ['nx', 'ex'=>1]); 命令,设置值为 1 过期时间为 1 秒的计数器,基于该计数器的