如何在etcd

时间:2016-01-06 09:41:26

标签: queue distributed etcd workload

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

但你怎么实际实现这个呢?

基本模式会是这样的。

1个流程生成"工作描述票据",并将该票证放在etcd的文件夹中,然后说" / queue / worktickets / 00000000001 /"

1->许多进程正在监听" / queue / worktickets /"更改文件夹。 当新工作票出现时,每个进程都会尝试通过在" / queue / locks / 00000001"中创建新值来抓取票证。锁定那张票。只有第一个能够创建锁定值。

创建锁定票证的过程可以正常工作,然后从队列中删除票证,也可能是锁定值。然后尝试从队列中获取下一个可用的票证。如果没有更多票据可用,请开始收听" / queue / worktickets /"中的更改。文件夹再次。

在我的脑海中,这应该是相当简单的实现,但如果队列变大(票证很容易生成但很难处理),那么似乎会有很多数据从etcd转移到每个客户端。 至于我的知识,没有办法说给我这个文件夹中没有的第一个值,这个文件夹中没有,也没有一些给我文件夹中的前n项。

任何人都愿意在此分享他们的思想。

2 个答案:

答案 0 :(得分:4)

所以我想出了一个我觉得很健壮的解决方案。以下是我设计解决方案的目标:

  • 工作人员从工作队列中检索项目应该是有效的(即O(1)网络往返)。
  • 如果工人在处理某件物品时死亡或以其他方式失败,则该物品可供其他工人使用。

所以我们的想法是拥有两个队列:一个待处理队列和一个正在运行的队列。最初所有项目都在待处理队列中。

当工作人员尝试检索某个项目时,它会使用事务将其从待处理队列传输到正在运行的队列(在etcd 3中可用)。在同一事务中,worker还会为该项创建锁。锁定由租约保护,因此如果工人死亡,它将被自动删除。

如果一个worker成功完成了对该项的处理,它将从正在运行的队列中删除该项,我们就完成了。如果工作程序失败,则锁定将过期,并且该项目将保留在正在运行的队列中。

因此,一旦挂起的队列耗尽,工作人员也应该查看正在运行的队列。期望运行队列与待处理队列相比较小,因此找到当前未锁定的项目(通过简单地列出正在运行的队列)并不会很昂贵。

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

答案 1 :(得分:0)

我想你已经解决了这个问题,但我这样做的方法是列出工作队列目录的内容(这是你获取目录时得到的内容)无论如何)。然后开始沿着列表尝试在锁定目录中创建具有相同名称的锁,直到您获得锁定。创建锁"文件"如果你使用" prevExist = false"是原子的flag,所以如果你成功创建了它,那么你就是锁定该项目的人。

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

另外,理想情况下,您可以使用您唯一的节点标识符" (主机名,等等)进入锁定文件,因此您的TTL更新会进行比较和设置,如果您因为花费太长时间而失去锁定,则会失败。

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