单个数据库上的分布式事务处理(SpringBoot、JMS、JPA)

问题描述 投票:0回答:1

我有一个设置,可以通过添加侦听 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 服务器)。

spring-boot spring-data-jpa jms jta distributed-transactions
1个回答
0
投票

由于同一作业的每个任务部分都在其自己的线程甚至不同的 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 的所有指令标记为计划并提交。然后,您有一个计划作业以相反的顺序执行所有计划的回滚指令。 这不是一个简单的方法,您很可能需要一些锁定机制,一旦任务失败,其他任务应该停止,但这是可行的。

也许更好的方法是拥有一个重复的架构,并在作业标记为已完成后复制数据。

无论如何,完整的解决方案将取决于您自己的许多用例。

希望这些想法能给你一个起点。

© www.soinside.com 2019 - 2024. All rights reserved.