秒杀架构
参考资料
这个比较靠谱的博客
http://blog.51cto.com/13527416/2085258?cid=700792
思路
- 页面做控制(页面jsp加载的时候,获取到后台的活动开始时间)
- 按钮做控制:活动开始前提交按钮置灰防止提前抢单
- 按钮做控制:开始时提交成功后置灰按钮,防止重复提交
- 防止恶意的抢单
- 控制层对请求的时间做校验,防止通过url或者程序恶意抢单,没开始就抢单了,超出了js控制
- redis做IP限流
- redis做用户名限流
缓存库存(Redis)
不管活动开始了,还是活动没开始,查询库存的时候,都是从redis获取库存分布式悲观锁(参考redis悲观锁的代码)
- 悲观锁(因为肯定争抢严重)
- Expire时间(抢到锁后,立刻设置过期时间,防止某个线程的异常停摆,导致整个业务的停摆)
- 定时循环和快速反馈(for缓存有超时设置,每次超时后,重新读取一次库存,还有货再进行第二轮的for循环争夺,实现快速反馈,避免没有货了还在持续抢锁)
- 异步处理订单
- redis抢锁成功后,记录抢到锁的用户信息后,就可以直接释放锁,并反馈用户,通过异步的方式来处理订单,提升秒杀的效率
- 为了避免异步的数据不同步,需要抢到锁的时候,在redis里面缓存用户信息列表,缓存结束后,触发抢单成功用户信息持久化,并且定时的比对一致性
消息队列削峰限流(RocketMQ自带的Consumer自带线程池和限流措施),集群。一般都是微服务,订单中心、库存中心、积分中心、用户的商品中心
数据库的并发修改(库存总数的扣减)
- 库存数据先加锁读取再修改的方式(select * for update 再 update 库存)避免集群模式下的修改无效的情况
- 扣减的时候再check一下,防止异常的消费,例如库存不能为负
架构图
Nginx在前端–> 对应多台集群的机子前端控制层(嵌套上Redis) –>MQ –>服务端处理订单 –> RPC更新各个微服务的库存中心、订单中心、积分中心等等完成订单