Search by

cjphp / rate-limiter

chenji

php限流器,支持文件/Redis 存储与固定窗口、滑动窗口、漏桶策略

Package info

github.com/ilookcc/rate-limiter

pkg:composer/cjphp/rate-limiter

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2024-05-17 15:25 UTC

This package is auto-updated.

Last update: 2026-10-28 00:18:15 UTC


README

基于 PHP 8.1+ 的限流组件,支持文件 / Redis 存储,以及固定窗口、滑动窗口、漏桶策略。

特性

存储方式

  • 文件存储(单机,目录自动创建)
  • Redis 存储(多机可用,通过分布式锁保证并发安全)

流控策略

  • 固定窗口策略(窗口交界处可能出现接近 2 倍限额的突发,属算法固有特性)
  • 滑动窗口策略
  • 漏桶策略

并发与失败策略

  • 策略判定在存储层互斥锁内执行,避免 read-modify-write 竞态超额放行
  • 抢锁或存储异常时采用失败关闭(fail-closed):视为触发限流,避免绕过

项目结构

rate-limiter/
├── src/
│   ├── RateLimiter.php
│   ├── StorageFactory.php
│   ├── StrategyFactory.php
│   ├── Exception/
│   │   └── RateLimitException.php
│   ├── Storage/
│   │   ├── StorageInterface.php
│   │   ├── FileStorage.php
│   │   └── RedisStorage.php
│   └── Strategy/
│       ├── StrategyInterface.php
│       ├── FixedWindowStrategy.php
│       ├── SlidingWindowStrategy.php
│       └── LeakyBucketStrategy.php
├── tests/
├── composer.json
├── phpunit.xml
└── README.md

安装

composer require cjphp/rate-limiter:~1.0

使用 Redis 存储时需安装 ext-redis(phpredis)。

使用方法

use RateLimiter\RateLimiter;
use RateLimiter\StorageFactory;
use RateLimiter\StrategyFactory;

$key = 'user_123';
$storeType = 'file'; // file | redis
$strategyType = 'fixed_window'; // fixed_window | sliding_window | leaky_bucket

$params = [
    'limit' => 10,      // 窗口内最大请求数(固定/滑动窗口)
    'window' => 60,     // 窗口大小,秒
    'rate' => 1,        // 漏桶:每秒漏出 1 个请求
    'capacity' => 3,    // 漏桶:桶容量 3
];

$ext = match ($storeType) {
    'file' => sys_get_temp_dir() . '/ratelimit',
    'redis' => $redis, // \Redis 已连接实例
};

$storage = StorageFactory::create($storeType, $ext);
$strategy = StrategyFactory::create($strategyType, $storage, $params);
// 注意:RateLimiter 与 Strategy 必须使用同一 $storage 实例
$rateLimiter = new RateLimiter($storage, $strategy);

if ($rateLimiter->isRateLimited($key, false)) {
    echo '不好意思,您被流控了';
} else {
    echo '允许通行';
}

返回值约定

isRateLimited() 返回 true 表示触发限流(拦截),false 表示放行。

全局限流

第二个参数 $isGlobal = true 时,忽略业务 key,所有调用共享同一计数器。

开发与测试

composer install
composer test

注意事项

  1. 未知存储类型 / 策略类型会抛出异常,不再静默降级。
  2. Redis 存储会为状态 key 设置 TTL,降低长期堆积风险。
  3. 滑动窗口会保存窗口内时间戳列表,极高 QPS 场景需评估存储体积。