基于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 26 Redis
比较几种Redis集群方案
Jun 21 Redis
k8s部署redis cluster集群的实现
Jun 24 Redis
redis使用不当导致应用卡死bug的过程解析
Jul 01 Redis
redis 存储对象的方法对比分析
Aug 02 Redis
Redis 常见使用场景
Aug 30 Redis
在项目中使用redis做缓存的一些思路
Sep 14 Redis
详解Redis在SpringBoot工程中的综合应用
Oct 16 Redis
Redis中缓存穿透/击穿/雪崩问题和解决方法
Dec 04 Redis
redis的list数据类型相关命令介绍及使用
Jan 18 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
用 PHP5 轻松解析 XML
2006/12/04 PHP
实现了一个PHP5的getter/setter基类的代码
2007/02/25 PHP
用PHP与XML联手进行网站编程代码实例
2008/07/10 PHP
zend framework文件上传功能实例代码
2013/12/25 PHP
php开发中的页面跳转方法总结
2015/04/26 PHP
php等比例缩放图片及剪切图片代码分享
2016/02/13 PHP
详解PHP匿名函数与注意事项
2016/03/29 PHP
ext form 表单提交数据的方法小结
2008/08/08 Javascript
测试JavaScript字符串处理性能的代码
2009/12/07 Javascript
De facto standard 世界上不可思议的事实标准
2010/08/29 Javascript
悄悄用脚本检查你访问过哪些网站的代码
2010/12/04 Javascript
js查找某元素中的所有图片地址的方法
2014/01/16 Javascript
用JavaScript实现类似于ListBox功能示例代码
2014/03/09 Javascript
javascript中clone对象详解
2014/12/03 Javascript
15款jQuery分布引导插件分享
2015/02/04 Javascript
Javascript中匿名函数的调用与写法实例详解(多种)
2016/01/26 Javascript
JavaScript简单实现弹出拖拽窗口(一)
2016/06/17 Javascript
jquery广告无缝轮播实例
2017/01/05 Javascript
JS字符串统计操作示例【遍历,截取,输出,计算】
2017/03/27 Javascript
基于three.js编写的一个项目类示例代码
2018/01/05 Javascript
解决vue项目打包后提示图片文件路径错误的问题
2018/07/04 Javascript
JS实现的Object数组去重功能示例【数组成员为Object对象】
2019/02/01 Javascript
spring+angular实现导出excel的实现代码
2019/02/27 Javascript
基于Element的组件改造的树形选择器(树形下拉框)
2020/02/27 Javascript
[03:24][TI9纪实] Dota奶爸
2019/08/22 DOTA
python client使用http post 到server端的代码
2013/02/10 Python
python创建一个最简单http webserver服务器的方法
2015/05/08 Python
Python中返回字典键的值的values()方法使用
2015/05/22 Python
Django 路由层URLconf的实现
2019/12/30 Python
Python GUI编程学习笔记之tkinter事件绑定操作详解
2020/03/30 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
绘画设计学生的个人自我评价
2013/09/20 职场文书
小学教师岗位职责
2013/11/25 职场文书
《周恩来的四个昼夜》观后思想汇报范文两篇
2014/09/10 职场文书
2014中学教师节广播稿
2014/09/10 职场文书
2015年大学生社会实践评语
2015/03/26 职场文书