防止商品超卖的 3 个思路!

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 前言在多个人同时对一个商品下单时,如果处理的不得当会存在超卖的现象,这种严重的bug是无法接受的。这是一种极为常见的并发问题,这个时候就有开发者想到了通过锁来控制。但是由于很多小伙伴对于锁没有一个充分的认识,最后却弄巧成拙。

前言

在多个人同时对一个商品下单时,如果处理的不得当会存在超卖的现象,这种严重的bug是无法接受的。这是一种极为常见的并发问题,这个时候就有开发者想到了通过锁来控制。但是由于很多小伙伴对于锁没有一个充分的认识,最后却弄巧成拙。


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


一、如何防止超卖

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


1、思路1

jvm提供了synchronized和reentrantlock。


这两个锁适合在减库存的时候使用吗?


理论上讲,是可以使用的,但是服务必须是单机部署。如果是多台服务器,就会变成如下场景,锁根本没有作用。


image.png


2、思路2

jvm锁弊端很明显,这时就会想到分布式锁,分布式锁实现的方法有很多。


我列举了下redis和zk的实现及其对比,这种方式不管是单机还是集群中使用都是可以有效的防止超卖的。大概的思路是由redis的setNX命令实现进行加锁,加锁之后实现单线程减库存,这也算是一种相对较好的解决方式。


image.png


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的时候,就没有必要再减少数据库的数据了。


image.png


总结

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


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


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
消息中间件 存储 NoSQL
面试题解析:如何解决分布式秒杀系统中的库存超卖问题?
面试题解析:如何解决分布式秒杀系统中的库存超卖问题?
121 0
|
6月前
|
SQL 前端开发 Java
淘东电商项目(74) -秒杀系统(库存超卖解决方案)
淘东电商项目(74) -秒杀系统(库存超卖解决方案)
75 0
|
9月前
|
数据库
.商品秒杀-超卖
.商品秒杀-超卖问题
54 0
|
11月前
|
SQL Java 数据库
Java开发篇 - 库存超卖,库存扣成负数?
库存扣减的时机处理,有对与不对。
202 0
|
缓存 NoSQL JavaScript
面试官:电商库存扣减如何设计?如何防止超卖?
面试官:电商库存扣减如何设计?如何防止超卖?
|
消息中间件 存储 数据库
扣减库存代码实现2|学习笔记
快速学习扣减库存代码实现2
121 0
扣减库存代码实现2|学习笔记
|
消息中间件 RocketMQ 开发者
扣减库存代码实现1|学习笔记
快速学习扣减库存代码实现1
129 0
扣减库存代码实现1|学习笔记
|
Java Scala 开发者
商品打折的最终解决 | 学习笔记
快速学习商品打折的最终解决
56 0
|
Java Scala 网络架构
商品打折的相关知识点和分析 | 学习笔记
快速学习商品打折的相关知识点和分析
85 0
|
SQL NoSQL Java
商品超买超卖问题分析及实战
商品超买超卖问题分析及实战
1073 0
商品超买超卖问题分析及实战