项目中高并发秒杀处理
目录
高并发秒杀问题
流程:
先来看秒杀活动流程:
- 活动入口
- 客户端秒杀列表页
- 商品秒杀详情页
- 点击购买
- 携带活动ID,商品ID提交服务端
- 服务端判断活动是否结束、商品是否在此活动中、修改数据库商品状态、下单、给用户发短信、给运营发邮件
问题:
问题1: 不到秒杀时间,用户疯狂点击秒杀按钮,给服务端带来额外不必要的压力。
问题2: 秒杀详情用户疯狂的下拉刷新页面。mysql压力大,采用redis缓存活动到时短时期内大量请求到redis没有数据,缓存击穿。
问题3: 同时提交购买,超卖问题
问题4: 秒杀成功后期操作多耗时问题
优化:
- 未到秒杀时间客户端先本地拦截部分请求,减轻服务端压力。
- 商品详情缓存redis,活动快开始时预放置缓存中,商品详情秒杀活动时商品信息几乎不变动。
- 避免缓存击穿,热点商品缓存失效时,分布式锁实现单一协程读mysql。
- 服务端把商品状态和参加活动的信息放置在缓存中,避免大量请求mysql。
- 商品在售状态,抢夺分布式锁,抢夺成功后,修改商品redis商品状态,发送mq,将后续任务异步处理,删除分布式锁。未抢到分布式锁返回客户端排队中,客户端进行短轮询。查询到商品redis状态已修改,提示商品已售出。
- mq读取消息,下单,并用乐观锁检查,防止超卖。再处理后续任务。
- 防止黑客直接请求接口,接口验签。
- 令牌桶流量控制。
这里为啥还要乐观锁呢?不是每次只有一个用户会拿到商品对应的分布式锁吗? 其实,我们想,如果A拿到分布式锁,分布式锁的过期时间我们设置为2秒,那两秒过去了,订单处理还没完成,那么B可能就拿到分布式锁了,就会出现并发修改mysql的情况。