为什么加了锁还是出现库存扣超的情况

本文探讨了在高并发环境下实现库存预扣减的挑战与解决方案。通过对比Redis分布式锁与Redisson的性能,分析了预扣减记录插入事务未及时提交导致的数据错误,并提出使用Spring事务监听来确保数据一致性的方法。

最近碰到一个需求,库存扣减,要保证在高并发情况下不出问题。

第一想到的就是redis分布式锁,为了保证原子操作,加锁和解锁都使用lua脚本,但是在压力测试的时候发现,TPS只有个位数,而且成功率不好控制,我是自己控制尝试获取锁的次数,因此造成了大量的线程阻塞。

后面找了一些资料,改为redisson,TPS能达到100以上,成功率在90%以上,以为就此完结,后来自己做测试的时候发现数据总是有误,这里再提一下,业务并不是直接扣减库存,而是预扣减,我的做法是增加一条预扣减库存记录,在确认扣减后再进行真正的库存扣减,所以在每次有预扣减前先查询预扣减记录,用实际的库存减去预扣减记录之和后才是剩下的库存,但是在压测的情况下(100个线程循环10次,测试工具为jmeter),库存明明只有一个,居然出现多余一条的预扣减记录,也就是说实际库存是不够减的,排除了锁的问题,最后发现其实是插入预扣减库存记录的事务没有及时提交(用的ORM是spring-data-jpa),也就是说,第一个线程进来,插入了一条预扣减库存数据,但是并没有立即提交这个事务,然后释放锁,第二个线程进来查询预扣减数据并没有查到第一个线程插入的那条数据,于是库存数据就出错了。

在网上找了很多资料,找到了一种解决方案,就是spring的事务监听,等待事务提交后再释放锁,让新的线程进来,就不会出错了。

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    lock.unlock();
                }
            });

把查询与插入操作抽取到一个单独的方法中并加上事务注解,然后加上上面的这段代码,就可以保证在高并发下库存的正确性。

当然,这个监听也是个同步方法,会一直等待事务提交,所以性能上有些许的下降,但还能接受,至少在分布式部署的情况下高并发也不会出现库存错误的问题。

<think> 嗯,用户这次问的是“购物车的库存联动的含义”,结合之前的对话历史,用户似乎对“联动”这个概念在不同领域的应用很感兴趣。之前讨论过艺术领域的库存联动,现在转向了电商场景。 用户提供的几个引用很有价值,特别是引用[1]的代码示例和引用[3]的业务逻辑说明。从这些材料可以看,用户可能正在开发或研究电商系统,需要理解购物车与库存的交互机制。用户身份可能是开发者或产品经理。 库存联动在购物车场景中核心要解决三个问题:实时性(操作时立即检查库存)、一致性(避免卖)、反馈性(提示用户库存不足)。引用[1]的代码片段展示了典型的实现逻辑: - 新增商品时直接校验库存 - 修改数量时再次校验 - 数据库事务确保数据一致性 用户可能还隐含想知道如何设计这个功能。需要强调几个关键点: 1)校验时机:不能只在结算时校验,添/修改购物车就要校验 2)库存减策略:预库存还是实时库存 3)并发处理:用乐观防止卖 另外引用[3]提到的促销系统联动也值得展开,比如满减活动可能影响用户频繁增减商品数量,这时候库存校验会更频繁。不过当前问题聚焦在基础含义,这部分可以放在后续问题里。 最后生成的三个相关问题都很有实操性: 第一个针对技术选型(校验策略),第二个涉及用户体验(交互设计),第三个关于系统设计(扩展性)。这样用户可以根据自己需求深入探索。 </think> 购物车的库存联动是指**购物车系统与库存管理系统实时交互的机制**,确保用户操作(添/修改商品数量)时,商品库存状态能即时反馈并约束购物行为,避免卖。其核心含义如下: --- ### 一、联动的关键机制 1. **实时库存校验** - 用户添商品到购物车或修改数量时,系统实时查询库存数据库。 - **举例**:若用户尝试购买10件商品,但库存仅剩5件,系统自动拦截并提示库存不足(引用[1]中的`联动校验`逻辑)。 2. **库存预占与释放** - **预占机制**:商品入购物车后,部分系统会暂时冻结对应库存(防止其他用户抢购)。 - **释放机制**:若购物车商品时未结算,库存自动释放(引用[3]中促销系统与购物车的联动)。 3. **动态数据同步** - 库存变动(如管理员补货、其他用户下单)实时同步到购物车界面。 - **示例**:商品降价时,购物车页面显示“已降价XX元”(引用[3])。 --- ### 二、技术实现原理 ```java // 引用[1]代码逻辑简化: public void addToCart(userId, productId, count) { // 1. 校验库存 Product product = productMapper.selectStock(productId); if (product.getStock() < count) { throw new Exception("库存不足"); } // 2. 更新购物车 Cart cart = cartMapper.findByUserAndProduct(userId, productId); if (cart == null) { cartMapper.insert(new Cart(userId, productId, count)); // 新增 } else { cart.setQuantity(cart.getQuantity() + count); cartMapper.update(cart); // 修改 } // 3. 联动库存系统(可选预占逻辑) inventoryService.reserve(productId, count); } ``` - **关键点**:操作前后均需校验库存,确保数据一致性(引用[1]中的`库存和购买数量联动校验`)。 --- ### 三、业务价值 1. **避免卖风险** 实时拦截库存购买,保障订单可履约(如引用[1]的校验逻辑)。 2. **提升用户体验** - 库存不足时即时提示,减少结算失败率。 - 动态显示价格/库存变化(引用[3])。 3. **支持复杂促销** 库存联动促销系统,实现“满减”“限购”等规则(引用[3]中促销系统的交互)。 --- ### 四、扩展场景 - **规格商品联动**:如手机选择不同颜色/内存组合时,联动显示对应库存(引用[4]中的规格选择逻辑)。 - **分布式系统挑战**:高并发下需用**分布式锁**或**Redis原子操作**确保库存准确。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值