秒杀项目用于处理高并发情况,我们采取发放令牌机制,根据用户的token、商品id、活动商品id和一串uuid产生一个令牌存入redis中
同时引入了秒杀大闸,目的是流量控制,比如当前活动商品只有100件,我们就发放500个令牌,秒杀前会先发放令牌,令牌发放完则把后来的用户挡在这一层之外,控制了流量
获取令牌后会对比redis中用户产生的令牌,对比成功才可以购买商品
首先,获取活动商品详情时就要根据库存设置大闸数量,我们设置大闸为库存的5倍
在发放令牌时就要根据大闸数量判断要不要发放
这样一来就减轻了巨大访问流量带来的压力
但是尽管如此,我们可以试想,如果一个网站做秒杀活动,有是个商品秒杀,每个有1000件,那么就要发放50000个令牌,这样的数量仍然很大,所以我们采取了队列泄洪来解决此问题
什么是队列化泄洪呢,就好比很多人同时进一个门,门很小,人很多,就可以排成队,假如一次能进20个人,就20个人一波,一波一波的进
同理,队列化泄洪就是把访问的用户分成批次,来减轻同时巨大的访问量造成的压力,一般分为令牌桶算法和漏桶算法,我们一般用令牌桶算法,那么怎么实现呢?
我们使用guava limiter 也就是单机限流,限制单个接口的流量
集群限流:依赖redis或者其他的中间件技术做统一的计数器,往往会产生性能瓶颈
单机限流:负载均衡的前提下,单机限流的效果要好
导包:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
在要使用的类下加入:
private RateLimiter orderCreateRateLimiter;
@PostConstruct
public void init() {
orderCreateRateLimiter = RateLimiter.create(180);//设置每秒处理300个请求
}
在下单之前校验
if(!orderCreateRateLimiter.tryAcquire()){
throw new BusinessException(EmBusinessError.RATELIMIT);
}