catchAdmin/extend/catcher/library/rate/SlidingWindowLimit.php

73 lines
1.8 KiB
PHP
Raw Normal View History

2020-07-01 15:24:42 +08:00
<?php
2020-11-29 09:29:14 +08:00
declare(strict_types=1);
2020-07-01 15:24:42 +08:00
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
2020-07-02 17:28:01 +08:00
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;
}
}