上级限流
针对于浏览器端,可以使用JS进行请求过滤,比如5秒钟之类只能点一次抢购按钮,5秒钟只能允许请求一次后端服务。
这样其实就可以过滤掉大部分普通用户。
但是防不住直接抓包循环调用。这种情况可以最简单的处理:在Web层通过限制一个UID在5秒之类的请求服务层的次数(可利用Redis实现)。
具体实现:进入方法时,判断是否包含某个UID,不存在就是第一次请求,那么可以设置一个过期时间和次数;存在就需要判断次数是否为0,不为0减1,为0表示5秒内的请求数已用完。
限流降级
限流是解决高并发大流量的一种方案,至少是可以保证应用的可用性。
通常有以下两种限流方案:
• 漏桶算法
• 令牌桶算法
漏桶算法非常简单,就是将流量放入桶中并按照一定的速率流出。如果流量过大时候并不会提高流出效率,而溢出的流量也只能是抛弃掉了。这种算法很简单,但也非常粗暴,无法应对突发的大流量。 这时可以考虑令牌桶算法。
令牌桶算法是按照恒定的速率向桶中放入令牌,每当请求经过时则消耗一个或多个令牌。当桶中的令牌为0时,请求则会被阻塞。
RateLimiter是Guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成令牌的速率。
例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌,只有取到令牌的请求才会被成功响应,获取的方式有两种:阻塞等待令牌或者取不到立即返回失败。
限流降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。
缓存
对于读请求则尽量使用缓存,可以提前将数据准备好,不管是 Redis还是其他缓存中间件效率都是非常高的。即提前缓存热点数据,采用LRU淘汰算法。
ps : 刷新缓存情况,比如库存扣除成功这种情况不用马上刷新缓存,如果库存扣到了0再刷新缓存。因为大多数用户都只关心是否有货,并不关心现在还剩余多少。
简而言之,当处理秒杀业务时,可以采取:JS请求过滤、Redis限制请求次数将请求在上层过滤,用MQ削峰,然后才放进业务逻辑里,再进行限流降级。