当前位置:首页 > PHP

php实现令牌桶

2026-02-16 01:44:50PHP

令牌桶算法简介

令牌桶算法是一种常用的流量控制算法,用于限制请求速率。核心思想是系统以固定速率向桶中添加令牌,请求处理需要消耗令牌,桶空时拒绝请求。

PHP实现令牌桶类

class TokenBucket {
    private $capacity;      // 桶容量
    private $tokens;        // 当前令牌数
    private $lastTime;      // 上次更新时间
    private $rate;          // 令牌生成速率(个/秒)

    public function __construct($capacity, $rate) {
        $this->capacity = $capacity;
        $this->rate = $rate;
        $this->tokens = $capacity;
        $this->lastTime = time();
    }

    private function addTokens() {
        $now = time();
        $elapsed = $now - $this->lastTime;
        $newTokens = $elapsed * $this->rate;

        $this->tokens = min($this->capacity, $this->tokens + $newTokens);
        $this->lastTime = $now;
    }

    public function consume($tokens = 1) {
        $this->addTokens();

        if ($this->tokens >= $tokens) {
            $this->tokens -= $tokens;
            return true;
        }
        return false;
    }
}

使用示例

// 创建容量为10,速率1个/秒的令牌桶
$bucket = new TokenBucket(10, 1);

// 模拟请求处理
for ($i = 0; $i < 15; $i++) {
    if ($bucket->consume()) {
        echo "处理请求 $i\n";
    } else {
        echo "拒绝请求 $i (限流)\n";
    }
    sleep(1); // 模拟请求间隔
}

Redis实现分布式令牌桶

对于分布式系统,可使用Redis实现:

class RedisTokenBucket {
    private $redis;
    private $key;
    private $capacity;
    private $rate;

    public function __construct($redis, $key, $capacity, $rate) {
        $this->redis = $redis;
        $this->key = $key;
        $this->capacity = $capacity;
        $this->rate = $rate;
    }

    public function consume($tokens = 1) {
        $script = '
            local key = KEYS[1]
            local capacity = tonumber(ARGV[1])
            local rate = tonumber(ARGV[2])
            local tokens = tonumber(ARGV[3])
            local now = tonumber(ARGV[4])

            local last = redis.call("hget", key, "last")
            local current = redis.call("hget", key, "tokens") or capacity

            if last then
                local elapsed = now - last
                current = math.min(capacity, current + elapsed * rate)
            end

            if current >= tokens then
                current = current - tokens
                redis.call("hmset", key, "tokens", current, "last", now)
                return 1
            end
            return 0
        ';

        return $this->redis->eval($script, [$this->key, $this->capacity, $this->rate, $tokens, time()], 1);
    }
}

性能优化建议

使用时间窗口预生成令牌,避免每次请求都计算 对于高并发场景,建议使用Redis+Lua脚本保证原子性 可结合漏桶算法实现更平滑的流量控制

php实现令牌桶

标签: 令牌php
分享给朋友:

相关文章

php实现递归

php实现递归

递归的基本概念 递归是一种函数调用自身的技术,适用于解决可以分解为相同子问题的问题。在PHP中,递归需要明确的终止条件(基线条件),否则会导致无限循环。 递归实现阶乘 阶乘是经典的递归案例,n! =…

php实现排序

php实现排序

PHP 数组排序方法 PHP 提供了多种内置函数用于数组排序,适用于不同的排序需求。以下是常见的排序方法: 按值升序排序 sort() 函数对数组按值升序排序,重置键名(索引数组适用): $num…

php队列的实现

php队列的实现

PHP队列的实现方式 PHP中实现队列功能可以通过多种方式,根据需求选择适合的方案: 使用数组实现基础队列 PHP数组本身支持队列操作,利用array_push和array_shift函数: $q…

php实现上传图片

php实现上传图片

上传图片的基本流程 PHP 实现图片上传功能需要处理文件接收、验证、保存等步骤。以下是具体实现方法。 创建 HTML 表单 在 HTML 中创建一个表单,设置 enctype="multipart…

php实现即时通讯

php实现即时通讯

PHP 实现即时通讯的方案 即时通讯(IM)可以通过多种方式实现,PHP 作为服务器端语言,通常需要结合前端技术(如 WebSocket、AJAX)或第三方服务来实现实时通信。以下是几种常见的实现方式…

php实现的分页

php实现的分页

PHP 实现分页的方法 基本分页逻辑 分页的核心在于计算总页数、当前页码以及数据偏移量。假设每页显示 10 条数据: $current_page = isset($_GET['page']) ?…