基于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 sentinel 频繁主备切换的问题
Apr 12 Redis
Django使用redis配置缓存的方法
Jun 01 Redis
浅析Redis Sentinel 与 Redis Cluster
Jun 24 Redis
k8s部署redis cluster集群的实现
Jun 24 Redis
详解redis在微服务领域的贡献
Oct 16 Redis
redis缓存存储Session原理机制
Nov 20 Redis
Redis命令处理过程源码解析
Feb 12 Redis
redis击穿 雪崩 穿透超详细解决方案梳理
Mar 17 Redis
redis数据一致性的实现示例
Mar 18 Redis
Redis 操作多个数据库的配置的方法实现
Mar 23 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 Redis
Redis 异步机制
May 15 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
php2html php生成静态页函数
2008/12/08 PHP
php中长文章分页显示实现代码
2012/09/29 PHP
Symfony2联合查询实现方法
2016/03/18 PHP
PHP中抽象类和抽象方法概念与用法分析
2016/05/24 PHP
jQuery 操作option的实现代码
2011/03/03 Javascript
JS读取cookies信息(记录用户名)
2012/01/10 Javascript
jquery判断元素的子元素是否存在的示例代码
2014/02/04 Javascript
node中socket.io的事件使用详解
2014/12/15 Javascript
jQuery实现最简单的切换图效果【可兼容IE6、火狐、谷歌、opera等】
2016/09/04 Javascript
AngularJS实现按钮提示与点击变色效果
2016/09/07 Javascript
jQuery特殊符号转义的实现
2016/11/30 Javascript
实例解析jQuery中如何取消后续执行内容
2016/12/01 Javascript
angular过滤器实现排序功能
2017/06/27 Javascript
vue2.0 子组件改变props值,并向父组件传值的方法
2018/03/01 Javascript
如何获取TypeScript的声明文件.d.ts
2018/05/01 Javascript
AngularJS修改model值时,显示内容不变的实例
2018/09/13 Javascript
浅析JS中NEW的实现原理及重写
2020/02/20 Javascript
vue移动端的左右滑动事件详解
2020/06/17 Javascript
用Python实现一个简单的能够上传下载的HTTP服务器
2015/05/05 Python
在Python中操作列表之List.append()方法的使用
2015/05/20 Python
Python import用法以及与from...import的区别
2015/05/28 Python
python将一个英文语句以单词为单位逆序排放的方法
2018/12/20 Python
python实现微信自动回复机器人功能
2019/07/11 Python
pyinstaller还原python代码过程图解
2020/01/08 Python
pandas之分组groupby()的使用整理与总结
2020/06/18 Python
python线程里哪种模块比较适合
2020/08/02 Python
使用CSS3编写灰阶滤镜来制作黑白照片效果的方法
2016/05/09 HTML / CSS
行政助理工作职责范本
2014/03/04 职场文书
中国梦演讲稿5分钟
2014/08/19 职场文书
副校长个人对照检查材料思想汇报
2014/10/04 职场文书
2014年学校后勤工作总结
2014/12/06 职场文书
幼儿园毕业致辞
2015/07/29 职场文书
如何在Python项目中引入日志
2021/05/31 Python
PostgreSQL 插入INSERT、删除DELETE、更新UPDATE、事务transaction
2022/04/12 PostgreSQL
Python实现双向链表
2022/05/25 Python
使用CSS定位HTML元素的实现方法
2022/07/07 HTML / CSS