3

我系统中的每个 Job 都属于一个特定的用户 ID,并且可以从多个来源放入 rabbitmq。我的要求:

  • 在任何给定时间,每个用户都不应运行超过 1 个作业。
  • 其他用户的作业不应因为特定用户的作业堆积而出现任何延迟。
  • 每个作业应至少执行一次。每个作业都有一个最大重试次数,如果失败,则会延迟重新插入队列(或可能延迟)。
  • 维护作业顺序(每个用户)是可取的,但不是强制性的。
  • 作业可能应该被持久化,因为我需要它们至少执行一次。作业没有到期时间。
  • 任何工作人员都应该能够为任何用户运行作业。

有了这些要求,我认为为每个单独的用户维护一个队列是有意义的。我还需要所有工作人员监视所有用户队列并为用户执行作业,该用户的作业当前未在任何地方运行(即每个用户不超过 1 个作业)

这个解决方案可以在集群设置中使用 RabbitMQ 吗?由于队列的数量会很大,我不确定每个观察每个用户队列的工作人员是否会导致显着的开销。任何帮助表示赞赏。

4

1 回答 1

2

正如@dectarin 所提到的,让多个工作人员监听多个作业队列将很难确保每个用户只执行一个作业。

我认为如果工作通过几个步骤会更好。

  1. 用户提交作业
  2. 作业按用户排队,直到没有其他作业在运行
  3. Coordinator 将作业放在工作人员使用的活动作业队列中
  4. 工人拿起工作并执行它
  5. Worker 将结果发布到结果队列中
  6. 结果被发送给用户

我不知道作业是如何提交到系统的,因此很难判断实际的每用户 MessageQueues 是否是排队等待的最佳方式。例如,如果作业已经放在邮箱中,那也可以。或者将排队的作业存储在数据库中,作为奖励,您可以编写一个小前端供用户检查和管理他们的排队作业。

根据您的选择,您可以找到一种优雅的方式来协调每个用户约束的单个作业。

例如,如果作业位于数据库中,数据库会保持同步,并且多个协调工作人员可以通过以下循环:

while( true ) {
    if incoming job present for any user {
        pick up first job from queue
        put job in database, marking it active if no other active job is present
        if job was marked active {
            put job on active job queue
        }
    }
    if result is present for any user {
        pick up first result from result queue
        send results to user
        mark job as done in database
        if this user has job waiting in database, mark it as active
        if job was marked active {
            put job on active job queue
        }
    }
}

或者,如果等待作业位于每个用户的消息队列中,则事务将更容易,并且通过循环的单个 Coordinator 无需担心多线程。

跨数据库和队列使事物完全事务化可能很困难,但不是必需的。引入挂起状态时,您应该允许您谨慎行事,以确保在步骤失败时不会丢失工作。

于 2014-08-08T11:50:09.767 回答