我有一个分布式作业调度程序,运行在三台机器上,从数据库中选择事件(弹性搜索)。
我面临的问题是,有时所有节点都会选择相同的事件。这是对系统资源的不必要负载。
我想要做的是实现一种机制,这样作为分布式调度程序一部分的每个节点都应该选择唯一的事件。
我现正探讨以下方案:
有人能帮我朝着正确的方向前进吗?
发布于 2021-08-18 07:20:26
使用后端存储作业没有错,但如果事务数量很高(> 1k tps),则可能成为瓶颈。
对于分布式调度,您需要解决两件事:
要用典型的后端轻松地解决这两个问题,您可以添加两个字段:
State :: { PENDING, WORKING, DONE }
LastUpdate :: DateTime要解决前一个问题,您必须原子地查询和更新一个PENDING记录(即在同一个事务中):
@Transactional
public Optional<Task> getTaskToWorkOnIfAny() {
Optional<Task> task = myBackend.getOnePendingTask();
if(task.isPresent())
// update task, I'm working on it!
myBackend.updateTask(task.get(), WORKING, new DateTime());
return task;
}然后,像往常一样努力去做。
要解决后一个问题,只需检查任务是否WORKING时间过长(如果任务很长,可以添加ping更新字段)。
如果任务失败,是否应该编写try/catch将WORKING移动到PENDING。当然可以,但是如果系统真的崩溃了,那么您的任务将是WORKING,所以您应该遵循我以前的策略。
注意:要考虑整个问题,您只需遵循前面的代码,其中getTaskToWorkOnIfAny类似于SELECT * FROM task WHERE state = 'PENDING' OR (state = 'WORKING' AND lastUpdate < yesterday()。没别的了。
https://stackoverflow.com/questions/68827919
复制相似问题