在此申明本人未做过电商抢购场景项目,出于好奇搜索相关资料学习之后在此总结出来和各位基友共同探讨,有不足之处望指正.
超发的核心问题是在并发场景下面的多线程安全问题,确保下单操作的原子性就能保证产品不会超卖,但是这样直接加分布式锁整体抢购接口的性能会比较低下,在这里就提出了一个预减概念,先判断库存是否充足,充足的情况下,先预减库存,使用消息队列异步下单(高并发情况下,直接下单接口性能会很低,DB也扛不住,消息队列在这里祈祷削峰填谷流控的功能)
本人是Java码农一个,首先想到的是通过Java代码实现,如下方案一是我实现的思路:
方案一:
1.Java代码执行Redis+Lua脚本,lua脚本中对产品库存进行判断,库存不足返回0,库存足够返回1,并对库存进行预减操作,redis是单线程执行命令的,在这里执行lua脚本能够确保预减操作的原子性,库存不足时告知前端库存不足,库存足够的情况下生成订单号,返回给前端,后面有用处,并将订单号发送消息队列,异步生成订单信息
2.前端针对预减操作返回结构进行处理,抢购成功,根据订单号轮询调用订单详情接口(订单是异步生成的,按照一定频率调用接口直到返回订单数据)
方案二:
原理也是预减库存的方式来杜绝超卖
1.利用nginx+lua+reids在网关层面预减库存,并生成订单号,发送订单号到消息队列,异步生成订单信息
2.前端轮询查询订单状态
方案对比分析:
上述方案二是本人在网上搜索到的一种方案实现,两种方案的核心原理都是先进行预减操作,获取下单资格之后异步生成订单详情.
这种结合redis特性的预减操作,很好的规避了多线程并发问题,将并发请求顺序话,规避了通过加分布式锁的方式保证预减操作的原子性来避免超发的问题,提升了并发抢购的性能
对比方案一和方案二,方案二在网关层面对预减操作进行处理,同时起到阻挡无效请求的作用,比方案一更加高效.
本人文笔功力有限,写起来比较费力,望谅解哈!