如何在多个JVM上运行的spring应用程序中启用事务管理

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

我从最近几个月开始使用Spring框架。我有一个关于事务管理器如何在以下场景中工作的问题。

场景:我正在进行一个Spring批处理,其中ItemReader多次调用下面的方法。此方法从“STUDENTS”表中获取状态为“NOT COMPLETED”的记录列表,并将这些记录的状态更新为“IN PROGRESS”。我正在处理1000万条记录,因此我计划使用多个线程和多个JVM来执行我的批处理。

解决方案到目前为止已实现:我已使此方法同步,以确保在给定时间只有单个线程获取记录,因此没有两个线程将尝试获取相同的“NOT COMPLETED”记录。还添加了@Transactional,以便在此方法中出现任何问题时,spring将回滚更改。

问题:事务管理如何使用多个JVM访问一个数据库?如果我正在运行我的应用程序的2-3个实例,那么如何确保这些实例不会尝试获取状态为“未完成”的相同记录?春天有这个功能吗?

@Transactional
public synchronized List<Student> processStudentRecords(){
List<Student> students = getNotCompletedRecords();
if(null != students && students.size() > 0){
    updateStatusToInProgress(students);
}
return student;
}
spring spring-batch spring-transactions distributed-transactions
1个回答
0
投票

要具体解决您的问题:

  1. 不要在Spring Batch使用的组件上使用@Transactional。 Spring Batch管理事务,并且该注释的使用将导致问题。
  2. 要使用流程指示器标志(正如您所建议的那样),您需要在选择之前进行更新。 select应仅查询可用于处理的标记的记录。

但是,上述内容并未解决多个JVM的问题。我假设您在跨多个JVM的处理中使用某种远程分区。如果是这种情况,您的更新查询将类似于UPDATE STUDENTS SET FLAG = 'NOT COMPLETE' WHERE ID > ? AND FLAG IS NULL LIMIT 100,其中ID是分区范围的起点,100是您的块大小。

标记行后,ItemReader可以通过SELECT * FROM STUDENT WHERE ID > ? AND FLAG = 'NOT COMPLETE'查询,其中ID是分区范围的开头。

上述技术允许您扩展到多个JVM,同时保留可重启性等内容。

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