业务场景系列:更新Redis中设置过期时间Key的值

本文介绍了一种通过Redis实现的接口限流策略,以防止无登录用户恶意提交数据导致系统卡顿或宕机。在初步构思中,使用用户的IP地址作为键,并设置提交次数限制和过期时间。然而,测试发现由于键值对过期时间被覆盖,导致限流失效。为解决此问题,升级方案提出使用额外的键记录过期时间,确保限流的有效性。通过这种方式,实现了对无登录用户提交请求的合理限制,保护了系统的稳定运行。
摘要由CSDN通过智能技术生成

1.需求分析

在编写一个插入数据的接口,这个接口是对接前端的的,前端的功能大致就是用户浏览和留言,因为这个页面是无登录的,只要是使用者都可以提交这个数据,这个接口是公开的,为了避免有恶意的数据提交请求导致大量的脏数据保存,造成程序卡顿甚至宕机,对这个接口进行优化改造。

2.初级构思

在用户发送请求时,传过来的同时有HttpServletRequest,从这个里面可以获取用户的IP地址,利用Redis可以设置过期Key的方式,以ration加上用户IP为key,插入的value为可以提交数据的次数,然后设置过期时间。

redisService.set("rate:" + userIp,50,10,TimeUnit.MINUTES);

这句代码的意思是设置一个过期时间为10分钟的键值对,这样每次插入的时候,先查询一下value,如果这个key不存在的时候就set一次设置key的过期时间,如果value大于0的时候可以继续插入,插入的同时给key设置一个原值减一的值。如果value小于等于0的时候,就不能继续插入,返回一个提示。

if (rate>0){
	customerService.save(entity);
    redisService.set("rate:" + userIp,(rate-1));
} else if (rate<=0){
   return R.error().data("msg","提交次数超过限制,请勿重复提交!");
}
 

表面看这样没毛病,当时间到了,这个key就不存在了,程序便会新set一个过期时间为10分钟的key。但程序经过测试之后,数据的大量插入任然可以,用循环100次进行数据插入,结果都是success。这样结果不没有达到效果的。

在这里插入图片描述

3.原因分析

在经过Debug断点后发现,在每次插入之后对key重新set的操作,就相当于覆盖原有键值对,连同过期时间也覆盖掉,这样新set的键值对是没有过期时间的,另外在插入之前也没有新获取rate的值,导致rate的值一直不变,这样就产生了两个bug,key一直不会过期,数据也能无限次插入。

4.升级构思

在CSDN翻了半天发现没有一种很直观的方法,不过在经过60000毫秒的思考之后,发现可以另外再设置一个键值对,key为time加上用户的ip地址,value值为当前时间毫秒值加上过期时间毫秒值,就能算出key过期的时间了。代码设计如下:

Integer rate = getRate("rate:" + userIp,userIp);
if (rate==null){
	 redisService.set("rate:" + userIp,50);
     redisService.set("time:"+userIp,System.currentTimeMillis()+GlobalConstant.TEN_MINUTES);
    }

这样的设计之外我们要封装一个新的get key的方法:

private Integer getRate(String key, String userIp){
        Long expires = redisService.get("time:" + userIp);
        if (expires==null){
            return null;
        }else {
            if (System.currentTimeMillis()>=expires){
                redisService.del("time:" + userIp);
                redisService.del(key);
                return null;
            }else {
                return redisService.get(key);
            }
        }
    }

在过期时间为空的时候,rate的值也一定为空,所以直接返回空,否则就要对比当前时间和过期时间,如果当前时间大于过期时间,说明这个rate的时间已经到了,就需要删除rate和expires,当两个都删除后同样返回空,如果当前时间小于过期时间,就说明rate还在有效时间内,这个时候就正常get值就行,将获取的value返回即可,判断逻辑依旧为rate小于或者等于0的时候不能进行数据的插入。
当rate为空的时候,就继续创建新的rate和time键值对。

插入十次数据

插入50次数据

利用Redis实现一个简单的提交请求限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值