NTP /中断如何影响定时器?

时间:2017-11-19 23:05:35

标签: java time ntp

我有一个循环,A,每n秒运行一次(可能大概是.5或1秒左右)。我有另一项任务B,大约每5n秒发生一次,但此任务发生在完全独立的环境和服务器中。

我需要确保任务A在任务B发生之间至少发生一次。但是,我担心以下情况:

  • NTP调整弄乱了任一服务器上的时间。
  • 中断或GC运行并减慢任务A,延迟执行。

有没有办法解决这些潜在的失败点?

这些将在Java中实现,但我认为它与语言无关。

1 个答案:

答案 0 :(得分:0)

如果在没有使用协调服务的情况下未运行任务A,则无法保证任务B不会执行。除了时钟偏差和过程暂停的问题之外,还有其他问题可能会发生。如果任务A因硬件/资源错误而失败,会发生什么?服务重启怎么样?

最简单的解决方法是让任务B容忍任务A未运行的情况。如果你不能这样做,那么你将不得不提供一项服务来跟踪任务A的状态。实现这一点的最轻的方法是用唯一的ID发出每次A的运行并在运行B之前检查它。

类似的东西:

public class TaskA implements Runnable {
    @Resource
    private TaskService taskService;

    @Override
    public void run() {
        // Run task A
        // ...

        // Set run ID for task B to retrieve
        taskService.setRunId("A", UUID.randomUUID().toString());
    }
}

public class TaskB implements Runnable {
    private static final Logger log = LoggerFactory.getLogger(TaskB.class);

    @Resource
    private TaskService taskService;

    private String lastId;

    @Override
    public void run() {
        String nextId = taskService.getRunId("A");
        if (this.lastId == null) {
            log.info("First run. Not executing");
        } else if (lastId.equals(nextId)) {
            log.warn("Task A has not run. Refusing to execute");
        } else {
            log.info("Executing");
            // Run task B
            // ...
        }
        this.lastId = nextId;
    }
}

我在上面的示例中使用了UUID,以避免需要持久存储来保证唯一ID。如果您在环境中有数据库,则可以使用该数据库。由于你注意到的原因(时钟偏差等),我会避免使用时间戳。