基于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限流的实际应用
Apr 24 Redis
浅谈Redis在直播场景的实践方案
Apr 27 Redis
Redis实现订单自动过期功能的示例代码
May 08 Redis
详解redis分布式锁的这些坑
May 19 Redis
压缩Redis里的字符串大对象操作
Jun 23 Redis
redis使用不当导致应用卡死bug的过程解析
Jul 01 Redis
关于redisson缓存序列化几枚大坑说明
Aug 04 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
redis击穿 雪崩 穿透超详细解决方案梳理
Mar 17 Redis
Redis安装使用RedisJSON模块的方法
Mar 23 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
Redis实现分布式锁的五种方法详解
Jun 14 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
我的论坛源代码(五)
2006/10/09 PHP
UCenter 批量添加用户的php代码
2012/07/17 PHP
轻轻松松学习JavaScript
2007/02/25 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
jQuery 中国省市两级联动选择附图
2014/05/14 Javascript
node.js中的fs.lchownSync方法使用说明
2014/12/16 Javascript
jquery代码实现简单的随机图片瀑布流效果
2015/04/20 Javascript
深入理解JavaScript中的对象
2015/06/04 Javascript
JavaScript中Textarea滚动条不能拖动的解决方法
2015/12/15 Javascript
深入理解JS addLoadEvent函数
2016/05/20 Javascript
es6的数字处理的方法(5个)
2017/03/16 Javascript
详解vue2 $watch要注意的问题
2017/09/08 Javascript
Vue2.0 给Tab标签页和页面切换过渡添加样式的方法
2018/03/13 Javascript
Vue 组件修改根实例的数据的方法
2019/04/02 Javascript
vue实现跳转接口push 转场动画示例
2019/11/01 Javascript
通过JS判断网页是否为手机打开
2020/10/28 Javascript
vue如何使用rem适配
2021/02/06 Vue.js
关于Js中new操作符的作用详解
2021/02/21 Javascript
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
Python中处理字符串之endswith()方法的使用简介
2015/05/18 Python
通过python的matplotlib包将Tensorflow数据进行可视化的方法
2019/01/09 Python
python实现多进程按序号批量修改文件名的方法示例
2019/12/30 Python
Pytorch GPU显存充足却显示out of memory的解决方式
2020/01/13 Python
Python3实现个位数字和十位数字对调, 其乘积不变
2020/05/03 Python
解决Tensorflow2.0 tf.keras.Model.load_weights() 报错处理问题
2020/06/12 Python
Html5页面点击遮罩层背景关闭遮罩层
2020/11/30 HTML / CSS
提供世界各地便宜的机票:Sky-tours
2016/07/21 全球购物
美国排名第一的在线葡萄酒商店:Wine.com
2016/09/07 全球购物
cosme官方海外旗舰店:日本最大化妆品和美容产品的综合口碑网站
2017/01/18 全球购物
行政专员岗位职责
2014/01/02 职场文书
自荐信格式简述
2014/01/25 职场文书
2014年企业党支部工作总结
2014/12/04 职场文书
2016入党积极分子考察评语
2015/12/01 职场文书
在CSS中映射鼠标位置并实现通过鼠标移动控制页面元素效果(实例代码)
2021/04/22 HTML / CSS
HTML+VUE分页实现炫酷物联网大屏功能
2021/05/27 Vue.js
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
2022/04/24 Java/Android