新增滑动窗口限流

This commit is contained in:
JaguarJack
2020-07-02 17:28:01 +08:00
parent 349f36df21
commit 5e076a6eb7
2 changed files with 71 additions and 1 deletions

View File

@@ -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();

View File

@@ -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;
}
}