Java - Cron 作业 - 如果一个实例触发批处理作业,则阻止其他实例执行相同的操作

Java - Cron job - if an instance triggers a batch job, prevent other instance from doing the same

我在两个实例上有一个应用程序 运行,实例之间的唯一通信是它们在单个数据库上运行。我上面几乎没有批处理作业 运行。例如:将记录从数据库复制到一个文件,并将该文件传送到服务器。由于这两个实例都有一个公共数据库,我正在尝试写入 table 作业已被触发。基本上,触发条件是在给定 table 上不存在这样的记录。我如何以原子方式执行此操作,即检查 table 该作业尚未被触发,然后插入 table?

悲观锁定在这里可以提供帮助:

  • 创建一个专用的table保存锁记录,最后执行时间
  • 在预定的执行中,获取(或创建)在注入的 EntityManagerLockModeType.PESSIMISTIC_WRITE 上的锁定记录。
  • 检查锁定记录上的执行时间:如果它是最近更新的,则作业必须已经运行在另一个实例上
  • 否则,执行作业,之后更新锁记录上的最后执行时间。

有关选项的更多详细信息,请参见Lock Modes (Java EE Tutorial)

这种锁定机制的示例应用:Liquibase 的 DATABASECHANGELOGLOCK table,记录在案 here

如果您有一个需要启动的计划任务,例如,每 15 秒一次,并且应该只在单个应用程序实例上 运行,那么您可以使用 ShedLock

这是一个非常简单的机制,基本上与您提到的相同 - 创建一个 table(实际上,您需要创建一次)并定期为其获取锁。您可以设置锁定时间和其他一些东西。

与 SQL 和 NoSQL 数据库一起工作,例如 Postgres 和 Mongo,并且只需要一个注释 @SchedulerLock。见下文:

    @Scheduled(fixedRateString = "PT15S")
    @SchedulerLock(name = "copy_records")
    public void copyRecords()
    {
        // do smth on a single instance of an app only
    }