基于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 24 Redis
Django使用redis配置缓存的方法
Jun 01 Redis
Redis缓存-序列化对象存储乱码问题的解决
Jun 21 Redis
聊一聊Redis与MySQL双写一致性如何保证
Jun 26 Redis
springboot使用Redis作缓存使用入门教程
Jul 25 Redis
在项目中使用redis做缓存的一些思路
Sep 14 Redis
Jedis操作Redis实现模拟验证码发送功能
Sep 25 Redis
关于SpringBoot 使用 Redis 分布式锁解决并发问题
Nov 17 Redis
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
Mar 16 Redis
redis调用二维码时的不断刷新排查分析
Apr 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
DedeCMS 核心类TypeLink.class.php摘要笔记
2010/04/07 PHP
PHP Stream_*系列函数
2010/08/01 PHP
PHP操作MongoDB GridFS 存储文件的详解
2013/06/20 PHP
简单的php文件上传(实例)
2013/10/27 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
2014/09/24 PHP
两个php日期控制类实例
2014/12/09 PHP
PHP+jquery+ajax实现即时聊天功能实例
2014/12/23 PHP
php中使用sftp教程
2015/03/30 PHP
php如何获取文件的扩展名
2015/10/28 PHP
CI框架常用方法小结
2016/05/17 PHP
PHP使用php-resque库配合Redis实现MQ消息队列的教程
2016/06/29 PHP
PHP laravel中的多对多关系实例详解
2017/06/07 PHP
封装好的一个万能检测表单的方法
2015/01/21 Javascript
JavaScript性能优化总结之加载与执行
2016/08/11 Javascript
微信小程序 toast 详解及实例代码
2016/11/09 Javascript
vue如何集成raphael.js中国地图的方法示例
2017/08/15 Javascript
详解封装基础的angular4的request请求方法
2018/06/05 Javascript
详解React 的几种条件渲染以及选择
2018/10/23 Javascript
微信小程序实现点赞、取消点赞功能
2018/11/02 Javascript
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
2019/05/08 Javascript
详解vue 2.6 中 slot 的新用法
2019/07/09 Javascript
javascript实现点击星星小游戏
2019/12/24 Javascript
[48:44]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS HGT
2014/05/22 DOTA
python逐行读取文件内容的三种方法
2014/01/20 Python
Python脚本实现网卡流量监控
2015/02/14 Python
python中查看变量内存地址的方法
2015/05/05 Python
Python hashlib模块用法实例分析
2018/06/12 Python
对pycharm代码整体左移和右移缩进快捷键的介绍
2018/07/16 Python
Python2和Python3中@abstractmethod使用方法
2020/02/04 Python
Django 再谈一谈json序列化
2020/03/16 Python
python异常处理、自定义异常、断言原理与用法分析
2020/03/23 Python
Python中的xlrd模块使用原理解析
2020/05/21 Python
美国女孩洋娃娃店:American Girl
2017/10/24 全球购物
opencv实现图像几何变换
2021/03/24 Python
结婚典礼证婚词
2014/01/08 职场文书
入党转正申请自我鉴定
2019/06/25 职场文书