基于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
为Java项目添加Redis缓存的方法
May 18 Redis
深入理解redis中multi与pipeline
Jun 02 Redis
Redis主从配置和底层实现原理解析(实战记录)
Jun 30 Redis
Redis如何实现分布式锁
Aug 23 Redis
Window server中安装Redis的超详细教程
Nov 17 Redis
redis缓存存储Session原理机制
Nov 20 Redis
linux下安装redis图文详细步骤
Dec 04 Redis
分布式Redis Cluster集群搭建与Redis基本用法
Feb 24 Redis
基于Redis6.2.6版本部署Redis Cluster集群的问题
Apr 01 Redis
Redis+AOP+自定义注解实现限流
Jun 28 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
全国FM电台频率大全 - 18 湖南省
2020/03/11 无线电
1982年日本摄影师镜头下的中国孩子 那无忧无虑的童年
2020/03/12 杂记
微信公众号开发之微信公共平台消息回复类实例
2014/11/14 PHP
PHP实现根据图片色界在不同位置加水印的方法
2015/08/08 PHP
PHP 5.6.11中CURL模块问题的解决方法
2016/08/08 PHP
PHP实现的CURL非阻塞调用类
2018/07/26 PHP
JavaScript 事件参考手册
2008/12/24 Javascript
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
2010/01/07 Javascript
IE6下CSS图片缓存问题解决方法
2010/12/09 Javascript
通过Jquery遍历Json的两种数据结构的实现代码
2011/01/19 Javascript
JQuery1.6 使用方法三
2011/11/23 Javascript
JavaScript中判断整数的多种方法总结
2014/11/08 Javascript
jQuery中$.get、$.post、$.getJSON和$.ajax的用法详解
2014/11/19 Javascript
NodeJS中Buffer模块详解
2015/01/07 NodeJs
Node.js 学习笔记之简介、安装及配置
2015/03/03 Javascript
Angularjs制作简单的路由功能demo
2015/04/14 Javascript
JavaScript实现仿新浪微博大厅和腾讯微博首页滚动特效源码
2015/09/15 Javascript
AngularJs bootstrap搭载前台框架——基础页面
2016/09/01 Javascript
jQuery内容过滤选择器用法示例
2016/09/09 Javascript
JavaScript正则表达式替换字符串中图片地址(img src)的方法
2017/01/13 Javascript
纯js实现画一棵树的示例
2017/09/05 Javascript
vue数组对象排序的实现代码
2018/06/20 Javascript
在vue使用clipboard.js进行一键复制文本的实现示例
2019/01/15 Javascript
vue实现前端列表多条件筛选
2020/10/26 Javascript
Python文件和目录操作详解
2015/02/08 Python
python中使用序列的方法
2015/08/03 Python
python实现杨辉三角思路
2017/07/14 Python
Python 内置函数memoryview(obj)的具体用法
2017/11/23 Python
Django中使用session保持用户登陆连接的例子
2019/08/06 Python
python 监测内存和cpu的使用率实例
2019/11/28 Python
python实现图片转换成素描和漫画格式
2020/08/19 Python
职工运动会邀请函
2014/02/02 职场文书
房屋租房协议书范本
2014/12/04 职场文书
2015年父亲节活动总结
2015/02/12 职场文书
开工典礼致辞
2015/07/29 职场文书
毕业欢送会致辞
2015/07/29 职场文书