目录

项目中高并发秒杀处理

高并发秒杀问题

流程

先来看秒杀活动流程:

  1. 活动入口
  2. 客户端秒杀列表页
  3. 商品秒杀详情页
  4. 点击购买
  5. 携带活动ID,商品ID提交服务端
  6. 服务端判断活动是否结束、商品是否在此活动中、修改数据库商品状态、下单、给用户发短信、给运营发邮件

问题

问题1: 不到秒杀时间,用户疯狂点击秒杀按钮,给服务端带来额外不必要的压力。

问题2: 秒杀详情用户疯狂的下拉刷新页面。mysql压力大,采用redis缓存活动到时短时期内大量请求到redis没有数据,缓存击穿。

问题3: 同时提交购买,超卖问题

问题4: 秒杀成功后期操作多耗时问题

优化

  1. 未到秒杀时间客户端先本地拦截部分请求,减轻服务端压力。
  2. 商品详情缓存redis,活动快开始时预放置缓存中,商品详情秒杀活动时商品信息几乎不变动。
  3. 避免缓存击穿,热点商品缓存失效时,分布式锁实现单一协程读mysql。
  4. 服务端把商品状态和参加活动的信息放置在缓存中,避免大量请求mysql。
  5. 商品在售状态,抢夺分布式锁,抢夺成功后,修改商品redis商品状态,发送mq,将后续任务异步处理,删除分布式锁。未抢到分布式锁返回客户端排队中,客户端进行短轮询。查询到商品redis状态已修改,提示商品已售出。
  6. mq读取消息,下单,并用乐观锁检查,防止超卖。再处理后续任务。
  7. 防止黑客直接请求接口,接口验签。
  8. 令牌桶流量控制。

这里为啥还要乐观锁呢?不是每次只有一个用户会拿到商品对应的分布式锁吗? 其实,我们想,如果A拿到分布式锁,分布式锁的过期时间我们设置为2秒,那两秒过去了,订单处理还没完成,那么B可能就拿到分布式锁了,就会出现并发修改mysql的情况。