乐趣区

关于java:防止商品超卖的-3-个思路

作者:叁滴水 \
博客:https://blog.csdn.net/qq_3028…

前言

在多集体同时对一个商品下单时,如果解决的不得当会存在超卖的景象,这种重大的 bug 是无奈承受的。这是一种极为常见的并发问题,这个时候就有开发者想到了通过锁来管制。然而因为很多小伙伴对于锁没有一个充沛的意识,最初却画蛇添足。

如下,我列举一些常见的解决思路和我的想法,请大家参考。

一、如何避免超卖

在避免超卖的逻辑编写时,加锁这个思路是没有问题的,然而要加什么锁,锁哪一段逻辑就成为了问题。

1、思路 1

jvm 提供了 synchronizedreentrantlock

这两个锁适宜在减库存的时候应用吗?

实践上讲,是能够应用的,然而服务必须是单机部署。如果是多台服务器,就会变成如下场景,锁基本没有作用。

2、思路 2

jvm 锁弊病很显著,这时就会想到分布式锁,分布式锁实现的办法有很多。

我列举了下 redis 和 zk 的实现及其比照,这种形式不论是单机还是集群中应用都是能够无效的避免超卖的。大略的思路是由 redis 的 setNX 命令实现进行加锁,加锁之后实现单线程减库存,这也算是一种绝对较好的解决形式。

3、思路 3

我在网上曾看到有人列举后面两种实现形式,这里重点阐明下,单机锁和分布式锁是不举荐的!

其实防超卖最终的目标是避免数据库的库存 (goods_num) 小于 0。导致小于 0 的起因是多个线程在程序中计算库存,而后在赋值给数据库。这么多锁要解决的问题,其实一条 sql 就能够实现。

update t_goods set goods_num=goods_num - 1 where goods_id=1 and goods_num>0

如上所示。例如卖了 id 为 1 的商品 1 件。这时库存减一,重点是 where 条件中判断了goods_num>0。这样就间接的限度了只有库存在大于 1 的时候该 sql 才会减一。间接就避免了超卖的景象。其实这个时候应该就会有人抬杠了,这是电商场景呀,间接连贯数据库压力很大的。其实这个时候就要在减库存之前进行敌对的限流了。

redis 提供了几个命令。

  • incr——加
  • decr——减
  • incrby——阶梯加
  • decrby——阶梯减

这几个都是原子操作,并且在执行胜利之后会返回后果。例如:

redis> SET failure_times 10
OK
redis> DECR failure_times
(integer) 9

这样如果有场景数据库减库存压力太大,能够双重判断,商品开卖之前,redis 缓存商品的库存,先通过 DECR 缩小 redis 库存,再缩小数据库库存,当 redis 库存曾经为 0 的时候,就没有必要再缩小数据库的数据了。

总结

如上便是我的想法,如果您有更好的解决形式,欢送点评。

本文来自作者「叁滴水」投稿,谢谢分享,也欢送喜好技术分享的各位技术敌人向「Java 技术栈」投稿,让更多人看到,投稿形式:关注公众号「Java 技术栈」在后盾回复:投稿。

近期热文举荐:

1.600+ 道 Java 面试题及答案整顿(2021 最新版)

2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

退出移动版