我有一个设置,可以通过添加侦听 JMS 队列的节点来扩展该设置。 所有资源(节点)写入同一个数据库,并并行处理一个或多个“作业”。
Job A --> Queue1 --> Sub-Task A.1 --> Queue 2 --> Resource 1
Sub-Task A.2 --> Queue 2 --> Resource 2
Sub-Task A.n --> Queue 2 --> Resource n
Job B --> Queue1 --> Sub-Task B.1 --> Queue 2 --> Resource 1
Sub-Task B.2 --> Queue 2 --> Resource 3
Sub-Task B.n --> Queue 2 --> Resource n
每个资源都在相同的数据库和表上执行 CRUD 操作,当前在自己的 JMS 和 JPA 事务中。
如果子任务 A.n 中发生错误,我需要回滚之前对作业 A 所做的所有更改,但不需要回滚对作业 B 所做的更改。即使子任务通过其“作业”相关,但在执行过程中它们彼此独立,可以并行执行。
我正在寻找一个框架或模式,允许回滚作业 A 中完成的所有数据库事务。
我正在使用带有 Hibernate/JPA 和 Active MQ Artemis 的 SpringBoot 命令行应用程序(不涉及 Web 服务器)。
由于同一作业的每个任务部分都在其自己的线程甚至不同的 JVM 中运行,因此当任务 A.2 失败时,无法开箱即用地回滚任务 A.1 已完成的操作。 您必须根据您的具体业务规则手动实施此操作。我这样做的方法是有一个
rollback
表,其结构如下(不完全准确,但旨在给您一个想法)
CREATE TABLE IF NOT EXISTS rollback_instructions(
id BIGSERIALL PRIMARY KEY,
jms_message_id VARCHAR(64),
job_id VARCHAR(10),
task_id INTEGER,
rollback_sequence NUMBER,
rollback_command CLOB,
scheduled boolean,
executed boolean
);
每个任务都应该负责按照其完成的顺序填充数据库更改的回滚命令。如果任务提交,则 rollback_instruction 也提交。如果任务出现问题,则会将来自该 jms_message_id 的所有指令标记为计划并提交。然后,您有一个计划作业以相反的顺序执行所有计划的回滚指令。 这不是一个简单的方法,您很可能需要一些锁定机制,一旦任务失败,其他任务应该停止,但这是可行的。
也许更好的方法是拥有一个重复的架构,并在作业标记为已完成后复制数据。
无论如何,完整的解决方案将取决于您自己的许多用例。
希望这些想法能给你一个起点。