【问题标题】:Spring synchronize saving to database with another instancesSpring将保存到数据库与另一个实例同步
【发布时间】:2021-12-27 11:32:38
【问题描述】:

我的 Spring Boot 应用程序有 2 个实例,我正在使用 Spring JPA。 cron 调度程序每隔一小时运行一次的方法 首先,检查记录是否已更新,如果已更新,则应跳过并且不更新,但无论如何它在两个实例上都已更新。 如何实现,比如同步,只允许在完成某事时读取?

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

【问题讨论】:

    标签: spring-boot hibernate jpa spring-data-jpa spring-data


    【解决方案1】:

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

    • 或者只在一个实例中运行 cron 作业。 (早在 90 年代,我们是“手动”完成的,但 spring-boot-profiles 在这里提供了很好的机会:用 @Profile("cronFooBar") 装饰“所有@scheduled beans”(重构!?),然后激活 /添加它只在一个实例上。)

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

    作为proposed by Erkan/found on internet,使用“少量设置”(并丢弃石英!),您可以为此提供方便的注释,例如:

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

    但我想,也可以使用 spring-data-jpa(仅和石英)资源,例如:

    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;
        }
      }
      

    【讨论】:

    • 你明白这个问题。我想锁定我的对象(ApplicationServer)。将首先访问它的实例,它给出像“已经更新”这样的前缀。另一个实例应该访问,并看到它有这个前缀,然后跳过。但是,我不知道如何正确锁定它,不幸的是,有 2 个实例正在更新,因为它同时在运行。
    • 好的...但是“ApplicationServer”是两个对象(在两个实例上..在 spring-boot 中!;)
    • 它是如何工作的: - 首先访问的实例,从数据库中获取对象(ApplicationServer)。 - 用一些值和前缀值更新它(“已经更新) - 将其保存到数据库中。我希望将此记录锁定在数据库中,以防止另一个实例同时更新它。
    • 如果我在调度程序中为另一个实例添加一些延迟,它会像预期的那样工作,但只想找到一个解决方案,如何完美锁定这条记录。
    • 我们使用 shedlock 进行锁定,以便在多个实例中运行一次。
    猜你喜欢
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2022-06-16
    • 2014-09-17
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    相关资源
    最近更新 更多