我有一个循环,A,每n
秒运行一次(可能大概是.5或1秒左右)。我有另一项任务B,大约每5n
秒发生一次,但此任务发生在完全独立的环境和服务器中。
我需要确保任务A在任务B发生之间至少发生一次。但是,我担心以下情况:
有没有办法解决这些潜在的失败点?
这些将在Java中实现,但我认为它与语言无关。
答案 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。如果您在环境中有数据库,则可以使用该数据库。由于你注意到的原因(时钟偏差等),我会避免使用时间戳。