PHP实现令牌桶限流Redis list列表 Lpush rpop 实现令牌桶 - 限流 PHP实例

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: PHP实现令牌桶限流Redis list列表 Lpush rpop 实现令牌桶 - 限流 PHP实例
本文环境 Windows10,PHP7.1,Redis6.0,Yii 2.0\

不懂的可以评论或联系我邮箱:owen@owenzhang.com\

著作权归OwenZhang所有。商业转载请联系OwenZhang获得授权,非商业转载请注明出处。

令牌桶限流介绍

令牌桶算法 (Token Bucket) 和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解。\

随着时间流逝,系统会按恒定 1/QPS 时间间隔 (如果 QPS=100, 则间隔是 10ms) 往桶里加入 Token (想象和漏洞漏水相反,有个水龙头在不断的加水), 如果桶已经满了就不再加了。\

新请求来临时,会各自拿走一个 Token, 如果没有 Token 可拿了就阻塞或者拒绝服务.

* 令牌桶的另外一个好处是可以方便的改变速度。

* 一旦需要提高速率,则按需提高放入桶中的令牌的速率。

* 一般会定时 (比如 1000 毫秒) 往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量.

Redis list lpush rpop 介绍

list

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。


redis 127.0.0.1:6379> lpush keyname owen

(integer) 1

redis 127.0.0.1:6379> lpush keyname zhang

(integer) 2

redis 127.0.0.1:6379> lpush keyname redis

(integer) 3

redis 127.0.0.1:6379> lrange keyname 0 10

​

1) "owen"

2) "zhang"

3) "redis"

**LPUSH** 将三个值插入了名为 **runoobkey** 的列表当中

lpush

lpush 将一个或多个值插入到列表头部。 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。 当 key 存在但不是列表类型时,返回一个错误。


redis 127.0.0.1:6379> lpush keyname value1..

rpop

rpop 移除列表的最后一个元素,返回值为移除的元素。


redis 127.0.0.1:6379> rpop keyname 

令牌桶父类

步骤如下:

  1. 加入令牌

注意:需要加入定时任务,定时增加令牌数量

  1. 获取令牌

  1. 重设令牌桶,填满令牌


<?php

​

namespace common\components;

​

use Yii;

use yii\redis\Connection;

​

/\*\*

 \* 令牌桶 - 限流

 \*

 \* 令牌桶算法 (Token Bucket) 和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解。

 \* 随着时间流逝,系统会按恒定 1/QPS 时间间隔 (如果 QPS=100, 则间隔是 10ms) 往桶里加入 Token (想象和漏洞漏水相反,有个水龙头在不断的加水), 如果桶已经满了就不再加了。

 \* 新请求来临时,会各自拿走一个 Token, 如果没有 Token 可拿了就阻塞或者拒绝服务.

 \*

 \* 令牌桶的另外一个好处是可以方便的改变速度。

 \* 一旦需要提高速率,则按需提高放入桶中的令牌的速率。

 \* 一般会定时 (比如 1000 毫秒) 往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量.

 \*

 \* Class TrafficShape

 \* @package common\components

 \*/

class TrafficShape

{

    /\*\*

     \* 令牌桶

     \*

     \* @var string

     \*/

    public $container;

​

    /\*\*

     \* 最大令牌数

     \*

     \* @var int

     \*/

    public $max;

​

    /\*\*

     \* @var Connection

     \*/

    protected $redis;

​

    /\*\*

     \* TrafficShaper constructor.

     \* @param int $max

     \* @param string $containe

     \*/

    public function \_\_construct($max = 300, $container = 'container')

    {

        $this->redis = Yii::$app->redis;

        $this->max = $max;

        $this->container = $container;

    }

​

    /\*\*

     \* 加入令牌

     \*

     \* 注意:需要加入定时任务,定时增加令牌数量

     \*

     \* @param int $num 加入的令牌数量

     \* @return int 加入的数量

     \*/

    public function add($num = 0)

    {

        // 当前剩余令牌数

        $curnum = intval($this->redis->llen($this->container));

        // 最大令牌数

        $maxnum = intval($this->max);

        // 计算最大可加入的令牌数量,不能超过最大令牌数

        $num = $maxnum >= $curnum + $num ? $num : $maxnum - $curnum;

        // 加入令牌

        if ($num > 0) {

            $token = array\_fill(0, $num, 1);

            $this->redis->lpush($this->container, ...$token);

            return $num;

        }

​

        return 0;

    }

​

    /\*\*

     \* 获取令牌

     \*

     \* @return bool

     \*/

    public function get()

    {

        return $this->redis->rpop($this->container) ? true : false;

    }

​

