php rides限制访问频率

php 复制代码
<?php

class FreqControl
{
    private $redis;
    private $max_freq;

    public function __construct($redis_client, $max_freq)
    {
        $this->redis = $redis_client;
        $this->max_freq = $max_freq;
    }

    public function get_freq($key_name, $time_unit = 'minute')
    {
        // 构建Redis键名
        $redis_key = "{$key_name}:{$time_unit}";

        // 尝试从Redis获取值
        $value = $this->redis->get($redis_key);

        // 如果值不存在或为null,返回0;否则返回转换成整数的值
        return $value !== null ? (int)$value : 0;
    }

    public function increment_freq($key_name, $time_unit = 'minute')
    {
        $key = "{$key_name}:{$time_unit}";
        $pipe = $this->redis->multi();
        $pipe->incr($key);

        if ($time_unit === 'minute') {
            $pipe->expire($key, 60);
        } elseif ($time_unit === 'hour') {
            $pipe->expire($key, 3600);
        }

        return $pipe->exec();
    }

    public function set_freq($key_name, $value, $time_unit = 'minute')
    {
        $key = "{$key_name}:{$time_unit}";
        $ttl = $this->redis->ttl($key);

        // 使用 MULTI/EXEC 块来确保原子性
        $pipe = $this->redis->multi();
        $pipe->set($key, $value);

        // 如果键存在并有TTL,则保留它
        if ($ttl > 0) {
            $pipe->expire($key, $ttl);
        } else {
            // 为新键设置默认的60秒TTL
            $pipe->expire($key, 60);
        }
        return $pipe->exec();
    }

    public function is_freq_exceeded($key_name, $time_unit = 'minute')
    {
        $current_freq = $this->get_freq($key_name, $time_unit);
        $max_freq = (int)($this->max_freq ?? 0);
        return $current_freq >= $max_freq;
    }

    public function control_freq($key_name, $time_unit = 'minute')
    {
        if ($this->is_freq_exceeded($key_name, $time_unit)) {
            return false; // 超过频率限制,不允许访问
        } else {
            $current_freq = $this->get_freq($key_name, $time_unit);
            if (!$current_freq) {
                $this->increment_freq($key_name, $time_unit);
            } else {
                $this->set_freq($key_name, ($current_freq + 1), $time_unit);
            }
            return true; // 允许访问
        }
    }
}

使用方法

php 复制代码
  $redis = new Redis();
    $redis->connect('127.0.0.1');
    // 选择数据库,例如数据库3
    $redis->select(4);
    $max_freq = 130;
    $freqControl = new FreqControl($redis, $max_freq);
    $key_name = $tongjiIp;
    if ($WXAPPOPENID) {
        $key_name = $tongjiIp . '_' . $WXAPPOPENID;
    }
    if ($freqControl->control_freq($key_name) == false) {
        json('请求频繁,请稍后再试', 200, 'error');
    }
相关推荐
小臭希19 分钟前
Java——琐碎知识点一
java·开发语言
淋一遍下雨天1 小时前
Spark Streaming核心编程总结(四)
java·开发语言·数据库
小白学大数据1 小时前
如何避免爬虫因Cookie过期导致登录失效
开发语言·爬虫·python·scrapy
爱吃烤鸡翅的酸菜鱼2 小时前
【SpringMVC】概念引入与连接
java·开发语言·mysql
小白学大数据2 小时前
Python自动化解决滑块验证码的最佳实践
开发语言·python·自动化
碎梦归途2 小时前
23种设计模式-行为型模式之策略模式(Java版本)
java·开发语言·jvm·设计模式·策略模式·行为型模式
Albert Edison2 小时前
Python入门基础
开发语言·python
小余吃大鱼2 小时前
OpenStack私有云详细介绍
开发语言·php·openstack
画个大饼3 小时前
Swift:什么是Optional?其背后的机制是什么?什么是Unconditional Unwrapping?
开发语言·ios·swift
T0uken3 小时前
【Python】Matplotlib:立体永生花绘制
开发语言·python·matplotlib