详解php基于redis的list型数据结构实现ip限流操作

在日常的业务功能开发中,如果要 限制任意一个ip在连续的某一段时间内,只能访问某个接口一定的次数,需要如何实现呢?
这种功能需求通常是用来应对防止脚本恶意刷接口的情况,目前网上已经有很多比较完善的限流方案。对于一般的站点来讲,可以借助redis的链表型数据结构来实现ip限流功能。
举个例子——
假如我们需要实现,对于接口A,限制任意IP在每一段连续的5秒内,最多允许3次访问,超过3次则返回报错。
file
对于上图来讲,在08秒的时候,最近的5秒内已经发起了4次请求,已经达到最大次数限制,所以此时访问会受限。
采用PHP来实现的话,具体的逻辑代码如下——

/**
* 检查队列的长度是否到达设定的阈值,已到达则返回false,未到达则将当前时间戳推入队列最末端,同时刷新队列整体的缓存时间
* @param $key 队列缓存的key
* @param $expire 队列缓存过期时间,例如上面例子中的5秒
* @param $limit 队列长度阈值,如上面例子中的3次
* @return bool
*/public function checkLimit($key, $expire, $limit){
    $length = $this->refreshList($key, $expire);
    if ($length < $limit) {
        // 未到达访问限制,将当前时间戳推入到list的最后边,同时把整个key的过期时间重新更新
        $this->rPush($key, time());
        $this->expire($key, intval($limit));
        return true;
    }
    return false;}/** 
* 刷新队列,过滤掉已经不在有效时间内的值,返回最新队列的长度
* @param $key string 自定义的缓存key
* @param $expire 队列缓存过期时间,例如上面例子中的5秒
* @return bool|int
*/public function refreshList ($key, $expire)   
 {
        if ($this->has($key)) {
            do { // 对于已存在数据的list,要先从前往后把已经过期的数据弹出
                $oldest_value = $this->lPop($key);
            } while ($oldest_value && time() - $oldest_value > $expire);
            // 把最后弹出的数据重新塞回list的最前边
            $oldest_value && $this->lPush($key, $oldest_value);
            return $this->lLen($key);
        }
        return 0;}

其中用到的lPop,lPush,lLen,rPush等方法,都是封装了redis拓展之后,操作链表型数据结构的一些方法,参数跟返回值都与原生方法保持一致。
其实后来网上查了之后才知道,redis处理这种场景,更多的是直接用zset这种有序集来实现,逻辑也是基本一致,就是存当前时间戳,然后用滑动窗口的算法思想,判断当前窗口内的值长度是否已经超过限制。

关于详解php基于redis的list型数据结构实现ip限流操作的文章就分享到这,如果对你有帮助欢迎继续关注我们哦

本文来自投稿,不代表重蔚自留地立场,如若转载,请注明出处https://www.cwhello.com/44713.html

如有侵犯您的合法权益请发邮件951076433@qq.com联系删除

(0)
php学习php学习订阅用户
上一篇 2022年6月27日 00:31
下一篇 2022年6月27日 00:31

相关推荐

  • PHP调用鼎信短信接口实现批量短信发送。

    随着科技的发展和人们的生活水平的不断提高,短信已经成为人们生活、工作中必不可少的的一种沟通方式。无论是商家推广活动,还是企业员工相互之间的通讯,都不可避免地需要用到短信。所以,如何使用短信接口来实现…

    2023年5月23日
    01
  • 详解PHP中的输出缓冲控制(Output Control)

    本篇文章带大家了解一下PHP中的输出缓冲控制(Output Control) 。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。在 PHP 中,我们直接进行 echo 、 或者 print_r 的时候,输出的内容就会直接打印…

    2023年3月29日
    00
  • 关于php preg_replace_callback回调函数传参问题

    preg_replace_callback这个函数的作用是执行一个正则表达式搜索并且使用一个回调进行替换preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]…

    2022年6月25日
    0129
  • PHP析构函数的小结

    析构函数的最佳实践 我们使用析构函数完成对资源的及时释放   说明 (1)   关于在析构函数中释放资源的问题,如果我们对效率没有很高很特殊的要求,完全可以不使用析构函数. (2)   如果我们不确定代码后面是否…

    2018年4月13日 PHP自学教程
    0188
  • 浅谈PHP中的装饰器模式

    装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。本篇文章带大家了解PHP中的装饰器模式,介绍一下装饰器的好处以及最适用于的场景。工厂模式告一段落,我们来研究其他一些模式。不知道各位大佬有…

    2023年3月29日
    00
  • Redis在PHP应用中的正则表达式操作。

    Redis是一个高性能的key-value存储系统,它支持多种数据结构,其中包括字符串、哈希表、列表、集合、有序集合等。同时,Redis也支持对字符串数据进行正则表达式的匹配和替换操作,这使得它在开发PHP应用中具有很大…

    2023年5月21日
    00
  • 详解PHP位运算符

    位运算符位运算符是指对二进制位从低位到高位对齐后进行运算。符号作用举例个人理解&按位与$m & $n全1为1,否则为0|按位或$m | $n全0为0,有1为1^按位异或$m | $n不同为1,相同为0~按位取反~$m<<向左…

    2022年6月27日
    097
  • 学习php简单实现短网址(短链)还原的方法

    本文实例讲述了php简单实现短网址还原的方法。分享给大家供大家参考,具体如下:具体代码如下:<?php $info1 = '亲!暂不能解析此类短网址。'; $info2 = '亲!网址解析失败,请重试。'; $in…

    2022年6月16日
    0158

联系我们

QQ:951076433

在线咨询:点击这里给我发消息邮件:951076433@qq.com工作时间:周一至周五,9:30-18:30,节假日休息