新增滑动窗口限流
This commit is contained in:
@@ -14,9 +14,18 @@ use think\facade\Cache;
|
||||
|
||||
trait Redis
|
||||
{
|
||||
/**
|
||||
* @var \Redis
|
||||
*/
|
||||
protected $redis = null;
|
||||
|
||||
protected function getRedis()
|
||||
/**
|
||||
* 返回 redis
|
||||
*
|
||||
* @time 2020年07月02日
|
||||
* @return \Redis
|
||||
*/
|
||||
protected function getRedis(): \Redis
|
||||
{
|
||||
if (!$this->redis) {
|
||||
$this->redis = Cache::store('redis')->handler();
|
||||
|
@@ -8,3 +8,64 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: JaguarJack [ njphper@gmail.com ]
|
||||
// +----------------------------------------------------------------------
|
||||
namespace catcher\library\rate;
|
||||
|
||||
use catcher\exceptions\FailedException;
|
||||
|
||||
/**
|
||||
* 滑动窗口
|
||||
*
|
||||
* Class SlidingWindowLimit
|
||||
* @package catcher\library\rate
|
||||
*/
|
||||
class SlidingWindowLimit
|
||||
{
|
||||
use Redis;
|
||||
|
||||
protected $key;
|
||||
|
||||
protected $limit = 10;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $window = 5;
|
||||
|
||||
public function __construct($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
|
||||
public function overflow()
|
||||
{
|
||||
$now = microtime(true) * 1000;
|
||||
|
||||
$redis = $this->getRedis();
|
||||
// 开启管道
|
||||
$redis->pipeline();
|
||||
// 去除非窗口内的元素
|
||||
$redis->zremrangeByScore($this->key, 0, $now - $this->window*1000);
|
||||
// 获取集合内的所有元素数目
|
||||
$redis->zcard($this->key);
|
||||
// 增加元素
|
||||
$redis->zadd($this->key, $now, $now);
|
||||
// 设置过期
|
||||
$redis->expire($this->key, $this->window);
|
||||
// 执行管道内命令
|
||||
$res = $redis->exec();
|
||||
|
||||
if ($res[1] > $this->limit) {
|
||||
throw new FailedException('访问限制');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setWindow($time)
|
||||
{
|
||||
$this->window = $time;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user