Spring 与另一个实例同步保存到数据库

Spring synchronize saving to database with another instances

我有 2 个 Spring 引导应用程序实例,我正在使用 spring JPA。 Cron scheduler 运行 方法每隔一小时 首先,检查记录是否已更新,如果已更新,则应跳过且不更新,但无论如何都会在两个实例上更新。 如何实现,类似synchronized,只允许在完成某事时读取?

@Scheduled(cron = "0 0 * * * ?", zone = "Europe/Paris")
public void updateServers() {
    applicationServerRepository.findAll().forEach(this::updateServerInfo);
}

请更详细准确的解释问题。 但据我了解,您应该:

  • 或 运行 仅在一个实例中执行 cron 作业。 (回到 90 年代,我们是“手动”完成的,但是 spring-boot-profiles 在这里提供了很好的机会:用 @Profile("cronFooBar")激活/添加仅在一个实例上。)

  • 或者,如果您还希望 cron 作业“负载平衡”,那么您应该想办法 synchronize/lock。 (可能最好 in updateServerInfoupdateServers。(更多细节!? ..我相信这两个实例至少会找到“要锁定的对象”数据库(table,行,..)))

作为 /found on internet,使用“小设置”(并丢弃石英!),您可以对此进行方便的注释,例如:

@SchedulerLock(name = "...", 
  lockAtLeastForString = "...", lockAtMostForString = "...")

但我想,使用 spring-data-jpa(仅 & quartz)资源也是可能的,例如:

  1. 添加(悲观)锁定:

    interface ApplicationServerRepository ... {
    
      @Lock(LockModeType.PESSIMISTIC_READ)
      @Query("select as from ApplicationService ...")
      findAllForCron();
      ...
    }
    
  2. 抓住它:

    @Scheduled(cron = "0 0 * * * ?", zone = "Europe/Paris")
    public void updateServers() {
      try {
        applicationServerRepository
        .findAllForCron()
        .forEach(this::updateServerInfo);
      ​}
      catch​ (javax.persistence.PessimisticLockException plex) {
        logger.info("i get some coffee");
        return;
      }
    }