乐观锁解决数据并发冲突

一 为什么会产生并发冲突

我们来看一个例子:

![image](images/7c-24tF7kyRfKLWDJqJ8vbPyStdFx1lkS4dACnBrcg4.png)

我们都知道,这个过程每次单独处理是没有问题的,但是一般情况下,在业务操作的过程中,可能我过程1没有结束,过程2就开始进行了,此时数据就不是之前的数据,如上图,理论我需要的结果是 400+100,完成后,再500+500=1000,实际可能我过程2得到的结果是900。

我们来看以前传统的解决方案是如何开启悲观锁的:

![image](images/ZZKy8_vNsI2xzEzGXJH3cNO9ZreR0RLyjb7NT5z0HvY.png)

手动在sql后边加for update,开启行锁。

悲观锁可以实现这个功能,但是其存在的觉点就是性能实在是太差。

可能会有人说,这个账户就是某个人的,应该不存在很高的并发,但是你想,如果这是一个结算的账户,那么他需要的并发就肯定很高。

那我们需要实现什么样的目标呢?

二 乐观锁的实现

乐观锁的实现是需要我们程序进行设计的,如下:

idbal_version
10014001

我们在表上设计一个_version的版本号,其现在的流程就会变成下边的样子:

![image](images/EO_JnAQTMUlLDwM_8HXjR5XQnIas3JnSokgRGLfuEgg.png)

我们在更新该条数据的时候,获取其值的同时,需要获取其版本号,然后在更新的时候,仅针对当前版本号做更新,同时更新其版本号。

假如当前版本号已被更新,版本号对不上,就需要重新去获取当前的数据,在更新的数据上进行更新。

![image](images/vYPSo1TojsTgbgeloX9FmLsnsx6hLeyfUiw574a5KkY.png)

按照以上的逻辑,其实我们在过程2时,发现版本号不一致,更新其实是不会成功的,保证了数据的安全,但是当前过程却被作废了,那么,如何解决这种数据冲突的问题呢?

首先解决方法一,前端友好提示:

  1. 前端应用提示“数据正在处理,请稍后再试!”

另外的解决方案就是在代码重试:

  1. 附加spring-retry在service上进行方法重试

如图:

![image](images/rfaLiJbvR-goYIT8xn0ntRYW_eb7SnThGqPOJVrHbEA.png)

但是这里要注意,更新结果返回0,不一定是并发问题,有可能是数据没有更新,就是本次更新与上次更新一致,但是我们更新了版本,所以不用太担心。

Last modification:July 5, 2022
If you think my article is useful to you, please feel free to appreciate