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

a11xaf1n  于 12个月前  发布在  Spring
关注(0)|答案(1)|浏览(112)

我有一个可以通过添加监听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回滚。
我正在使用一个SpringBoot命令行应用程序(不涉及Web服务器)与Hibernate/JPA和ActiveMQ Artemis。

hxzsmxv2

hxzsmxv21#

由于同一作业的每个任务部分都运行在自己的线程中,甚至是不同的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中的所有指令标记为已调度并提交。然后,您有一个计划作业,以与它们的顺序相反的顺序执行所有计划的回滚指令。这不是一个简单的方法,你很可能需要一些锁定机制,一旦一个任务失败,其他任务应该停止,但这是可行的。
也许更好的方法是拥有一个副本模式,并在作业标记为完成后复制数据。
无论如何,一个完整的解决方案将取决于你自己的许多用例。
希望这些想法能给你一个蓬特。

相关问题