一周技术思考笔记(第47期)-并发与库存有什么关系

2022-01-18 19:25:26 浏览数 (1)

我有一次在做关于并发知识的分享,交流环节的时候,有一位同学提问,并发与库存有什么关系。

其实,他的思路背景是这样,有秒杀活动,会有大流量产生,然后有并发情况出现,扣减库存改怎么办。

那么,从本质上来讲,并发不仅仅跟库存有关系,有并发出现的场景会影响到一切跨多个原子事务的业务。

库存中的两个原子事务,一个是查询库存,一个是扣减库存。

下面这张图是佘志东老师在极客专栏《手把手带你搭建秒杀系统》中的一张图。

现在活动商品有 2 件库存,此时有两个并发请求过来,其中请求 A 要抢购 1 件,请求 B 要抢购 2 件,然后大家都去调用活动查询接口,发现库存都够,紧接着就都去调用对应的库存扣减接口,这个时候,两个都会扣减成功,但库存却变成了 -1,也就是超卖了。

看到这里,估计你会立马想到并发的终身伴侣,锁。

是的,加锁就能够让请求A和请求B在顺序上保持并发安全的先后关系,当然也就不会产生扣减库存结果不一致的情况发生。

肯定也会需要一个分布式锁。

让所有的并发请求,先到这个分布式锁那里,停留”一会“,把请求规整规整,给你排个顺序。造成上面扣减库存结果不一致的原因,一个是上面说的查询库存和扣减库存这两个动作不在一个原子操作里面,另外一个就是这两个请求无序。

看到这里,你肯定也会立马想到Redis这样的中间件,是的,它很适合做这件事。

但是,分布式锁的时间,你该如何控制呢。

时间太短不行,业务有可能因异常原因,导致超时,还没有执行完,锁就失效了。如果发生异常,万一没有及时释放掉这把锁,甚或是释放的时候又发生了异常导致释放失败。那么这样的情况下就跟我们期望的结果不一致了。

当然,有的同学会说这是概率性事件,如果活动的访问量没有那么大,是不是可以采用这样的做法。

那么,我们换个思路呢,可不可以不用锁,我只有将这两个操作放到一个线程里面去执行不就好了吗。

确实是可以的。

Redis本身就是单线程的。

另外Redis还有个特性,可以执行Lua脚本。我们将Lua脚本嵌入到Redis中,另外再借助Redis单线程的特性,这样不就能够实现我们的愿望了么:用一个线程来执行两个操作,这两个操作肯定能够保证顺序性。

关于Redis执行lua脚本的方式,和相关的命令,大家可以搜索或者到文中提到的专栏里面去看一看。

0 人点赞