1.常用的限流思路令牌桶算法和漏桶算法
直接令牌桶算法代码
<?php
class TokenBucket{
private $_config; //redis设定
private $_redis; //redis对象
private $_queue; //令牌桶
private $_max; //最大令牌数
/**
* 创建redis连接
* @return Redis
*/
private function connect()
{
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$redis->select($this->_config['index']);//用于切换到指定的数据库,数据库索引号 index 用数字值指定,以 0 作为起始索引值。
return $redis;
}
public function __construct($config ,$queue,$max)
{
$this->_config = $config;
$this->_queue = $queue;
$this->_max = $max;
$this->_redis = $this->connect();
}
/**
*获取令牌
*/
public function get()
{
return $this->_redis->rPop($this->_queue)?true:false;
}
/**
* 添加令牌
* @param int $num
* @return int
*/
public function add($num =0)
{
$currNum = $this->_redis->lSize($this->_queue);
$maxNum = $this->_max;
$num = $maxNum >$currNum+$num?$num:$maxNum-$currNum;
if ($num >0){
$token = array_fill(0,$num,1);
$this->_redis->lPush($this->_queue,...$token);
return $num;
}
return 0;
}
/**
* 重新设置了令牌桶,填满令牌
*/
public function reset()
{
$this->_redis->delete($this->_queue);
$this->add($this->_max);
}
}
// redis连接设定
$config = array(
'host' => 'localhost',
'port' => 6379,
'index' => 0,
'auth' => '',
'timeout' => 1,
'reserved' => NULL,
'retry_interval' => 100,
);
$queue = "mycontainer";
$max = 5;
$tokenBucket = new TokenBucket($config,$queue,$max);
$tokenBucket->reset();
// 循环获取令牌,令牌桶内只有5个令牌,因此最后3次获取失败
for($i=0; $i<8; $i++){
var_dump($tokenBucket->get());
}
// 加入10个令牌,最大令牌为5,因此只能加入5个
$add_num = $tokenBucket->add(10);
var_dump($add_num);
// 循环获取令牌,令牌桶内只有5个令牌,因此最后1次获取失败
for($i=0; $i<6; $i++){
var_dump($tokenBucket->get());
}