技术交流28群

服务热线

135-6963-3175

微信服务号

activiti之事务子流程 更新时间 2022-3-23 浏览2531次

事务子流程介绍

事务子流程是内嵌子流程,可以用来把多个流程放到一个事务里。 事务是一个逻辑单元,可以把一些单独的节点放在一起,这样它们就可以一起成功或一起失败。

事务可能的结果 

事务可以有三种可能的结果:

1.事务成功,如果没有取消也没有因为问题终结。如果事务子流程是成功的, 就会使用外出顺序流继续执行。 如果流程后来抛出了一个补偿事件,成功的事务可能被补偿。

注意:和普通内嵌子流程一样,事务可能在成功后, 使用中间补偿事件进行补偿。

2.事务取消,如果流程到达取消结束事件。这时, 所有流程都会终结和删除。触发补偿的一个单独的流程,会通过取消边界事件继续执行。 在补偿完成之后,事务子流程会使用取消边界事务的外出顺序流向下执行。

3.事务被问题结束,如果抛出了一个错误事件, 而且没有在事务子流程中捕获。(如果错误被事务子流程的边界事件处理了,也会这样应用。) 这时,不会执行补偿。


与ACID事务的关系

一定不要吧bpmn事务子流程与技术(ACID)事务相混淆。 bpmn事务子流程不是技术事务领域的东西。要理解activiti中的事务管理,请参考 并发与事务。 bpmn事务和技术事务有以下不同点:


ACID事务一般是短期的,bpmn事务可能持续几小时,几天,甚至几个月才能完成。 (考虑事务中包含的节点可能有用户任务,一般人员响应的时间比应用时间要长。或者, 或者,在其他情况下,bpmn事务可能要等待发生一些事务事件,就像要根据某种次序执行。) 这种操作通常要相比更新数据库的一条数据,或把一条信息保存到事务性队列中,消耗更长的时间来完成。


因为不能在整个业务节点的过程中保持一个技术性的事务,所以bpmn事务一般要跨越多个ACID事务


因为bpmn事务会跨越多个ACID事务,所以会丧失ACID的特性。比如,考虑上述例子。 假设“约定旅店”和“刷信用卡”操作在单独的ACID事务中执行。 也假设“预定旅店”节点已经成功了。现在我们处于一个中间不稳定状态,因为我们预定了酒店,但是还没有刷信用卡。 现在,在一个ACID事务中,我们要依次执行不同的操作,也会有一个中间不稳定状态。 不同的是,这个中间状态对事务的外部是可见的。 比如,如果通过外部预定服务进行了预定,其他使用相同预定服务的部分就可以看到旅店被预定了。 这意味着实现业务事务时,我们完全失去了隔离属性 (注:我们也经常放弃隔离性,来为ACID事务获得更高的并发,但是我们可以完全控制,中间不稳定状态也只持续很短的时间)。


bpmn业务事务也不能使用通常的方式回滚。因为它跨越了多个事务,bpmn事务取消时一些ACID事务可能已经提交了。 这时,它们不能被回滚了。


因为bpmn事务实际上运行时间很长,缺乏隔离性和回滚机制都需要被区别对待。 实际上,这里也没有更好的办法在特定领域处理这些问题:

使用补偿执行回滚。如果事务范围抛出了取消事件,会影响已经执行成功的节点, 并使用补偿处理器执行补偿。

隔离性的缺乏通常使用特定领域的解决方法来解决。比如,上面的例子中, 一个旅店房间可能会展示给第二个客户,在我们确认第一个客户付费之前。 虽然这可能与业务预期不符,预定服务可能选择允许一些过度的预约。

另外,因为事务会因为风险而中断,预定服务必须处理这种情况,已经预定了旅店,但是一直没有付款的情况。 (因为事务被中断了)。这时预定服务需要选择一个策略,在旅店房间预定超过最大允许时间后, 如果还没有付款,预定就会取消。

综上所述:ACID处理的是通常问题(回滚,隔离级别和启发式结果),在实现业务事务时,我们需要找到特定领域的解决方案来处理这些问题。

目前的限制:

        bpmn规范要求流程引擎能根据底层事务的协议处理事件,比如如果底层协议触发了取消事件,事务就会取消。 作为内嵌引擎,activiti目前不支持这项功能。(对此造成的后果,可以参考下面的一致性讨论)。

        ACID事务顶层的一致性和优化并发: bpmn事务保证一致性,要么所有节点都成功,或者一些节点成功,对其他成功的节点进行补偿。 无论哪种方式,都会有一致性的结果。不过要讨论一些activiti内部的情况,bpmn事务的一致性模型是叠加在流程的一致性模型之上的。 activiti执行流程是事务性的。并发使用了乐观锁。在activiti中,bpmn错误,取消和补偿事件都建立在同样的acid事务与乐观锁之上。 比如,取消结束事件只能触发它实际到达的补偿。如果之前服务任务抛出了未声明的异常。或者, 补偿处理器的效果无法提交,如果底层的acid事务的参与者把事务设置成必须回滚。 或者当两个并发流程到达了取消结束事件,可能会触发两次补偿,并因为乐观锁异常失败。 所有这些都说明activiti中实现bpmn事务时,相同的规则也作用域普通的流程和子流程。 所以为了保证一致性,重要的是使用一种方式考虑实现乐观事务性的执行模型。