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');
    }
相关推荐
星夜离尘568 小时前
MATLAB 工程实验:不等间隔流量积分,先把缺口与覆盖率说清楚
开发语言·matlab·时间戳·数据质量·数值积分
Ai-_Man9 小时前
Meta Muse还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·c#·1024程序员节
梓豪csd9 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
学逆向的9 小时前
C 枚举变量
c语言·开发语言·网络安全
Sakura_j_h_9 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
李纲明11 小时前
WordPress 后台登录马上被踢回登录页:Cookie 域、HTTPS、盐值和页面缓存怎么查
运维·缓存·https·php·wordpress·cookie
4SAPI11 小时前
AI 数据分析工具大模型 API 选型指南
大数据·人工智能·架构·php·1024程序员节
f89790707012 小时前
php升级之后切换到php8.2.35报pdo错误
php
4SAPI12 小时前
搭建 AI 数据分析工具大模型 API 选型指南
数据库·人工智能·架构·php·1024程序员节
Regentsoft丽晶软件13 小时前
从 “定时拉取“ 到 “事件驱动“,服装库存实时同步的底层架构怎么设计?
经验分享·php·零售