基于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 08 Redis
Redis延迟队列和分布式延迟队列的简答实现
May 13 Redis
Windows下redis下载、redis安装及使用教程
Jun 02 Redis
redis requires ruby version2.2.2的解决方案
Jul 15 Redis
关于redisson缓存序列化几枚大坑说明
Aug 04 Redis
Redis字典实现、Hash键冲突及渐进式rehash详解
Sep 04 Redis
SpringBoot集成Redis的思路详解
Oct 16 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
Window server中安装Redis的超详细教程
Nov 17 Redis
使用RedisTemplat实现简单的分布式锁
Nov 20 Redis
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
Feb 12 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
解析PHP留言本模块主要功能的函数说明(代码可实现)
2013/06/25 PHP
php 删除目录下N分钟前创建的所有文件的实现代码
2013/08/10 PHP
php取整函数ceil,floo,round的用法及介绍
2013/08/31 PHP
使用PHP curl模拟浏览器抓取网站信息
2013/10/28 PHP
ThinkPHP实现递归无级分类――代码少
2015/07/29 PHP
PHP文件上传之多文件上传的实现思路
2016/01/27 PHP
深入剖析PHP中printf()函数格式化使用
2016/05/23 PHP
PHP实现数组array转换成xml的方法
2016/07/19 PHP
php使用parse_str实现查询字符串解析到变量中的方法
2017/02/17 PHP
PHP单例模式与工厂模式详解
2017/08/29 PHP
php 截取中英文混合字符串的方法
2018/05/31 PHP
PHP实现二维数组中的查找算法小结
2018/06/09 PHP
优化 JavaScript 代码的方法小结
2009/07/16 Javascript
JavaScript的继承的封装介绍
2013/10/15 Javascript
简单学习JavaScript中的for语句循环结构
2015/11/10 Javascript
Javascript 实现微信分享(QQ、朋友圈、分享给朋友)
2016/10/21 Javascript
jquery 实时监听输入框值变化的完美方法(必看)
2017/01/26 Javascript
Element InputNumber 计数器的实现示例
2020/08/03 Javascript
[01:07:19]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第一场
2018/04/06 DOTA
[28:07]完美世界DOTA2联赛PWL S3 Phoenix vs INK ICE 第二场 12.13
2020/12/17 DOTA
python matplotlib画图实例代码分享
2017/12/27 Python
python实现支付宝当面付(扫码支付)功能
2018/05/30 Python
基于python实现聊天室程序
2018/07/27 Python
Python Django的安装配置教程图文详解
2019/07/17 Python
opencv 获取rtsp流媒体视频的实现方法
2019/08/23 Python
python飞机大战pygame碰撞检测实现方法分析
2019/12/17 Python
Python实现对adb命令封装
2020/03/06 Python
女大学生毕业找工作的自我评价
2013/10/03 职场文书
采购主管的岗位职责
2013/12/17 职场文书
《叶问2》观后感
2015/06/15 职场文书
2019 入党申请书范文
2019/07/10 职场文书
php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
2021/04/01 PHP
多表查询、事务、DCL
2021/04/05 MySQL
Python文件的操作示例的详细讲解
2021/04/08 Python
win10以太网连接不上怎么办?Win10连接以太网详细教程
2022/04/08 数码科技
Java 数组的使用
2022/05/11 Java/Android