基于Redis zSet实现滑动窗口对短信进行防刷限流的问题


Posted in Redis onFebruary 12, 2022

前言

  主要针对目前线上短信被脚本恶意盗刷的情况,用Redis实现滑动窗口限流

public void checkCurrentWindowValue(String telNum) {
        
        String windowKey = CommonConstant.getNnSmsWindowKey(telNum);
        //获取当前时间戳
        long currentTime = System.currentTimeMillis();
        //1小时,默认只能发5次,参数smsWindowMax做成可配置项,配置到Nacos配置中心,可以动态调整
        if (RedisUtil.hasKey(windowKey)) {
            //参数smsWindowTime表示限制的窗口时间
            //这里获取当前时间与限制窗口时间之间的短信发送次数
            Optional<Long> optional = Optional.ofNullable(RedisUtil.zCount(windowKey, currentTime - smsWindowTime, currentTime));
            if (optional.isPresent()) {
                long count = optional.get();
                if (count >= smsWindowMax) {
                    log.error("==========>当前号码:{} 短信发送太频繁,{}", telNum, count);
                    throw new ServiceException(MidRetCode.umid_10060);
                }
            }
        }
        StringBuilder sb =new StringBuilder();
        String windowEle = sb.append(telNum).append(":").append(currentTime).toString();
        //添加当前发送元素到zSet中(由于保证元素唯一,这里将元素加上了当前时间戳)
        RedisUtil.zAdd(windowKey, windowEle, currentTime);
        //设置2倍窗口Key:windowKey 的过期时间
        RedisUtil.expire(windowKey, smsWindowTime*2, TimeUnit.MILLISECONDS);
    }

补充:下面看下以php语言为例基于redis实现滑动窗口式的短信发送接口限流

滑动窗口短信发送限流算法

1.有两条规则

基于IP的限制和基于手机号的限制

IP规则:

1分钟限制5

10分钟限制30

1小时限制50

手机号规则:

1分钟限制1

10分钟限制5

1小时限制10

2.滑动窗口就是随着时间的流动 , 进行动态的删减区间内的数据 , 限制时获取区间内的数据

最主要的是用到了redis的zRemRangeByScore来进行删除区间外的数据

<?php
/*滑动窗口短信发送限流算法
1.有两条规则
 基于IP的限制和基于手机号的限制
 IP规则:

 1分钟限制5
 10分钟限制30
 1小时限制50

 手机号规则:
 1分钟限制1
 10分钟限制5
 1小时限制10
*/
//IP规则
$ipRules=array(
    60=>5,
    600=>30,
    3600=>50
);
//手机号规则
$phoneRules=array(
    60=>1,
    600=>5,
    3600=>10
);

$r = checkLimits($ipRules,$_SERVER["REMOTE_ADDR"],$_GET['tel']);
var_dump($r);

$r = checkLimits($phoneRules,$_GET['tel'],$_GET['tel']);
var_dump($r);

function checkLimits($rules,$key,$tel){
    $redis = new Redis();
    $redis->connect('115.159.28.111', 1991);
    foreach($rules as $ruleTime=>$rule) {
        $redisKey=$key."_".$ruleTime;
        $score=time();
        $member=$tel.'_'.$score;
        $redis->multi();
        $redis->zRemRangeByScore($redisKey, 0, $score - $ruleTime);//移除窗口以外的数据
        $redis->zAdd($redisKey, $score, $member);
        $redis->expire($redisKey, $ruleTime);
        $redis->zRange($redisKey, 0, -1, true);
        $members = $redis->exec();
        if (empty($members[3])) {
            break;
        }
        $nums=count($members[3]);
        var_dump($nums);

        if($nums>$rule){
            return false;
        }
    }
    return true;
}

