camunda流程引擎事务管理和乐观锁

本文重点介绍camunda开源流程引擎的事务配置,以及在高并发多线程情况下,可能会发生多个线程尝试对相同流程实例数据进行更改的情况Camunda如何通过数据库的乐观锁解决这种并发冲突的,并介绍了乐观锁和悲观锁的适用场景、性能影响等。

1、camunda流程引擎事务配置

camunda流程引擎可以配置为与事务管理器(或事务管理系统)集成。该流程引擎开箱即用,支持与 Spring 和 JTA 事务管理集成。

如果你使用的是springboot框架,事务的配置更加简单,只需要配置:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

Spring Boot 为我们提供了默认的事务管理器,当我们使用了 spring-boot-starter-jdbc 的启动器时,框架会自动注入 DataSourceTransactionManager 管理器。只需要在启动类上使用@EnableTransactionManagement注解来开启注解事务,即可不需要任何额外配置就可以用 @Transactional 注解进行事务的使用。但是当我们自己配置了事务管理器的时候,Spring Boot 将不再提供事务管理,而是使用我们定义的事务管理器。

1.1、事务和流程引擎上下文

当执行流程引擎命令时,引擎将创建流程引擎上下文。Context 会缓存数据库实体,因此对同一实体的多个操作不会导致多次数据库查询。这也意味着对这些实体的更改会被累积,并在命令返回后立即刷新到数据库。但需要注意的是,当前事务可能会在稍后时间提交。

如果一个流程引擎命令嵌套在另一个命令中,即一个命令在另一个命令中执行,则默认行为是重用现有的流程引擎上下文。这意味着嵌套命令将有权访问相同的缓存实体以及对它们所做的更改。

当嵌套的Command要在新的事务中执行时,需要创建一个新的流程引擎上下文来执行它。在这种情况下,嵌套命令将为数据库实体使用新的缓存,独立于先前(外部)命令缓存。这意味着,一个命令的缓存中的更改对另一个命令不可见,反之亦然。当嵌套命令返回时,更改将独立于外部命令的流程引擎上下文而刷新到数据库。

3、乐观锁

Camunda 引擎可用于多线程应用程序。在这样的设置中,当多个线程同时与流程引擎交互时,可能会发生这些线程尝试对相同数据进行更改的情况。例如:两个线程尝试同时(并发)完成相同的用户任务。这样的情况就是冲突:任务只能完成一次。

Camunda 引擎使用一种名为“乐观锁定”(或乐观并发控制)的众所周知的技术来检测和解决此类情况。

本节分为两部分:第一部分介绍乐观锁的概念。第二部分解释了Camunda中乐观锁的用法。

3.1、什么是乐观锁?

乐观锁定(也称为乐观并发控制)是一种并发控制方法,用于基于事务的系统。在数据读取频率高于更改频率的情况下,乐观锁定最为有效。许多线程可以同时读取相同的数据对象,而不会相互排斥。然后,通过检测冲突并防止在多个线程尝试同时更改相同数据对象的情况下进行更新来确保一致性。如果检测到此类冲突,则可以确保只有一个更新成功,而所有其他更新都会失败。

举例说明:假设我们有一个包含以下条目的数据库表:

ID

版本

姓名

地址

……

8

1

史蒂夫

令牌城Workflow大道3号

……

……

……

……

……

……

上表显示单行保存用户数据。用户拥有唯一的 ID(主键)、版本、名称和当前地址。

我们现在构建一种情况,其中有 2 个事务尝试更新此条目,一个事务尝试更改地址,另一个事务尝试删除用户。预期的行为是,一旦一个事务成功,另一个事务就会中止,并出现错误,表明检测到并发冲突。然后,用户可以根据数据的最新状态决定重试交易:

如上图所示,Transaction 1读取用户数据,对数据执行某些操作,删除用户,然后提交。 Transaction 2同时启动并读取相同的用户数据,并且也对数据进行操作。当Transaction 2尝试更新用户地址时,检测到冲突(因为Transaction 1已经删除了用户)。

检测到冲突是因为Transaction 2执行更新时读取用户数据的当前状态。此时并发Transaction 1已经标记了要删除的行。数据库现在等待Transaction 1结束。结束后Transaction 2即可继续。此时,该行不再存在,更新成功,但报告已更改0行。应用程序可以对此做出反应并回滚,Transaction 2以防止该事务所做的其他更改生效。

应用程序(或使用它的用户)可以进一步决定是否Transaction 2应该重试。在我们的示例中,交易将找不到用户数据并报告用户已被删除。

乐观锁与悲观锁

悲观锁与读锁一起使用。读锁会在读取时锁定数据对象,从而防止其他并发事务也读取该数据对象。这样,就可以避免冲突的发生。

在上面的示例中,Transaction 1一旦读取用户数据就会锁定它。当尝试阅读时,也会Transaction 2被阻碍而无法取得进展。完成后Transaction 1Transaction 2可以继续并读取最新状态。这样可以防止冲突,因为事务始终只针对最新的数据状态进行工作。

在写入与读取一样频繁且竞争激烈的情况下,悲观锁定非常有效。

