incr命令和expire命令的误区--举例每分钟访问次数限制

2024-09-04 00:18

本文主要是介绍incr命令和expire命令的误区--举例每分钟访问次数限制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要实现的功能:限制用户的每分钟的访问次数

一个有严重bug的代码:每次访问来了,就执行代码块二,当第一次访问,就走else语句,设置当前用户的次数为1,且设置该key的有效期是一分钟。
在一分钟之内,第二次来访问了,就走if语句了,因为redis存在这个key了,就实现自增一,然后取出来判断是否超过了设定的阈值。逻辑上看似看似没什么问题。

代码块一:

Long maxAllowedTimes = 100L;
Long REQUEST_EXIT_MILLISECONDS = 60*1000L;
代码块二:
Jedis jedis = RedisUtils.getJedis();
String requestKey = Times + ":" + ID + ":" + getId();
if (jedis.exists(requestKey)) {//???jedis.incr(requestKey);String times = jedis.get(requestKey);if (StringUtil.strIsNotEmpty(times)){if (Long.parseLong(times) > maxAllowedTimes) {jedis.del(requestKey);return true;}}
} else {jedis.set(requestKey, "1");jedis.pexpire(requestKey,REQUEST_EXIT_MILLISECONDS);
}


实际上问题来了,maxAllowedTimes给设置成1000次,而实际上每分钟没有超过1000次的去访问数也能return true。
这TM设置的key的有效期没起到作用啊。。。各种讲道理讲不通,也是醉了。。。

其实不然,经过查资料发现:

Redis Incr 命令将 key 中储存的数字值增一,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作,且将key的有效时间设置为长期有效。

耶,这么说就对了。其实,即使判断了key是否存在if (jedis.exists(requestKey)),也不能保证在执行jedis.incr(requestKey)自增的时候key是存在的。问题就出在这里。

就是这么巧,当三个问号“//???”这里时,恰好key到期了,从redis中删除了,然后继续执行jedis.incr(requestKey)自增,这时候,key的value等于1,且key是长期有效的。
所以当前用户不管何时每次访问的时候(只要redis不重启),key始终是存在的,这样就会一直自增,自增,自增到1000次。就这样bug就出现了。

解决方案:得对症下药啊

Jedis jedis = RedisUtils.getJedis();
String requestKey = Times + ":" + ID + ":" + getId();
jedis.incr(requestKey);//如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作,且将key的有效时间设置为长期有效.
String times = jedis.get(requestKey);
if("1".equals(times)){jedis.pexpire(requestKey,REQUEST_EXIT_MILLISECONDS);//如果是第一次访问,设置key的有效时间
} else if(StringUtils.isEmpty(times)){//如果key过期了,再incr(从第1次开始记录),再设置key的有效时间jedis.incr(requestKey);jedis.pexpire(requestKey,REQUEST_EXIT_MILLISECONDS);times = jedis.get(requestKey);
}
if (times != null && Long.parseLong(times) > maxAllowedTimes) {jedis.del(requestKey);return true;
}


至此,问题解决。
这里只是给出了一种“限制用户的每分钟的访问次数”的实现方案,应该还有其他更安全跟有效的实现方案。如有,请赐教,一起学习讨论。


另外:

Redis Incrby 命令将 key 中储存的数字加上指定的增量值,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

Redis Hincrby 命令用于为哈希表中的字段值加上指定增量值。
--------------------- 
作者:Joohong 
来源:CSDN 
原文:https://blog.csdn.net/jingzi123456789/article/details/80625930?utm_source=copy 
版权声明:本文为博主原创文章,转载请附上博文链接!

这篇关于incr命令和expire命令的误区--举例每分钟访问次数限制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134457

相关文章

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

WinForm跨线程访问UI及UI卡死的解决方案

《WinForm跨线程访问UI及UI卡死的解决方案》在WinForm开发过程中,跨线程访问UI控件和界面卡死是常见的技术难题,由于Windows窗体应用程序的UI控件默认只能在主线程(UI线程)上操作... 目录前言正文案例1:直接线程操作(无UI访问)案例2:BeginInvoke访问UI(错误用法)案例

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon