【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

如果有侵权请联系删除

令牌桶算法
  1. 首先设有一个令牌桶,桶内存放令牌,一开始令牌桶内的令牌是满的(桶内令牌的数量可根据服务器情况设定)

  2. 每次访问从桶内取走一个令牌,当桶内令牌为0,则不允许再访问。

  3. 每隔一段时间,放入令牌,最多使桶内令牌满额。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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;
    }
}

  

 

posted @   蓝色星辰1993  阅读(409)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示