当前位置: 首页 > 后端技术 > PHP

防止超卖物品的3个想法!

时间:2023-03-30 02:42:34 PHP

前言多人同时下单一件商品时,如果处理不当,会出现超卖现象。这个严重的错误是不可接受的。这是一个极其常见的并发问题。这时,一些开发者想到了通过锁来控制它。但是,由于很多朋友对锁的了解并不充分,结果弄巧成拙。下面,我列出一些常见的解决方案和我的想法,请大家参考。1.如何防止超卖在写防止超卖的逻辑时,加锁的思路是没有问题的,但是加什么锁,锁哪一段逻辑就成了问题。1、思路1jvm提供了synchronized和reentrantlock。这两种锁适合在减库存的时候使用吗?理论上是可以用的,但是服务必须部署在单机上。如果有多个服务器,就会变成下面的场景,锁根本没有作用。2.思路2jvm锁的缺点很明显。这时候就会想到分布式锁。分布式锁的实现方式有很多种。我列出了redis和zk的实现和比较。这种方法无论是在单机上还是在集群中使用,都可以有效的防止超卖。大致思路是通过redis的setNX命令实现加锁,加锁后实现单线程减库存,也是比较好的方案。3.思路3在网上看到有人列举了前两种实现方式。这里重点说明单机锁和分布式锁不推荐使用!其实防止超卖的最终目的是为了防止数据库的库存(goods_num)小于0,之所以小于0是因为程序中多线程计算库存,然后赋值给数据库。解决这么多锁的问题,其实一条SQL就可以实现。updatet_goodssetgoods_num=goods_num-1wheregoods_id=1andgoods_num>0如上所示。例如,id为1的一件商品已售出。这时,存货减一。重点是where条件判断goods_num>0。这样就间接限制了sql只有在库存大于1的时候才减1。直接防止了超卖的现象。其实这个时候,就该有人抬杠了。这是一个电商场景,直接连接数据库压力很大。其实这个时候,在去库存之前进行友好的限流是很有必要的。Redis提供了几个命令:incr-adddecr-minusincrby-stepplusdecrby-stepminus这些都是原子操作,执行成功后会返回结果。例如:redis>SETfailure_times10OKredis>DECRfailure_times(integer)9这样如果出现数据库减库存压力过大的场景,可以双判断。库存,当redis库存已经为0时,不需要再减少数据库中的数据。综上所述,以上是我的想法。如果您有更好的解决方案,欢迎评论。