<?php use Predis\Client; /** * Created by PhpStorm. * User: shichaopeng * Date: 2018/10/20 * Time: 17:44 */ class RateLimiter { private $client; private $name; private $maxCallsPerHour; private $slidingWindow; /** * RateLimiter constructor. * @param $client * @param $name * @param $maxCallsPerHour * @param $slidingWindow */ public function __construct(Client $client, $name, $maxCallsPerHour, $slidingWindow) { $this->client = $client; $this->name = $name; $this->maxCallsPerHour = $maxCallsPerHour; $this->slidingWindow = $slidingWindow; } public function remaining() { $now = microtime(true); $accessToken = md5($this->name); $this->client->multi(); $this->client->zrangebyscore($accessToken, 0, $now - $this->slidingWindow); $this->client->zrange($accessToken, 0, -1); $this->client->zadd($accessToken, $now, $now); $this->client->expire($accessToken, $this->slidingWindow); $result = $this->client->exec(); $timestamps = $result[1]; $remaining = max(0, $this->maxCallsPerHour - count($timestamps)); return $remaining > 0; } // /** // * @param $key // * @param int $limit // * @param int $expire // * @return bool // */ // function rate_limit($key, $limit = 10, $expire = 1) { // $redis = createRedisCli(); // // 获取当前的计数器的值 // $current = $redis->get($key); // // 如果当前计数器的值存在且计数器已经超过限制,返回失败 // if ($current != null && $current >= $limit) { // return false; // } else { // // 获取计数器的存活时间 // $ttl = $redis->ttl($key); // // 开始一个事务 // 命名为op2(操作2) // $redis->multi(Redis::MULTI); // // 将计数器原子加1,若计数器不存在,则创建计数器 // $redis->incr($key); // // 若存活时间小于0,代表计数器之前不存在,是刚刚创建的,则设置一个存活时间 // if ($ttl < 0) { // $redis->expire($key, $expire); // } // // 提交事务 // $redis->exec(); // return true; // } // } }