基于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 20 Redis
redis哨兵常用命令和监控示例详解
May 27 Redis
redis客户端实现高可用读写分离的方式详解
Jul 04 Redis
使用redis实现延迟通知功能(Redis过期键通知)
Sep 04 Redis
详解Redis在SpringBoot工程中的综合应用
Oct 16 Redis
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
Feb 12 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
分布式架构Redis中有哪些数据结构及底层实现原理
Mar 13 Redis
sentinel支持的redis高可用集群配置详解
Apr 01 Redis
一文搞懂Redis中String数据类型
Apr 03 Redis
Redis基本数据类型Set常用操作命令
Jun 01 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
虹吸壶煮咖啡26个注意事项
2021/03/03 冲泡冲煮
Laravel模型事件的实现原理详解
2018/03/14 PHP
脚本吧 - 幻宇工作室用到js,超强推荐base.js
2006/12/23 Javascript
jquery ajax 同步异步的执行示例代码
2010/06/23 Javascript
jQuery页面加载初始化常用的三种方法
2014/06/04 Javascript
checkbox勾选判断代码分析
2014/06/11 Javascript
jQuery中attr()方法用法实例
2015/01/05 Javascript
js实现缓冲运动效果的方法
2015/04/10 Javascript
windows下安装nodejs及框架express
2015/08/07 NodeJs
D3.js中data(), enter() 和 exit()的问题详解
2015/08/17 Javascript
Bootstrap表单布局样式源代码
2016/07/04 Javascript
jQuery之简单的表单验证实例
2016/07/07 Javascript
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
2016/09/09 Javascript
基于JavaScript实现的顺序查找算法示例
2017/04/14 Javascript
理解Angular的providers给Http添加默认headers
2017/07/04 Javascript
jQuery实现广告条滚动效果
2017/08/22 jQuery
Vue-router 类似Vuex实现组件化开发的示例
2017/09/15 Javascript
BootStrap 标题设置跨行无效的解决方法
2017/10/25 Javascript
JavaScript 对引擎、运行时、调用堆栈的概述理解
2018/10/22 Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
2019/06/10 jQuery
JS实现页面跳转与刷新的方法汇总
2019/08/30 Javascript
JavaScript实现京东快递单号查询
2020/11/30 Javascript
进一步探究Python的装饰器的运用
2015/05/05 Python
Python中模块string.py详解
2017/03/12 Python
numpy.random.seed()的使用实例解析
2018/02/03 Python
Python实现通讯录功能
2018/02/22 Python
对Python 获取类的成员变量及临时变量的方法详解
2019/01/22 Python
获取Pytorch中间某一层权重或者特征的例子
2019/08/17 Python
python3.7添加dlib模块的方法
2020/07/01 Python
HTML5 微格式和相关的属性名称
2010/02/10 HTML / CSS
德国旅行、体验和活动的预订平台:Watado
2019/12/04 全球购物
跟单文员的岗位职责
2013/11/14 职场文书
学校评语大全
2014/05/06 职场文书
导游词之重庆渣滓洞
2020/01/08 职场文书
golang正则之命名分组方式
2021/04/25 Golang
浅谈JavaScript浅拷贝和深拷贝
2021/11/07 Javascript