【PHP】php 基于redis使用令牌桶算法实现流量控制
整理自:
https://www.cnblogs.com/itbsl/p/13407489.html
https://www.cnblogs.com/myJuly/p/13608475.html
https://mp.weixin.qq.com/s/JQYWVL2YUKLiVZfV99z4cg
如果有侵权请联系删除
令牌桶算法
-
首先设有一个令牌桶,桶内存放令牌,一开始令牌桶内的令牌是满的(桶内令牌的数量可根据服务器情况设定)
-
每次访问从桶内取走一个令牌,当桶内令牌为0,则不允许再访问。
-
每隔一段时间,放入令牌,最多使桶内令牌满额。
class TrafficShaperController extends Controller
{
/**
* 令牌桶总数量
* @var int
*/
private $totleNum = 25;
/**
* 令牌标识(可以根据需要加上关键ID,uid、orderid...)
* @var string
*/
private $quekueName ="TrafficShaper_queue";
/**
* redis缓存类
* @var object
*/
private $redis;
/**
* 初始化方法
*
* @author heyw<1051834593@qq.com>
* @since 2020/12/10
*/
public function _initialize()
{
$this->redis = Redis::getInstance();
}
/**
* 模拟用户消耗令牌
*
* @param int $num
* @author heyw<1051834593@qq.com>
* @since 2020/12/10
*/
public function run($num = 1)
{
// 初始化
$this->reset();
// 模拟1s请求10次
while (1) {
$this->getKey();
sleep(0.1);
}
}
/**
* 获取令牌
*
* @return bool
* @author heyw<1051834593@qq.com>
* @since 2020/12/11
*/
protected function getKey()
{
// 初始化
$redis = $this->redis;
$queueName = $this->quekueName;
// 获取一个令牌,如果没有直接返回
$res = $redis->rPop($queueName);
// 获得令牌,处理业务
var_dump($res ?'get it' : 'empty');
return true;
}
/**
* 重置
*
* @author heyw<1051834593@qq.com>
* @since 2020/12/11
*/
protected function reset()
{
$this->redis->delete($this->quekueName);
$this->add(25);
}
/**
* 定时加入令牌桶,1s执行1次
*
* @author heyw<1051834593@qq.com>
* @since 2020/12/10
*/
public function add($stepNum = 5)
{
// 初始化
$redis = $this->redis;
$queueName = $this->quekueName;
// 当前令牌书
$currNum = $redis->lSize($queueName) ?: 0;
$maxNum = $this->totleNum;
$addNum = $maxNum >= $currNum + $stepNum ? $stepNum : $maxNum - $currNum;
if ($addNum == 0) {
return true;
}
// 加入令牌
$token = array_fill(0, $addNum, 1);
$redis->lPush($queueName, $token);
return true;
}
}
得意时做事,失意时读书

浙公网安备 33010602011771号