库存高并发下的不准确和超卖

本文探讨了在库存管理中避免不准确和超卖的问题,重点介绍了Redis锁的实现,通过setnx确保原子性。此外,讨论了程序锁的synchronized和Lock两种方式,以及各自的特性和适用场景。还提到了数据库锁的机制,包括乐观锁和悲观锁,并指出在分布式环境中可能需要考虑分布式锁解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Redis锁实现方式------通过redis的原子性方法setnx来实现

redis为单线程单进程模式,采用队列模式将并发访问变成串行访问,使用 setnx命令实现分布式锁。

通过注解@CacheLock(lockedPrefix = "xx"),setnx key = xx,如果返回1,则客户端获得该锁,执行程序。若其它客户端同时访问时,会返回0,表示该锁已经被获得,则不执行程序,可进行重试,直至超过设置的重试时间,锁超时。

当获得锁的程序执行完成后,通过del key = xx释放锁,其它重试的客户端则可以进入。

利用setnx防止库存超卖的详细步骤:

  1. 获取锁:使用setnx命令尝试为特定产品设置锁。如果成功获得锁,则可以继续操作;否则,等待锁被释放或重新尝试。
  2. 检查库存:在获得锁后,查询当前库存值,确保库存充足。
  3. 更新库存:如果库存充足,减少库存并更新数据库。
  4. 释放锁:完成操作后,删除锁,释放锁给其他客户端。
  5. 重试逻辑:如果无法获得锁或库存不足,可能需要重试,直到成功为止

2、程序锁有几种实现方式,如何实现

两种 synchronized和lock 
类别 synchronized Lock
存在层次 Java的关键字,在jvm层面上 是一个类
锁的释放 1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁 在finally中必须释放锁,不然容易造成线程死锁
锁的获取 假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待 分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
锁状态 无法判断 可以判断
锁类型 可重入 不可中断 非公平 可重入 可判断 可公平(两者皆可)

性能 少量同步 大量同步

3、先Select 剩余量 from 表,再update为什么有问题

select是共享锁,update是排它锁,共享锁不能解决并发问题

4、乐观锁实现方式

数据库表增加version字段,每次version查询时都增长1.
update test_version set totalprice = #{totalprice,jdbcType=DOUBLE}, 
num = #{num,jdbcType=INTEGER}, price = #{price,jdbcType=DOUBLE},
version = version + 1 where id =#{id,jdbcType=INTEGER} and 

version = #{version,jdbcType=INTEGER}

5、分布式的环境不适用程序锁

6、悲观锁实现方式

先select * from A for update, 根据查出来的信息,再进行update

悲观锁:数据库锁

select -- 共享锁

select * from xx for update 独占锁--表锁

select * from xx where id = ? for update 行级锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值