基于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位图实现用户签到功能
May 08 Redis
详解Redis瘦身指南
May 26 Redis
Windows中Redis安装配置流程并实现远程访问功能
Jun 07 Redis
聊一聊Redis与MySQL双写一致性如何保证
Jun 26 Redis
浅谈Redis中的RDB快照
Jun 29 Redis
Redis Cluster集群动态扩容的实现
Jul 15 Redis
源码分析Redis中 set 和 sorted set 的使用方法
Mar 22 Redis
Redis 操作多个数据库的配置的方法实现
Mar 23 Redis
Redis数据同步之redis shake的实现方法
Apr 21 Redis
Redis特殊数据类型Geospatial地理空间
Jun 01 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
追忆往昔!浅谈收音机的百年发展历史
2021/03/01 无线电
php Notice: Undefined index 错误提示解决方法
2010/08/29 PHP
php像数组一样存取和修改字符串字符
2014/03/21 PHP
PHP超全局数组(Superglobals)介绍
2015/07/01 PHP
php计算年龄精准到年月日
2015/11/17 PHP
PHP 二维关联数组根据其中一个字段排序(推荐)
2017/04/04 PHP
PHP+Mysql分布式事务与解决方案深入理解
2021/02/27 PHP
用javascript实现的支持lrc歌词的播放器
2007/05/17 Javascript
flash 得到自身url参数的代码
2009/11/15 Javascript
简介JavaScript中Boolean.toSource()方法的使用
2015/06/05 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
javascript中Date format(js日期格式化)方法小结
2015/12/17 Javascript
CascadeView级联组件实现思路详解(分离思想和单链表)
2016/04/12 Javascript
Node.js的Web模板引擎ejs的入门使用教程
2016/06/06 Javascript
再谈Javascript中的基本类型和引用类型(推荐)
2016/07/01 Javascript
BootStrap实现手机端轮播图左右滑动事件
2016/10/13 Javascript
微信小程序中使元素占满整个屏幕高度实现方法
2016/12/14 Javascript
jQuery获取table下某一行某一列的值实现代码
2017/04/07 jQuery
js插件实现图片滑动验证码
2020/09/29 Javascript
React Native 自定义下拉刷新上拉加载的列表的示例
2018/03/01 Javascript
vue打包相关细节整理(小结)
2018/09/28 Javascript
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
利用python实现简单的循环购物车功能示例代码
2017/07/05 Python
numpy找出array中的最大值,最小值实例
2018/04/03 Python
Django框架自定义session处理操作示例
2019/05/27 Python
《小石潭记》教学反思
2014/02/13 职场文书
工商管理专业大学生职业生涯规划范文
2014/03/09 职场文书
安全生产月标语
2014/10/07 职场文书
2014幼儿园中班工作总结
2014/11/10 职场文书
逃课检讨书怎么写
2015/01/01 职场文书
中学生综合素质自我评价
2015/03/06 职场文书
2015年组织委员工作总结
2015/04/23 职场文书
2016年质量月活动总结报告
2016/04/05 职场文书
Mysql超详细讲解死锁问题的理解
2022/04/01 MySQL
Java 关于String字符串原理上的问题
2022/04/07 Java/Android
SQL Server数据库备份和恢复数据库的全过程
2022/06/14 SQL Server