基于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 IP地址的绑定的实现
May 08 Redis
浅谈Redis存储数据类型及存取值方法
May 08 Redis
redis实现排行榜功能
May 24 Redis
详解Redis复制原理
Jun 04 Redis
Redis读写分离搭建的完整步骤
Sep 14 Redis
CentOS8.4安装Redis6.2.6的详细过程
Nov 20 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
使用Redis实现点赞取消点赞的详细代码
Mar 20 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
redis 解决库存并发问题实现数量控制
Apr 08 Redis
Redis基本数据类型Zset有序集合常用操作
Jun 01 Redis
Redis批量生成数据的实现
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短网址的生成代码(仿微博短网址)
2014/05/07 PHP
30个php操作redis常用方法代码例子
2014/07/05 PHP
PHP变量赋值、代入给JavaScript中的变量
2015/06/29 PHP
php使用imagecopymerge()函数创建半透明水印
2018/01/25 PHP
Flash+XML滚动新闻代码 无图片 附源码下载
2007/11/22 Javascript
一些相见恨晚的 JavaScript 技巧
2010/04/25 Javascript
JQuery的Pager分页器实现代码
2016/05/03 Javascript
浅谈JavaScript 覆盖原型以及更改原型
2016/08/31 Javascript
将html页面保存成图片,图片写入pdf的实现方法(推荐)
2016/09/17 Javascript
AngularJS动态添加数据并删除的实例
2018/02/27 Javascript
解决vue 项目引入字体图标报错、不显示等问题
2018/09/01 Javascript
图解JS原型和原型链实现原理
2020/09/15 Javascript
如何编写一个 Webpack Loader的实现
2020/10/18 Javascript
vue+springboot+element+vue-resource实现文件上传教程
2020/10/21 Javascript
[04:41]2014DOTA2国际邀请赛 Liquid顺利突围晋级正赛
2014/07/09 DOTA
python处理cookie详解
2014/02/07 Python
在python中实现调用可执行文件.exe的3种方法
2019/07/07 Python
详解python中自定义超时异常的几种方法
2019/07/29 Python
Python 获取指定文件夹下的目录和文件的实现
2019/08/30 Python
python模块和包的应用BASE_PATH使用解析
2019/12/14 Python
浅谈在django中使用filter()(即对QuerySet操作)时踩的坑
2020/03/31 Python
浅谈django channels 路由误导
2020/05/28 Python
详解用 python-docx 创建浮动图片
2021/01/24 Python
Python使用cn2an实现中文数字与阿拉伯数字的相互转换
2021/03/02 Python
泰国汽车、火车和轮渡票预订网站:Bus Online Ticket
2017/09/09 全球购物
网络公司美工设计工作个人的自我评价
2013/11/03 职场文书
十佳班主任事迹材料
2014/01/18 职场文书
《中彩那天》教学反思
2014/02/22 职场文书
跟单业务员岗位职责
2014/03/08 职场文书
摄影专业毕业生求职信
2014/03/13 职场文书
领导参观欢迎词
2015/01/26 职场文书
教师个人年度总结
2015/02/11 职场文书
考生诚信考试承诺书
2015/04/29 职场文书
2015年挂职干部工作总结
2015/05/14 职场文书
工作简报格式范文
2015/07/21 职场文书
为什么中国式养孩子很累?
2019/08/07 职场文书