Spring Shedlock 不保证同步

Spring Shedlock does not ensure synchronization

我有以下在多个实例中运行的计划作业。

@Scheduled(fixedRate = 10000)
@SchedulerLock(name = "AwesomeJob", lockAtLeastForString = "5S", lockAtMostForString = "5S")
public void awesomeJob() throws InterruptedException {

    for (int i = 0; i < 5; i++) {
        log.info("Processing {}", i);
        Thread.sleep(100000L);
    }
}

我知道如果任务花费的时间比 lockAtMostFor 长,则结果行为可能无法预测。有没有办法通过使用 SimpleLock.extend 方法来避免这种行为?我正在使用 JdbcLockProvider。我从 https://github.com/lukas-krecan/ShedLock/issues/151 得到这个想法。

interface LockService {
   bool aquireLock(String lockKey, String value);
   bool releaseLock(String lockKey);
}

interface SomeService {
   void do();
}

class Scheduler{
    @AutoWired LockService lockService;
    @Autowired SomeService someService;
    @Scheduled(fixedRate = 10000)
    public void awesomeJob() throws InterruptedException {
      if(lockService.aquireLock("awesomeJob", serverId) ){
        try{
           //call service method 
            someService.do();
        }catch( Exception e ){
          //TODO
        }finally{
          lockService.releaseLock("awesomeJob");
        }
      }   
    }
}

你可以像这个例子一样有一个锁,实现一个锁接口,为给定的服务提供锁。一旦你有 LockService 使用它来限制函数 运行。

唯一的问题是您需要将此代码块添加到所有函数中。如果您不想将此代码块添加到所有函数,请添加一个基于注释的 AOP 处理程序。

另外,如果获得锁的服务器挂掉了怎么办?我们需要在锁值中设置每把锁的最大过期时间或者使用时间来识别是什么时候加的,根据锁时间判断是否可以运行。

最简单的方法是将 lockAtMostFor 设置为更高的值。当执行任务的节点死亡时,它只是一个安全网,所以这应该不是问题。

如果由于某种原因你不能这样做,你可以使用你提供的问题中描述的extend方法。但这意味着您必须手动管理锁。当前没有允许扩展使用 AOP 自动创建的锁的功能。