我需要设计一个分布式系统,调度程序将任务发送给多个节点中的工作人员。每个任务都分配了一个id,并且可以由调度程序安排多次执行(通常每小时一次)。
我唯一的要求是具有特定id的任务不应该由群集同时执行两次。我可以想到一个设计,其中调度程序为每个任务id保存一个锁,并将任务发送给适当的worker。工作人员完成后,应释放锁定,并且调度程序可能会再次安排锁定。
我的设计应包含哪些内容以确保这一点。我担心将任务发送给启动任务但未能通知调度程序的工作人员的情况。
在这种情况下,确保一次只执行一个作业的单个实例的最佳做法是什么?
答案 0 :(得分:1)
您可以使用实现共识协议的解决方案。比如说 - 集群中的所有节点都可以使用Raft protocol进行通信。因此,每当节点X想要开始处理任务Y时,它将尝试提交消息X starts working on Y
。将此类消息提交到日志后,所有节点将以相同的顺序查看日志中的所有消息。
当节点X完成或中止任务时,它将尝试提交X no longer works on Y
,以便另一个节点可以开始/继续处理它。
可能会发生两个节点(X和Z)可能同时尝试提交 start 消息,然后日志看起来像这样:
...
N-1: ...
N+0: "X starts working on Y"
...
N+k: "Z starts working on Y"
...
但由于N + 0和N + k条目之间没有X no longer works on Y
消息,所以每个节点(包括Z)都知道Z不能在Y上开始工作。
唯一剩下的问题是,如果节点X在集群中尝试提交X no longer works on Y
之前已经从集群中进行了分区,我相信没有完美的解决方案。
解决方法可能是X会尝试定期提交消息X still works on Y at time T
,如果在某个阈值持续时间内没有将此类消息提交给日志,则群集会认为没有人正在处理该任务了。
然而,通过这种解决方法,您将允许两个或更多节点在同一任务上工作的可能性(分区节点X和一些在超时后接收任务的新节点)。
答案 1 :(得分:0)
经过彻底的搜索,我得出的结论是,这个问题可以通过一个名为fencing的方法来解决。
实质上,当您怀疑节点(工作者)失败时,确保它不会破坏系统其余部分的唯一方法是提供一个阻止节点访问您需要的共享资源的栅栏。保护。这必须是一个激进的方法,如重置运行失败进程的计算机或设置防止进程访问共享资源的防火墙规则。一旦围栏到位,您就可以安全地打破失败流程所持有的锁定并开始新流程。