    /\*\*

     \* 重设令牌桶,填满令牌

     \*/

    public function reset()

    {

        $this->redis->lrem($this->container, 0, $this->max);

        $this->add($this->max);

    }

}

调用实例

步骤如下:

  1. 添加令牌数量

注意:需要加入定时任务,定时增加令牌数量

  1. 验证令牌桶请求过快

一般会定时 (比如 1000 毫秒) 往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量.

添加令牌


/\*\*

     \* 添加令牌数量

     \*/

    public function add()

    {

        // 默认最大添加数量为300

        $trafficShaper = new TrafficShaper(300);

        $trafficShaper->add(50);

    }

请求过快


$trafficShaper = new TrafficShaper();

        if (!$trafficShaper->get()) {

            throw new TooManyRequestsHttpException('请求过快');

        }

Buy me a cup of coffee :)

觉得对你有帮助,就给我打赏吧,谢谢!

Buy me a cup of coffee :)

https://www.owenzhang.com/wechat_reward.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
18天前
|
NoSQL 算法 Java
Java Redis多限流
通过本文的介绍,我们详细讲解了如何在Java中使用Redis实现三种不同的限流策略:固定窗口限流、滑动窗口限流和令牌桶算法。每种限流策略都有其适用的场景和特点,根据具体需求选择合适的限流策略可以有效保护系统资源和提高服务的稳定性。
43 18
|
30天前
|
C语言 Python
[oeasy]python054_python有哪些关键字_keyword_list_列表_reserved_words
本文介绍了Python的关键字列表及其使用规则。通过回顾`hello world`示例,解释了Python中的标识符命名规则,并探讨了关键字如`if`、`for`、`in`等不能作为变量名的原因。最后,通过`import keyword`和`print(keyword.kwlist)`展示了Python的所有关键字,并总结了关键字不能用作标识符的规则。
35 9
|
1月前
|
数据挖掘 大数据 数据处理
python--列表list切分(超详细)
通过这些思维导图和分析说明表,您可以更直观地理解Python列表切分的概念、用法和实际应用。希望本文能帮助您更高效地使用Python进行数据处理和分析。
65 14
|
1月前
|
数据挖掘 大数据 数据处理
python--列表list切分(超详细)
通过这些思维导图和分析说明表,您可以更直观地理解Python列表切分的概念、用法和实际应用。希望本文能帮助您更高效地使用Python进行数据处理和分析。
83 10
|
2月前
|
存储 安全 搜索推荐
hyperf-throttle-requests,一个超牛的 PHP 限流神器
`hyperf-throttle-requests` 是专为 Hyperf 框架设计的请求频率限流库,适用于分布式系统和微服务架构,能有效防止恶意攻击和流量高峰对后端服务的影响。通过限制用户在一定时间内的请求次数,确保服务的稳定性和可用性。该库支持注解、助手函数及直接调用三种使用方式,并提供了灵活的配置选项,如存储驱动、最大请求次数等。最新版已兼容 Hyperf 3.1 版本,安装简便,配置灵活,是保护后端服务的理想选择。
37 3
|
2月前
|
PHP
PHP的pcntl多进程用法实例
PHP使用PCNTL系列的函数也能做到多进程处理一个事务。
39 12
|
2月前
|
索引 Python
List(列表)
List(列表)。
63 4
|
3月前
|
测试技术 开发者 Python
在 Python 中创建列表时,应该写 `[]` 还是 `list()`?
在 Python 中,创建列表有两种方法:使用方括号 `[]` 和调用 `list()` 函数。虽然两者都能创建空列表,但 `[]` 更简洁、高效。性能测试显示,`[]` 的创建速度比 `list()` 快约一倍。此外,`list()` 可以接受一个可迭代对象作为参数并将其转换为列表,而 `[]` 则需要逐一列举元素。综上,`[]` 适合创建空列表,`list()` 适合转换可迭代对象。
在 Python 中创建列表时,应该写 `[]` 还是 `list()`?
|
2月前
|
JavaScript 数据管理 虚拟化
ArkTS List组件基础:掌握列表渲染与动态数据管理
在HarmonyOS应用开发中,ArkTS的List组件是构建动态列表视图的核心。本文深入探讨了List组件的基础,包括数据展示、性能优化和用户交互,以及如何在实际开发中应用这些知识,提升开发效率和应用性能。通过定义数据源、渲染列表项和动态数据管理,结合虚拟化列表和条件渲染等技术,帮助开发者构建高效、响应式的用户界面。
246 2
|
3月前
|
NoSQL 关系型数据库 MySQL
Redis 列表(List)
10月更文挑战第16天
50 2