滑动窗口实现访问频率限制

滑动窗口实现访问频率限制

  • 使用redis的有序集合实现滑动窗口,从而实现对访问频率的限制
    • 思路一
    • 思路二

使用redis的有序集合实现滑动窗口,从而实现对访问频率的限制

主要思路有两个

思路一

  1. 以时间戳为有序集合的成员
  2. 每次请求,先使用ZREMRANGEBYLEX命令移除窗口外的成员
  3. 使用ZRANGE命令获取有序集合的成员和相应权重
  4. 使用ZINCRBY命令对相应的成员的权重加一
  5. 使用EXPIRE命令重新设置有序集合有效期
  6. 对获取到的有序集合的成员的权重求和,并判断是否超过阈值

PHP实现

$maximum = 10; // 最大请求数量
$slidingWindow = 10; // 滑动窗口大小(s)

$now = time();
$redisKeyMod = 'pre:sliding_window:sorted_sets:%s';
$redisKey = sprintf($redisKeyMod, 'test.com');// 全站窗口
//$redisKey = sprintf($redisKeyMod, '/api/test/info');// 某个接口窗口
//$redisKey = sprintf($redisKeyMod, '{access-token}');// 某个access-token窗口

$redis = new Redis();
$redis->connect('192.168.10.5', 6379);
$redis->auth('rc_redis');

$redis->multi();
$redis->zRemRangeByLex($redisKey, '[0', '[' . ($now-$slidingWindow)); // 移除窗口外的数据
$redis->zrange($redisKey, 0, -1, true); // 获取窗口权重数据
$redis->zincrby($redisKey, 1, $now); // 增加权重
$redis->expire($redisKey, $slidingWindow);
$res = $redis->exec();

if (array_sum($res[1]) > $maximum) {
    echo '超频', PHP_EOL;
}

思路二

  1. 以时间戳为有序集合的成员
  2. 每次请求,先使用ZREVRANGEBYSCORE命令移除窗口外的成员
  3. 使用ZRANGE命令获取有序集合的成员
  4. 使用zAdd命令给有序集合增加成员
  5. 使用EXPIRE命令重新设置有序集合有效期
  6. 计算获取到的成员数量,并判断是否超过阈值

PHP实现

$maximum = 10; // 最大请求数量
$slidingWindow = 10; // 滑动窗口大小(s)

$now = microtime(true);
$redisKeyMod = 'pre:sliding_window:sorted_sets:%s';
$redisKey = sprintf($redisKeyMod, 'test.com');// 全站窗口
//$redisKey = sprintf($redisKeyMod, '/api/test/info');// 某个接口窗口
//$redisKey = sprintf($redisKeyMod, '{access-token}');// 某个access-token窗口

$redis = new Redis();
$redis->connect('192.168.10.5', 6379);
$redis->auth('rc_redis');

$redis->multi();
$redis->zRemRangeByScore($redisKey, 0, $now-$slidingWindow); // 移除窗口外的数据
$redis->zrange($redisKey, 0, -1); // 获取窗口数据
$redis->zAdd($redisKey, $now, $now);
$redis->expire($redisKey, $slidingWindow);
$res = $redis->exec();

if (count($res[1]) > $maximum) {
    echo '超频', PHP_EOL;
}

你可能感兴趣的:(php,redis)