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');
    }
相关推荐
不光头强2 分钟前
Java中的异常
java·开发语言
Coding茶水间4 分钟前
基于深度学习的管道缺陷检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
开发语言·人工智能·深度学习·yolo·机器学习
shamalee5 分钟前
MS SQL Server partition by 函数实战二 编排考场人员
java·服务器·开发语言
listhi5208 分钟前
基于MATLAB的汽车电动助力转向系统(EPS)转向特性分析
开发语言·matlab·汽车
C++chaofan15 分钟前
JUC 并发编程:对可见性、有序性与 volatile的理解
java·开发语言·spring·java-ee·juc·synchronized·
csbysj202019 分钟前
Django ORM - 单表实例
开发语言
XiYang-DING20 分钟前
【Java SE】双亲委派模型
java·开发语言
阿阿阿阿里郎23 分钟前
ROS2快速入门--C++基础
开发语言·c++·算法
free-elcmacom25 分钟前
C++<x>new和delete
开发语言·c++·算法
程序喵大人30 分钟前
map的[]运算符,这个看似方便的语法,藏着怎样的魔鬼?
开发语言·c++·map·运算符