beanstalkd的条件工作队列插入?

时间:2009-12-23 20:19:51

标签: perl algorithm beanstalkd

我正在使用beanstalkd的Perl客户端。我需要一种简单的方法来不要将相同的工作排成两次。

我需要的东西基本上要等到有K个元素,然后将它们组合在一起。要做到这一点,我有制作人:

insert item(s) into DB
insert a queue item into beanstalkd

消费者:

while ( 1 ) {
   beanstalkd.retrieve
   if ( DB items >= K )
       func_to_process_all_items
   kill job
}

这是请求/处理的数量是线性的,但是在:

的情况下
insert 1 item
... repeat many times ...
insert 1 item

假设所有这些插入都发生在检索作业之前,这将添加N个队列项,并且它会这样做:

check DB, process N items
check DB, no items
... many times ...
check DB, no items

是否有更智能的方法来执行此操作,以便它不会不必要地插入/处理以后的作业请求?

2 个答案:

答案 0 :(得分:2)

我有相关的要求。我只想在几分钟内处理一次特定的工作,但是生产者可以排队同一工作的几个实例。我使用memcache来存储作业标识符,并将密钥的到期时间设置为几分钟。

当工作人员尝试将作业标识符添加到memcache时,只有第一个成功 - 如果未能添加作业ID,则工作人员将删除该作业。几分钟后,密钥将从memcache到期,并且可以再次处理作业。

不是特别优雅,但它有效。

答案 1 :(得分:1)

这对你有用吗?:

  1. 创建两个Tubes“buffer”和“live”。您的制作人总是只添加到“缓冲”管。
  2. 创建两个工作人员,一个人观看“缓冲区”,另一个人观看“实时”,呼叫阻止reserve()电话
  3. 每当“缓冲”工作人员返回保留时,如果少于K个项目,则会隐藏作业。如果确切地存在K,则它“踢”所有K个作业并将它们转移到“实时”管。
  4. “实时”观察者现在将自行返回reserve()
  5. 您只需要注意作业不会从隐藏状态返回缓冲区队列。一种故障安全的方法可能是删除它,然后将其添加到实时。

    两个独立的队列仅用于清洁分离。你可以通过埋葬每个工作来做同样的事情,直到有K-1,然后在第K个工作到来时,将所有这些工作都踢出去。