但是,由于悲观锁是独占的,因此并发性会降低,从而降低性能。因此,乐观锁定检测冲突而不是阻止冲突发生,因此在高并发级别以及读取比写入更频繁的情况下更可取。此外,悲观锁会很快导致死锁。

3.2、Camunda 中的乐观锁

Camunda 使用乐观锁进行并发控制。如果检测到并发冲突,则会引发异常并回滚事务。执行UPDATEDELETE语句时会检测到冲突。执行删除或更新语句会返回受影响的行数。如果该计数等于 0,则表明该行之前已被更新或删除。在这种情况下,会检测到冲突并OptimisticLockingException引发冲突。

3.2.1、Camunda 实现乐观锁的细节

大多数 Camunda Engine 数据库表都包含一个名为 的列REV_。此列代表修订版本。读取一行时,会按给定的“修订版”读取数据。修改(更新和删除)始终尝试更新当前命令读取的修订版本。更新增加修订版。执行修改语句后,将检查受影响的行数。如果计数为,1则推断执行修改时读取的版本仍然是当前版本。如果受影响的行数为0,则其他事务在该事务运行时修改了相同的数据。这意味着检测到并发冲突,并且不得允许该事务提交。随后,事务被回滚(或标记为仅回滚)并且OptimisticLockingException被抛出。

3.2.2、乐观锁定异常

可以OptimisticLockingException通过 API 方法抛出。考虑该completeTask(...)方法的以下调用:

taskService.completeTask(aTaskId); // may throw OptimisticLockingException

OptimisticLockingException如果执行方法调用导致数据并发修改,则上述方法可能会抛出异常。

作业执行也可能导致OptimisticLockingException抛出异常。由于这是预期的,因此将重试执行。

3.2.3、处理乐观锁异常

如果当前命令由作业执行器触发,OptimisticLockingException则会使用重试自动处理。由于预计会发生此异常,因此它不会减少重试计数。

如果当前Command是由外部API调用触发的,Camunda引擎会将当前事务回滚到最后一个保存点(等待状态)。现在用户必须决定如何处理异常,是否应该重试事务。还要考虑到,即使事务被回滚,它也可能具有尚未回滚的非事务副作用。

为了控制事务的范围,可以使用异步延续在活动之前和之后添加显式保存点。

3.2.4、引发乐观锁异常的常见位置

有一些常见的地方OptimisticLockingException可以扔。例如

  • 竞争性外部请求:同时完成同一任务两次。
  • 进程内的同步点:例如并行网关、多实例等。

以下模型显示了可以发生这种情况的并行网关OptimisticLockingException

打开并行网关后有两个用户任务。在用户执行任务之后,关闭并行网关将执行合并为一个。在大多数情况下,其中一项用户任务将首先完成。然后,执行等待正在关闭的并行网关,直到第二个用户任务完成。

然而,两个用户任务也有可能同时完成。假设上面的用户任务已经完成。该交易假设他是第一个关闭并行网关的人。下面的用户任务是并发完成的,并且事务还假设他是关闭并行网关上的第一个。两个事务都尝试更新一行,这表明它们是正在关闭的并行网关上的第一个事务。在这种情况下,OptimisticLockingException会抛出一个异常。其中一个事务已回滚,另一个事务成功更新该行。

3.2.5、乐观锁定和非事务副作用

发生后OptimisticLockingException,事务将回滚。任何事务性工作都将被撤消。非事务性工作(例如创建文件或调用非事务性 Web 服务的效果)将无法撤消。这可能会导致不一致的状态。

此问题有多种解决方案,最常见的解决方案是使用重试进行最终整合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/475599.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】数9的个数

编写程序数一下 1到 100 的所有整数中出现多少个数字9 1&#xff0c;首先产生1~100的数字。然猴设法得到数9个数&#xff0c;例如个位&#xff1a;19%109&#xff0c;十位&#xff1a;91/109。 2&#xff0c;每次得到数九的时候&#xff0c;就用一个变量来进行计数。 代码如…

【项目笔记】java微服务:黑马头条(day04)

文章目录 自媒体文章-自动审核1)自媒体文章自动审核流程2)内容安全第三方接口2.1)概述2.2)准备工作2.3)文本内容审核接口2.4)图片审核接口2.5)项目集成 3)app端文章保存接口3.1)表结构说明3.2)分布式id3.3)思路分析3.4)feign接口 4)自媒体文章自动审核功能实现4.1)表结构说明4.…

搭建ELK+minio及配置

什么是ELK ELK是一种基于开源工具的日志管理和数据分析解决方案&#xff0c;它由三个核心组件组成&#xff1a; Elasticsearch&#xff1a;用于存储、搜索和分析大规模数据的分布式搜索引擎。Logstash&#xff1a;用于收集、过滤、转换和发送日志数据的数据处理管道。Kibana&…

mysql虚拟列Generated Column

目录​​​​​​​ 1、Generated Column简介 生成的列定义具有以下语法&#xff1a; 2、实践 2.1 存储格式为json字段增加索引 2.2 手机号后四位 3、虚拟列索引介绍 3.1 虚拟列索引的限制 3.1.1 Virtal Generated Column 4、阿里云数据库环境是否支持 下期扩展&…

