加锁失效,非锁之过,加之错也|京东零售供应链库存研发实践

本文导读

从事京东零售供应链库存业务,库存数量操作增减十分频繁,并且项目开发中会常常遇到各种并发情况,一旦库存数量操作有误,势必给前台销售产生损失影响,因此需要关注对库存数量并发操作下的一致性问题。

大部分情况下,加锁可以很好地解决并发问题,但是只要加上锁后就一定不会有并发问题吗?哪些情况下引起锁失效呢?本文会以一个真实的线上案例来剖析业务处理加锁过程易使用不当的点以及对应的解决方案。

引言

多个进程或线程同时(或着说在同一段时间内)访问同一资源会产生并发问题。

比如:银行两操作员同时操作同一账户就是典型的例子。比如A、B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户减去 50元,A先提交,B后提交。最后实际账户余额为1000-50=950元,但本该为1000+100-50=1050。这就是典型的并发问题。

从事零售供应链库存业务,对库存数量操作增减十分频繁,同样存在类似上述银行取款遇到的问题,库存数量操作有误势必给前台销售产生损失影响,因此需要关注对库存数量并发操作下的一致性。

下面通过一个真实的案例分享在并发情况下如何保证库存数量的准确性。

问题是什么-加锁失效

看看下面这段流程和代码,思考会有并发问题吗?

1.加锁前,获取箱子明细数据,此处在锁之外,存在并发脏读问题

2.加锁后,并进行箱子上架分批次回传业务处理

3.加锁后,更新箱子明细上架数量逻辑:已上架数量 = 加锁前的明细数据(脏读) + 报文回传的明细数据 直接进行行更新

原因是什么-加锁的位置不正确

核心的问题原因

1.业务分布式锁失效:使用分布式锁加锁了,但是仍然使用加锁前查询的数据,导致出现脏读

2.Mysql锁失效:数据库更新时,未上任何锁,导致脏读的数据直接覆盖更新当前行

有同学这时问了,为啥防重码也没有生效呢?

防重码主要是用作幂等逻辑的,同一个请求多次处理,结果仍然是相同的。

但是这是两次不同的请求,防重码是不同的,因此不能只依赖防重码保证一致性。

解决方案有哪些

**1、代码层面:**使用锁(如互斥锁、读写锁、分布式锁等)来控制资源的访问,数据获取的全部操作都需要再获取锁后才进行。

将获取箱子明细的代码移动到加锁之后,只有获取到分布式锁,才能执行分批次上架查询和更新(串行化)

对应改造后的代码:

**2、数据库层面:**实现事务管理,确保数据的一致性;合理设置事务隔离级别,以防止脏读、或者采用乐观锁或悲观锁来处理并发更新,合理设计查询效率,减少锁竞争。

数据库的并发上锁处理和业务代码的上锁是互补的关系

因为无法保证后续业务的调整或其他业务代码的调用能始终保持获取数据的一致性,数据库的并发上锁处理更多是一种兜底保证机制。

乐观锁更新

悲观锁更新

扩展方案

**应用程序设计:**在应用程序设计阶段,尽量避免长时间持有数据库连接或事务,减少并发操作的可能性,利用AI代码评审或者人工提前找出可能出现并发问题的地方;合理设置锁的粒度,避免锁失效。

**网络负载层面:**采用限流控制访问频率;采用分布式数据库,进行数据分片,降低单节点并发压力;使用负载均衡,将网络请求分发到不同的服务器,提高系统处理并发的能力,防止系统过载。

**请求层面:**前端点击防重、系统幂等防重、尽可能降低同一请求的多次重试访问引起的一致性问题。

通过以上措施,可以在不同层面有效地防止并发问题,保证系统的数据的一致性。

相关推荐
2301_8112743115 分钟前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
草莓base1 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Ljw...1 小时前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
编程重生之路1 小时前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端
薯条不要番茄酱1 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
qq_17448285759 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
锅包肉的九珍10 小时前
Scala的Array数组
开发语言·后端·scala
心仪悦悦10 小时前
Scala的Array(2)
开发语言·后端·scala
2401_8827275710 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
心仪悦悦11 小时前
Scala中的集合复习(1)
开发语言·后端·scala