当前位置: 首页 > article >正文

php rides限制访问频率

<?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; // 允许访问
        }
    }
}

使用方法
 

  $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');
    }


http://www.kler.cn/a/383630.html

相关文章:

  • 数据采集之selenium模拟登录
  • ThingsBoard规则链节点:RPC Call Reply节点详解
  • 讲讲分布式与集群的区别?
  • 【C++】C++内存管理(一):new/delete
  • 大模型LLama3!!!Ollama下载、部署和应用(保姆级详细教程)
  • Rancher的安装
  • uniapp学习(010-2 实现抖音小程序上线)
  • 【ChatGPT】如何将ChatGPT的回答与外部数据进行结合
  • ThingsBoard规则链节点:Push to Edge节点详解
  • Yarn介绍 | 组成 | 工作流程
  • GESP4级考试语法知识(算法概论(三))
  • 加密通信的“军备竞赛”:科技的“猫鼠游戏”与永无止境的密码对抗
  • SpringSecurity6+OAuth2.0 从入门到熟练使用
  • 视频自动播放被浏览器阻止及其解决方案
  • 「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
  • 【神经网络加速】神经加速棒
  • Spring中@Autowired@Resource和@Inject注解区别
  • 记录学习react的一些内容
  • 123456789
  • K8S node节点没有相应的pod镜像运行故障处理办法
  • Spring Boot驱动的导师双选系统:设计与实现
  • 现货白银的交易技巧:成功进行趋势跟踪的技巧
  • 双指针算法篇——一快一慢须臾之间解决问题的飘逸与灵动(3)
  • IT专业入门,高考假期预习指南
  • Linux服务管理-DHCP
  • 【STM32】项目实战——OV7725/OV2604摄像头颜色识别检测(开源)