基于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的几个过期策略
May 27 Redis
redis客户端实现高可用读写分离的方式详解
Jul 04 Redis
Redis入门教程详解
Aug 30 Redis
Jedis操作Redis实现模拟验证码发送功能
Sep 25 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
Redis中有序集合的内部实现方式的详细介绍
Mar 16 Redis
Redis 的查询很快的原因解析及Redis 如何保证查询的高效
Mar 16 Redis
源码分析Redis中 set 和 sorted set 的使用方法
Mar 22 Redis
Redis 操作多个数据库的配置的方法实现
Mar 23 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 Redis
windows安装 redis 6.2.6最新步骤详解
Apr 26 Redis
Redis过期数据是否会被立马删除
Jul 23 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
玩转图像函数库―常见图形操作
2006/09/03 PHP
十天学会php之第一天
2006/10/09 PHP
PHP中获取变量的变量名的一段代码的bug分析
2011/07/07 PHP
PHP7之Mongodb API使用详解
2015/12/26 PHP
PHP浮点比较大小的方法
2016/02/14 PHP
Gird事件机制初级读本
2007/03/10 Javascript
javascript得到当前页的来路即前一页地址的方法
2014/02/18 Javascript
PhotoShop给图片自动添加边框及EXIF信息的JS脚本
2015/02/15 Javascript
javascript中this指向详解
2016/04/23 Javascript
jQuery easyui刷新当前tabs的方法
2016/09/23 Javascript
layer弹出层框架alert与msg详解
2017/03/14 Javascript
使用Bootstrap打造特色进度条效果
2017/05/02 Javascript
Vue入门之animate过渡动画效果
2018/04/08 Javascript
vue.js图片转Base64上传图片并预览的实现方法
2018/08/02 Javascript
puppeteer实现html截图的示例代码
2019/01/10 Javascript
微信实现自动跳转到用其他浏览器打开指定APP下载
2019/02/15 Javascript
javascript网页随机点名实现过程解析
2019/10/15 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
Vue+Element自定义纵向表格表头教程
2020/10/26 Javascript
python函数返回多个值的示例方法
2013/12/04 Python
Python实现一个简单的MySQL类
2015/01/07 Python
numpy实现神经网络反向传播算法的步骤
2019/12/24 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
英国现代市场:ARKET
2019/04/10 全球购物
时尚、社区、科技:SEVENSTORE
2019/04/26 全球购物
港湾网络笔试题
2014/04/19 面试题
大学生自我鉴定
2013/12/08 职场文书
单位在职证明范本
2014/01/09 职场文书
建筑系毕业生自我鉴定
2014/01/24 职场文书
开办大学饮食联盟创业计划书
2014/01/29 职场文书
科研先进个人典型材料
2014/01/31 职场文书
你的创业计划书怎样才能打动风投
2014/02/06 职场文书
腾讯广告词
2014/03/19 职场文书
职业道德模范事迹材料
2014/08/24 职场文书
2014年校务公开工作总结
2014/12/18 职场文书
收费员岗位职责
2015/02/14 职场文书