【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号