到此这篇关于基于Redis zSet实现滑动窗口对短信进行防刷限流的文章就介绍到这了,更多相关Redis zSet滑动窗口限流内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
redis连接被拒绝的解决方案
Apr 12 Redis
Django使用redis配置缓存的方法
Jun 01 Redis
比较几种Redis集群方案
Jun 21 Redis
你真的了解redis为什么要提供pipeline功能
Jun 22 Redis
Redis入门教程详解
Aug 30 Redis
使用redis生成唯一编号及原理示例详解
Sep 15 Redis
Window server中安装Redis的超详细教程
Nov 17 Redis
解决linux下redis数据库overcommit_memory问题
Feb 24 Redis
Redis之RedisTemplate配置方式(序列和反序列化)
Mar 13 Redis
Redis安装使用RedisJSON模块的方法
Mar 23 Redis
解决 redis 无法远程连接
May 15 Redis
Redis keys命令的具体使用
Jun 05 Redis
聊聊redis-dump工具安装问题
Jan 18 #Redis
redis的list数据类型相关命令介绍及使用
Jan 18 #Redis
关于使用Redisson订阅数问题
Jan 18 #Redis
Redis中缓存穿透/击穿/雪崩问题和解决方法
linux下安装redis图文详细步骤
Springboot/Springcloud项目集成redis进行存取的过程解析
使用RedisTemplat实现简单的分布式锁
Nov 20 #Redis
You might like
PHP setcookie指定domain参数后,在IE下设置cookie失效的解决方法
2011/09/09 PHP
PHP遍历某个目录下的所有文件和子文件夹的实现代码
2013/06/28 PHP
基于laravel制作APP接口(API)
2016/03/15 PHP
24条货真价实的PHP代码优化技巧
2016/07/28 PHP
PHP实现的简单排列组合算法应用示例
2017/06/20 PHP
Nigma vs Alliance BO5 第三场2.14
2021/03/10 DOTA
Javascript客户端将指定区域导出到Word、Excel的代码
2008/10/22 Javascript
jquery异步循环获取功能实现代码
2010/09/19 Javascript
利用js 进行输入框自动匹配字符的小例子
2013/06/29 Javascript
常用的JavaScript模板引擎介绍
2015/02/28 Javascript
使用AOP改善javascript代码
2015/05/01 Javascript
Javascript实现div层渐隐效果的方法
2015/05/30 Javascript
功能强大的Bootstrap效果展示(二)
2016/08/03 Javascript
详解Node.js如何开发命令行工具
2016/08/14 Javascript
codeMirror插件使用讲解
2017/01/16 Javascript
angularjs实现上拉加载和下拉刷新数据功能
2017/06/12 Javascript
详解Angular2 之 结构型指令
2017/06/21 Javascript
基于jQuery的表单填充实例
2017/08/22 jQuery
ES6解构赋值的功能与用途实例分析
2017/10/31 Javascript
js生成word中图片处理方法
2018/01/06 Javascript
JavaScript常用数学函数用法示例
2018/05/14 Javascript
JavaScript原型对象、构造函数和实例对象功能与用法详解
2018/08/04 Javascript
微信小程序支付PHP代码
2018/08/23 Javascript
为什么要使用Vuex的介绍
2019/01/19 Javascript
浅谈用VSCode写python的正确姿势
2017/12/16 Python
python 利用pyttsx3文字转语音过程详解
2019/09/25 Python
python中p-value的实现方式
2019/12/16 Python
Python Request类源码实现方法及原理解析
2020/08/17 Python
解决import tensorflow导致jupyter内核死亡的问题
2021/02/06 Python
比利时香水网上商店:NOTINO
2018/03/28 全球购物
24岁生日感言
2014/01/13 职场文书
中文专业毕业生自荐信
2014/05/24 职场文书
学雷锋活动总结报告
2014/06/26 职场文书
承诺书样本
2014/08/30 职场文书
成本会计实训报告
2014/11/05 职场文书
十大公认最好看的动漫:《咒术回战》在榜,《钢之炼金术师》第一
2022/03/18 日漫