在一些瞬时可能会有大量并发请求同时到达服务器的场景下,比如抢购、限时活动等等,如果不对并发量进行控制,瞬时的高并发可能会导致系统崩溃,这时我们就需要把一部分请求挡掉,可以结合redis来实现一个基本的限流功能。
function makeOrder(\Redis $redis, $concurrencyKey) {
try {
if ($redis->incr($concurrencyKey) > 500) {
if ($redis->ttl($concurrencyKey) == -1) {
// 请求数超过限制,如果key没有过期时间则加上过期时间
$redis->expire($concurrencyKey, 60);
return false;
}
} else {
// 请求数降下来,则清除key的过期时间
$redis->persist($concurrencyKey);
}
// 处理业务逻辑...
return true;
} finally {
$redis->decr($concurrencyKey);
}
}
这里除了使用redis incr/decr原子计数外,还对计数key增加了过期时间的逻辑,防止incr操作成功,而decr操作失败,导致计数key的基数值越来越大而再无法降下去,最终将没有请求再能够进来,当然加过期时间也存在问题,当并发请求量一直在阈值之上,这时计数key会过期删除,但此时仍积压大量的请求,后来的请求又从新计数,可以把key的过期时间适当延长来降低影响。