php redis 限流解决方案

<?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;
//        }
//    }

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注