「Redis应用」Redis ”高级“应用场景 -- 限流、延时队列、幂等处理

引言

自Redis入门篇过后,已经好久没更Redis了,接下来应该从实战篇,原理篇,面试篇几个层次来展开,本篇主要是实战篇环节,以问题展开,应对面试场景作答【melo称其为"手撕面答"】,尽量简短,某些部分可能不会进行详细介绍。

emmm,但后边有些部分还是干脆整合在一起了,可观性好一点,不至于看得一头雾水

🎨本篇脑图速览

🎯🎈Redis限流是怎么做的?

固定窗口计数

固定窗口计数是指,假设我们的限流规则是:1min内最多只能访问10次,那么固定窗口就是固定了【 1min-2min】这个窗口内,只能有10次访问 ,相应的我们就要给这个窗口维护一个计数器。 为了节省空间,其实我们不需要维护一个个窗口,只需要维护当前访问时间所在的窗口即可,以及对应的计数器,当新的访问到达了下一个窗口时,则计数器重置即可

redis实现

用redis的话,由于有过期机制,其实设置1min过期,就可以实现计数器重置的效果了

  • redis设置一个名为qps的key,val用来计数,1min过期即可
//原子自增类
RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(redisKey, redisTemplate.getConnectionFactory());
//先自增
int qps = redisAtomicInteger.getAndIncrement();
//若是第一次访问
if(qps==0){
    //设置1min过期
	redisAtomicInteger.expire(1, TimeUnit.MINUTES);
}
if(qps>10){
	throw new RuntimeException("qps超过阈值");
}
复制代码

存在的问题

由于是固定窗口,那其实存在窗口临界问题,比如用户可以在【1.5-2】这段区间访问10次,【2-2.5】这段区间也访问10次,这样就变成了1min内其实可以访问20次!看起来破坏了我们的限流规则,但由于我们是固定窗口计数,到达2的时候已经重置计数器了。

滑动窗口计数

假设我们的限流规则是:1min内最多只能访问10次,那么滑动窗口呢就是会根据你访问进来的时间,以访问时间作为区间末尾当前时间-1min作为区间头部,相当于窗口一直在往右滑动,这样其实就能在一定程度上解决我们刚才提到的窗口临界问题

  • 当访问时间为2.5的时候,此时对于的窗口是【1.5-2.5】,计数器都能正确计数

实现

要获得一段区间,并且按时间排序,我们可以想到用ZSet来实现,能按区间查询出【当前访问时间-1min,当前访问时间】这段区间的计数

//interMills为限流时间,也就是我们这里的1min
Long count = redisTemplate.opsForZSet().count(redisKey, currentTimeMillis - interMills, currentTimeMillis);
复制代码

存在的问题

其实我们只是以更小的窗口大小去移动这个区间罢了,固定窗口计数是以1min为单位去移动,滑动窗口是以1s为单位去移动,后者出现窗口临界问题的概率更小,但依然是可能出现的,比如:

  1. 一开始是【1-2min】这段区间,下一秒会移动为【1min1s - 2min1s】,如果此时有人在1min这一刻,访问了10次,然后下一秒又进入下一个区间了,计数重置,在1min1s这一刻又访问了10次,依旧会出现窗口临界问题,1min内访问次数达到了20次

窗口临界问题小结

其实窗口临界问题,就是在即将被移出窗口的这段区间内,可能一次性访问量达到了我们的阈值,而由于要移出窗口了,计数又将重置了,所以这些访问量就相当于不会被后续统计到,那么后续再次超过阈值,就变成双倍阈值了。

漏桶算法

不限制流入,只限制流出的速率 -- 以一定的速率,去获取桶中的请求

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个开源的Java开发框架,可以用来简化和加速Java应用程序的开发。它提供了很多开箱即用的特性和功能,包括对延时队列的支持。 延时队列是一种可以按照一定的时间顺序处理任务的队列,其中任务会在一定的延时时间后被执行。Spring Boot可以利用基于sorted-set的数据结构来实现延时队列。 在Spring Boot中,可以使用Redis作为存储延时队列的后端。Redis是一个开源的内存数据结构存储系统,支持多种数据结构,包括sorted-set。Sorted-set是Redis的一种有序集合数据结构,可以根据元素的score值进行排序。 要实现基于sorted-set的延时队列,可以将任务的执行时间作为score值,将任务的内容作为value值,将任务存储在sorted-set中。当一个任务需要被执行时,可以通过定时任务或者其他方式,定时从sorted-set中获取score值小于当前时间的任务,并进行处理处理完成后,可以从sorted-set中删除该任务。 基于sorted-set的实现延时队列有以下几个优点: 1. 实现简单:利用Redis的sorted-set数据结构,可以直接存储和获取有序的任务。 2. 高效性能:Redis是一个高性能的内存数据库,可以快速处理大量的任务。 3. 数据持久化:Redis可以将数据持久化到磁盘,保证任务的可靠存储。 总结来说,Spring Boot可以利用Redis的sorted-set数据结构来实现基于sorted-set的延时队列。这种实现简单高效,可以保证任务按照一定的延时顺序进行处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值