乐观锁原理与实战演练

一、 前言

最近在做一个简单审批流程的项目,由于只有固定二级审批所以没有工作流组件,然后就遇到一个审批节点捞单时候,多个人同时审批时候如何保证业务正常运行的问题,我采用的就是乐观锁来解决的。所谓捞单就是一个审批节点可以同时由多个人同时审批。

二、 乐观锁实现方式

乐观锁意思是说多个事务修改数据库中同一条记录时候,并不是在一个事务中使用 for update 锁定这条记录从而防止其他事务在本事务提交前访问这条记录,而是在具体执行更新语句时候进行判断,并通过更新结果影响的行数来判断当前更新是否有效。具体来说有两种实现方式:

2.1 使用业务状态来实现乐观锁

比如一个任务表里面包含如下字段:

id

comment

status

1

123456

new

一个任务的status有:new,operator,manager状态。new状态下有多个A人可以去更新这条记录的comment并且把status更新为operator,但是只能有一个人能成功。operator状态下可以多个B人去更新这题记录的comment并且status更新为manager但是只有一个人能更新成功。

这时候就可以使用status这个字段的值来实现乐观锁,具体来说: 对于A类人来说更新使用: update 表 set comment='',status='operator' where status = 'new' and id = 1; 对应B类型来说更新使用: update 表 set comment='',status='manager' where status = 'operator' and id = 1;

假如多个A类人同时去更新数据时候,第一个执行更新语句的人会锁住该条记录,更新status='operator",这时候其他事务是访问不了该记录的,直到当前事务提交返回结果1。当前事务提交后,然后其他事务在执行这条语句,这时候由于根据条件status = 'new' and id = 1获取到0条记录,所以返回0.所以如果更新结果返回1,则提示当前A类人数据更新成功,返回0的操作人则提示当前任务已经被捞单人员处理过了,无须在处理。同理B类人也是这样。

2.2 使用版本来实现乐观锁

相比于2.1 要在任务表添加一个字段version,因为并不是所有业务场景都会有一个状态枚举值来做乐观控制

id

comment

status

version

1

123456

new

1

如图初始化版本号为1,这时候: 对于A类人来说更新使用: update 表 set comment='',status='operator',version=version+1 where version = 1 and id = 1; 对应B类型来说更新使用: update 表 set comment='',status='manager',version=version+1 where version = 2 and id = 1;

三、 实战演练

3.1场景介绍

  • 概念模型

image.png

如图,一个合同基本信息对应多个审批任务

  • 审批流程

image.png

如图三级审批,假设三级审批都是捞单角色。只有三级都审批通过后合同基本信息的状态才是审批结束,只有一个审批节点的人审批驳回后,合同基本信息状态才是驳回状态,只有申请人撤回了申请,当前状态才是撤回。其他状态下都是审批中状态,也就是说即使一级,二级审批通过了,当前合同基本信息状态是审批中状态。

所以由于一级二级审批时候当前状态都是审批中,所以没办法用2.1的方式,所以使用version的方式。

  • 问题与解决

__ 问题一__ 首先审批人都有自己的审批列表,对应一个审批任务来说,假如一级审批有两个人A和B,那么A和B打开自己的审批列表时候都会看到一个审批任务如下,都一个审批按钮,单击审批按钮就会进入审批页面

image.png

考虑A和B都看到了同一个审批任务,其中A单击了审批按钮,进入了审批页面,并且审批了该任务A任务状态从new->done,取消了其他捞单任务B的任务状态new->cancel。但是此时B的审批列表里面该任务还是处于审批状态,因为他没有刷新页面,假如这时候B单击审批时候如果不做任何处理将会出现问题,所以在进入审批页面时候还需要再次校验下B的任务当前状态是否还是new。

下面在说下A和B同时进入审批页面后,A审批后,那么B在审批如何正常处理。 考虑在A和B进入页面时候去合同基本信息里面根据id获取当前version然后把version加密后的值encversion存在前端审批页面,当审批时候在使用该version进行乐观锁控制。 update 表 set version=version+1,.... where id = *,version = encversion; 这样两个人同时审批时候只有一个人能审批成功。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沃趣科技

基于Prometheus的数据库监控

作者 金 戈 沃趣科技技术专家 传统监控系统面临的问题 Prometheus的前身:Borgmon Borgmon介绍 应用埋点 服务发现 指标采集与堆叠 ...

756100
来自专栏云计算

基于Karma构建微服务

“微服务”和“微服务架构”在开发社者区中是一个热门话题,但实际中的微服务例子仍然很少。通过简要介绍一下我们在Karma上构建的后端API可会对现在的情况有所帮助...

12650
来自专栏程序员的知识天地

为何Node.js 能成为 Web 应用开发最佳选择?【强推理由】

一项颠覆性的技术进入技术市场总会带来一阵震惊,但随之而来往往是被放弃。然而,Node.js 当然不是这样的情况,它是一个开源的、跨平台的基于 Chrome 的 ...

16410
来自专栏服务端技术杂谈

初页CTO丁乐:分布式架构

初页现有架构 首先介绍一下初页目前的架构。它主要由计算服务和后面的运维与运营系统组成。 ? 计算服务由passport、works(作品服务)、social、m...

30540
来自专栏技巅

docker解决数据存储问题的方案

26370
来自专栏运维一切

为什么我们不能使用KUBERNETES 原

kubernetes的服务发现到node创建启动,最终到提供服务,中间都离不开iptable的nat模块,在业务高访问量的情况下,这是无法满足性能要求的。

8620
来自专栏IT技术精选文摘

高并发大容量NoSQL解决方案探索

17130
来自专栏Java技术交流群809340374

最新鲜的美团现场面试41题(三面技术+HR面):Redis+Kafka+分布式

互联网特别是电商平台,阿里双11秒杀、还有12306春运抢票、以及平时各种节假日抢购活动等,都是典型的高并发场景。

43200
来自专栏原创

高并发大容量NoSQL解决方案探索

19180
来自专栏非著名程序员

绝对干货:供个人开发者赚钱免费使用的一些好的API接口

不久前,我写了一篇文章,名为《科普技术贴:个人开发者的那些赚钱方式》,讲了一些个人开发者接私活和自己做软件加广告的一些科普知识。可是做软件,需要服务器,需要后台...

46890

扫码关注云+社区

领取腾讯云代金券