Queue 如何在etcd中实现工作队列

Queue 如何在etcd中实现工作队列,queue,distributed,etcd,workload,Queue,Distributed,Etcd,Workload,我刚刚开始研究etcd,创作者在演讲中提到的一个用例是工作队列系统 但实际上,您将如何实现这一点 基本模式是这样的 1进程生成“工作描述票证”,并将该票证放在etcd文件夹中,例如“/queue/worktickets/0000000000 1/” 1->许多进程正在侦听“/queue/worktickets/”文件夹中的更改。 当出现新的工作通知单时,每个进程都会尝试通过在“/queue/locks/0000000 1”中创建一个新值来锁定该通知单来获取该通知单。只有第一个可以创建锁值 创建锁

我刚刚开始研究etcd,创作者在演讲中提到的一个用例是工作队列系统

但实际上,您将如何实现这一点

基本模式是这样的

1进程生成“工作描述票证”,并将该票证放在etcd文件夹中,例如“/queue/worktickets/0000000000 1/”

1->许多进程正在侦听“/queue/worktickets/”文件夹中的更改。 当出现新的工作通知单时,每个进程都会尝试通过在“/queue/locks/0000000 1”中创建一个新值来锁定该通知单来获取该通知单。只有第一个可以创建锁值

创建锁票证的进程完成了它的工作,然后从队列中删除票证,可能还有锁值。然后尝试从队列中获取下一张可用的票证。如果没有可用的工单,请再次开始侦听“/queue/worktickets/”文件夹中的更改

在我看来,这应该很容易实现,但如果队列变大(票据很容易生成,但很难处理),那么似乎会有大量数据从etcd传输到每个客户机。 据我所知,没有办法说“给我该文件夹中不存在的第一个值”,也没有办法说“给我该文件夹中的前n个项目”


任何人都愿意分享他们在这方面的想法

我想您已经解决了这个问题,但我要做的是列出工作队列目录的内容(这是您在获取目录时得到的内容)。然后开始往下看列表,尝试在lock目录中创建同名锁,直到获得锁为止。如果您使用“prevExist=false”标志,则锁“file”的创建是原子的,因此如果您成功创建了它,您就是对该项拥有锁的人

理想情况下,您可以粗略估计处理项目所需的时间,并将TTL设置为略长于此时间(或者在可以估计时间的步骤之后定期刷新TTL)。完成后,您可以从原始队列中删除该项(也可以在“已完成”目录中重新创建),或者您的锁过期,其他人将其拾取

此外,理想情况下,您应该将唯一的“节点标识符”(主机名,无论什么)放入锁文件中,这样您的TTL更新就会进行比较和设置,如果您因为花费太长时间而丢失了锁,则会失败


工作目录可能会有使用目录上的POST按顺序创建的项,而锁队列和完成的目录则会有使用PUT按名称创建的项。

因此我提出了一个我认为很可靠的解决方案。以下是我设计解决方案的目标:

  • 工作人员从工作队列检索项目应该是高效的(即O(1)网络往返)
  • 如果工作人员在处理项目时死亡或以其他方式失败,则该项目将可供其他工作人员使用
因此,我们的想法是有两个队列:一个挂起队列和一个运行队列。最初,所有项目都在挂起队列中

当工作程序尝试检索项目时,它使用事务(在etcd 3中提供)将其从挂起队列传输到运行队列。在同一事务中,工作者还为该项创建锁。锁由租约保护,因此如果工人死亡,锁会自动移除

如果工作进程成功地完成了对该项的处理,它将从正在运行的队列中删除该项,我们就完成了。如果工作进程失败,锁将过期,该项将留在正在运行的队列中

因此,在挂起队列耗尽后,工作人员还需要查看正在运行的队列。我们的期望是,与挂起队列相比,正在运行的队列将很小,因此查找当前未锁定的项目(通过简单地列出正在运行的队列)不会很昂贵


或者,正如@dannysauer在评论中提到的,您还可以使用另一个容错进程,将项目从正在运行的队列传输回挂起的队列。

但是,如果您的工作队列中有很多项目,该怎么办?你当然不想一个接一个地锁定它们。有什么方法可以有效地检索未锁定的项目吗?如果您有很多客户端,您将使用几个队列。作业进入“挂起”队列,然后当客户端处理作业时,客户端将挂起的作业移动到“进行中”队列,然后在完成时移动到已完成队列或将其删除。您需要一些东西来监视锁,并将正在进行的内容移回挂起状态(如果它们在锁过期之前未完成)。另一种方法是让工作队列使用顺序编号条目(etcd将为您执行),然后使用计数器,每个客户机对其执行原子增量。您不必这样放置目录,因为您只需获取与计数器对应的一项。但是,您有一个所有客户端都依赖的单点争用,这可能是一个问题,具体取决于工作定义。我发布了一个类似于您提到的多队列方法的解决方案。关于按顺序命名的方法:我认为它对分发项目非常有效,但不清楚如果工作人员失败,您如何将项目“返回”到队列中,因为计数器会提前超过项目;使用计数器,您仍然需要一个清理操作,如果存在不完整的作业,该操作将检查不完整的作业。不管怎样,大多数时候我都不喜欢单一的共享锁。谢谢Derek和@dannysauer的精彩回答。我需要实现类似的东西,具有潜在的大(100kB)值。与复制到一个似乎很昂贵的挂起文件夹相比,使用j