高并发业务场景下的秒杀解决方案

https://www.qqdeveloper.com/2019/10/10/chaomai/

文章简介

本文内容是对并发业务场景出现超卖情况而写的一pian解决方案。主要是利用到了 Redis 中的队列技术。

超卖介绍

所谓的超卖,就是我们的售卖量大于了物品的库存量。该情况一般出现在电商系统中促销类的业务场景中。轻则只是部分商品超卖,较小的经济损失,但是当大量的超卖情况,例如淘宝双十一这样的业务场景下导致超卖,则损失是非常大的,同时给用户体验带来的也是负面影响,很有可能损失用户量。记得之前遇到一个公司,做电商项目,就是因为超卖导致公司倒闭。

常规的秒杀模式

首先,我们见下图

这种模式为什么会出现超卖呢?

按照我们上面所讲的,按理来说是一种正常的逻辑流程。但是当并发量大的时候,就会出现超卖情况。

在上图第 2 步骤中,是做商品库存的查询。假如此时我们查询到的商品库存为 1,这时候就会走 4 中上面的部分(插入抢购信息并减少库存),由于并发量大的情况下,下一个请求在上一个还未执行减库操作就去查询了商品库存,这时候查询出来的库存量依然是 1。

同样的,会走到 4 上面的步骤中去。然后上一个请求执行了减库操作,此时库存为 0,第二个请求再去减库时,就会把库存量设置为-1,这样就出现了超卖情况。

由于并发,同时会发生很多请求,因此减少的数量不仅仅是 1 了,或许是成百上千甚至上万等等。

解决超卖思路

网上有很多这样的思路,几乎是通过队列技术来解决的。先将商品库存信息缓存到我们的缓存中去,例如 Redis。(文章中示例也是通过该方案实现)。

秒杀实现

这里单独讲一讲示例代码中秒杀的解决思路。

在秒杀前将商品的库存信息加入到 Redis 缓存中。如下格式:

当每一个商品有多少个库存则循环多少次,这样就可以保证每个商品队列中的长度就是商品库存长度。其实这里个人是有一个疑问的,如果商品少,我们加入到缓存的耗时是很小的,但是商品数量大,这样就很耗时,并且 redis 是放在内存中的,也暂用大量的内存。

当秒杀开始时,用户发送请求,每次去检测一下商品的队列是否为空,当非空时,则使用 lpop 减少一个长度,也就是减少一个库存量。这时候将秒杀的信息写入到缓存中去,给缓存信息配一个唯一的键,将该键返回给用户。(由于 lpop 是原子性的,jishi大量并发来了,也是要在 Redis 内部进行排队执行的,假如在判断是否为空时,检测到是非空,进行 lpop 操作,由于队列是空,这时候去执行出队列也是返回错误的)。

返回给用户秒杀成功的信息,用户根据返回的键进行下单操作。利用该键,将秒杀中的缓存信息写入数据库并生成对应的订单。

接下来,我们可以结合上图,得出下面的流程图

代码具体实现

创建公共的 Redis 连接

秒杀前将商品库存写入缓存中

模拟客户发送请求,这里可以开多个窗口,增加请求量。

服务端接收秒杀请求并写入缓存

客户端在接收到秒杀请求结果后,进行支付

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20191014A0MIQL00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券