通过 Socket 手动实现 HTTP 协议

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

使用Oxygen编辑器的项目来做团队协作

▲ 搜索“大龙谈智能内容”关注公众号▲ 扫码见我视频号上的视频 今天&#xff0c;分享一种在Oxygen中使用项目文件进行团队协作的高效方法。这种方法不仅能帮助我们轻松共享文件和文件夹&#xff0c;还能确保团队成员使用统一的项目级别选项和发布配置&#xff0c;从而提高工…

【Git】第二课:git安装和配置

安装 我们伟大祖国有句古话叫巧妇难为无米之炊&#xff0c;还有句话叫工欲善其事必先利其器。所以&#xff0c;在正式的学习之前&#xff0c;我们需要先把git这把利器安装好。 Windows系统 下载安装包 打开Git - Downloading Package页面&#xff0c;根据系统类型32位还是6…

有ai写文案的工具吗?分享5款好用的工具!

在数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;已渗透到我们生活的方方面面&#xff0c;包括内容创作领域。AI写文案的软件以其高效、便捷的特点&#xff0c;正逐渐受到广大内容创作者、营销人员、甚至普通用户的青睐。本文将为您盘点几款热门的AI写文案软件&…

Flume入门概述及安装部署

目录 一、Flume概述1.1 Flume定义1.2 Flume基础架构 二、Flume安装部署 一、Flume概述 1.1 Flume定义 Flume是Cloudera提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统。Flume基于流式架构&#xff0c;灵活简单。 1.2 Flume基础…

粒子群算法 - 目标函数最优解计算

粒子群算法概念 粒子群算法 (particle swarm optimization&#xff0c;PSO) 由 Kennedy 和 Eberhart 在 1995 年提出&#xff0c;该算法模拟鸟群觅食的方法进行寻找最优解。基本思想&#xff1a;人们发现&#xff0c;鸟群觅食的方向由两个因素决定。第一个是自己当初飞过离食物…

windows查看局域网内所有已使用的IP IP扫描工具 扫描网段下所有的IP Windows环境下

推荐使用&#xff1a; Advanced IP Scanner 官网下载&#xff1a; https://www.advanced-ip-scanner.com/

动手做简易版俄罗斯方块

导读&#xff1a;让我们了解如何处理形状的旋转、行的消除以及游戏结束条件等控制因素。 目录 准备工作 游戏设计概述 构建游戏窗口 游戏方块设计 游戏板面设计 游戏控制与逻辑 行消除和计分 判断游戏结束 界面美化和增强体验 看看游戏效果 准备工作 在开始编码之前…

前端框架推荐 Arco Design

Arco Design - 企业级产品的完整设计和开发解决方案 预览地址&#xff1a;Arco Design Pro - 开箱即用的中台前端/设计解决方案 一 开发 有vue3、React版本。 文档地址&#xff1a;Arco Design - 企业级产品的完整设计和开发解决方案 还配有对应脚手架&#xff1a;GitHub -…

Scala--02--IDEA编写Hello World

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.Scala 插件安装1&#xff09;插件离线安装步骤2&#xff09; 插件在线安装&#xff08;推荐可选&#xff09; 2.HelloWorld 案例1&#xff09;打开 IDEA->点击…

刷题DAY27 | LeetCode 39-组合总和 40-组合总和II 131-分割回文串

39 组合总和&#xff08;medium&#xff09; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates…

4 CUDA 环境搭建

4.1 简介 本章面向从未接触过CUDA的初学者。我们将依次介绍如何在不同操作系统上安装CUDA、有哪些可用的CUDA 工具以及CUDA如何编译代码&#xff0c;最后介绍应用程序接口提供的错误处理手段&#xff0c;并帮助读者识别CUDA代码和开发过程中必然碰到的应用程序接口报错。Windo…

二、typescript基础语法

一、条件语句 二、函数 1、有名函数 function add(x:number, y:number):number {return x y;}2、匿名函数 let add function (x:number, y:number):number {return x y;}函数可选参数 function buildName(firstname: string, lastname?:string) {if (lastname) {return fi…

MT2492 16V输入 600KHz 2A DCDC同步降压转换器 航天民芯一级代理

深圳市润泽芯电子有限公司为航天民芯一级代理 描述 MT2492是一款完全集成的高效率产品2A同步整流降压变换器。MT2492在一段时间内高效运行宽输出电流负载范围。该设备提供两种工作模式&#xff0c;即PWM控制和PFM模式切换控制在更宽的工作范围内实现高效率加载。MT2492需要…

k8s系列之十四安装Istio

Istio 是一个开源的服务网格&#xff08;Service Mesh&#xff09;&#xff0c;用于连接、管理和保护微服务。它提供了一组功能强大的工具&#xff0c;包括流量管理、安全性、监控和跟踪等&#xff0c;以帮助在微服务架构中更好地管理服务之间的通信。 一些主要的 Istio 功能包…

【VTKExamples::Points】第五期 ExtractPointsDemo

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例ExtractPointsDemo,并解析接口vtkExtractPoints,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U…