之前完成了一个秒杀下单系统的开发,现在总结一下,

<>起因

业务场景是社区电商,
疫情期间,社区准备了一批口罩,打算分批让用户抢购。那时我们还在过年,客户也没通知我们,然后我们这个小电商系统,在当晚就挂掉了。下面是我们当时的架构:类似下面

稍微思考到这个架构的问题,用户下单时,redisson进行加锁时,会让其他线程等待。所以在并发大时,会导致tomcat连接数超限。后面查询日志也证明了如此,所以当时临时的解决方案是,重启+增加应用容器。总算勉强度过。

后面我们紧急改造了我们的业务j流程,变成了下面这样:

主要做了两点改变:

​ 1.将查询库存放到了redis中

​ 2.将实际的下单功能放到了,MQ应用中。

这样极大的提高了前端应用的承载能力,经实战测试 2万的口罩,3分钟内全部卖空,系统平稳运行。

首先先看一下我们现在具体的秒杀流程。

<>秒杀流程概览:

文字表述如下:

* 客户提交订单,包含多个商品
* 后台应用
* 对商品id加锁,
* 循环判断商品库存是否在redis中存在
* redis没有库存,从数据库查询库存,减去本次构购买数,放入到redis中
(如果库存不够此次贩卖,将数据库库存放入到redis中)
* redis中有库存,减去本次购买数,重新放到redis中。
* 解锁生成订单号,将本次订单信息发送到mq,异步消费
* 返回订单号,
* 客户端获取订单号,轮询查询订单状态。
* MQ消费应用
* 对商品,促销商品,优惠券,积分进行加锁
* 扣减优惠券,积分,生成订单,扣减库存,保存订单信息
* 将订单结果存入redis。解锁
* 完成实际下单
* 前端轮询查询订单是否下单成功
<>问题

看完整个详细流程,已经解决了主要的高并发问题,现在讲讲实际遇到的一些问题:

<>1.如果redis缓存被清空了怎么办?

因为我们公司目前将redis的作用就是缓存,所以当redis快满了时,运维会将redis进行清空。(虽然有做redis
内存淘汰侧率,但是主要是总有人使用redis时没设置redis的过期时间),所以redis缓存失效的情况,需要考虑,所以我们mq消费时,会重新加锁,如果发现库存不足,会将结果存入redis。前端通过oderNo轮询就知道订单失败。

<>2.库存不足

情景一 :提交两个商品,一个redis 库存够,另一个redis库存不够如何处理?

情景二:提交两个商品,一个在redis中有库存,但库存不足,另一个redis没有库存,需要从数据库查询,但库存足够本次购买:

答:这个我们处理思路是,判断是否超卖 循环中判断,但是所有redis存库存的操作,解锁前统一保存到redis。(我们是 redis
cluster,分片了不支持事务);

<>3.秒杀开始后能否修改库存?

这个当时我们是考虑到库存存到redis了,并设置过期时间,所以无论商家改大或者该小,都不会导致错误。但是,由于MQ消费消息,是有并发锁的,这个时候去看的库存,是不真实的,因为有许多订单是已经提交,但是没有落库。所以我们禁止了秒杀开始后修改库存

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信