基于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 27 Redis
redis内存空间效率问题的深入探究
May 17 Redis
redis实现共同好友的思路详解
May 26 Redis
详解缓存穿透击穿雪崩解决方案
May 28 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
Feb 12 Redis
解决Redis启动警告问题
Feb 24 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
Redis分布式锁的7种实现
Apr 01 Redis
使用Redis实现分布式锁的方法
Jun 16 Redis
一文教你快速生成MySQL数据库关系图
Jun 28 Redis
redis lua限流算法实现示例
Jul 15 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 变量未定义等错误的解决方法
2011/01/12 PHP
超小PHP小马小结(方便查找后门的朋友)
2012/05/05 PHP
PHP采集类Snoopy抓取图片实例
2014/06/19 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
浅谈php调用python文件
2019/03/29 PHP
Yii2框架中一些折磨人的坑
2019/12/15 PHP
javascript preload&amp;lazy load
2010/05/13 Javascript
ASP.NET jQuery 实例18 通过使用jQuery validation插件校验DropDownList
2012/02/03 Javascript
在子窗口中关闭父窗口的一句代码
2013/10/21 Javascript
jquery左边浮动到一定位置时显示返回顶部按钮
2014/06/05 Javascript
基于Jquery easyui 选中特定的tab
2015/11/17 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
jquery实现全选和全不选功能效果的实现代码【推荐】
2016/05/05 Javascript
微信小程序 教程之WXML
2016/10/18 Javascript
JavaScript函数节流和函数防抖之间的区别
2017/02/15 Javascript
再谈Angular4 脏值检测(性能优化)
2018/04/23 Javascript
Vue源码中要const _toStr = Object.prototype.toString的原因分析
2018/12/09 Javascript
浅谈vue3中effect与computed的亲密关系
2019/10/10 Javascript
JS实现关闭小广告特效
2021/01/29 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
2020/08/22 Javascript
Python批量修改文本文件内容的方法
2016/04/29 Python
Django Highcharts制作图表
2016/08/27 Python
python在ubuntu中的几种安装方法(小结)
2017/12/08 Python
Python2中文处理纪要的实现方法
2018/03/10 Python
python程序封装为win32服务的方法
2021/03/07 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
2020/02/04 Python
Python使用PyQt5/PySide2编写一个极简的音乐播放器功能
2020/02/07 Python
iframe在移动端的缩放的示例代码
2018/10/12 HTML / CSS
巴黎卡诗美国官方网站:始于1964年的头发头皮护理专家
2017/07/10 全球购物
菲律宾优惠券网站:MetroDeal
2019/04/12 全球购物
MYSQL支持事务吗
2013/08/09 面试题
单位在职证明范本
2014/01/09 职场文书
2014年科研工作总结
2014/12/03 职场文书
在Spring-Boot中如何使用@Value注解注入集合类
2021/08/02 Java/Android
Element-ui Layout布局(Row和Col组件)的实现
2021/12/06 Vue.js
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android