ruby - 在不同服务器上执行多项任务的作业

标签 ruby mongodb redis scheduled-tasks

我需要一个包含多个任务的作业,在不同的机器上一个接一个地(不是同时)运行,并且当当前作业正在运行时,另一个相同的作业可以到达队列,但不应该开始直到上一个已经完成了。所以我想出了这个可能不是最好的“解决方案”,但它完成了工作:)。我只有一个问题。

我发现我需要一个具有以下结构的 JobQueue(MongoDb 或 Redis):

{
hostname: 'host where to execute the task',
running:FALSE,
task: 'current task number',
tasks:{
    [task_id:1, commands:'run these ecommands', hostname:'aaa'],
    [task_id:2,commands:'another command', hostname:'bbb']
    }
}

主持人:

  • 搜索具有相同主机名的作业,并运行==FALSE
  • 执行该作业中设置的任务
  • 完成后,主机设置 running=FALSE,检查是否有任何其他任务要执行并增加任务编号 + 将主机名设置为下一个任务的下一台机器

因为作业可以累积,想象一下当作业像这样在一台主机上排队时的情况:A,B,A

因为我必须运行指定机器的所有作业,我如何不启动第 3 个 A(第一个 A 仍在运行)?

最佳答案

{
   _id : ObjectId("xxxx"),    // unique, generated by MongoDB, indexed, sortable
   hostname: 'host where to execute the task',
   running:FALSE,
   task: 'current task number',
   tasks:{
      [task_id:1, commands:'run these ecommands', hostname:'aaa'],
      [task_id:2,commands:'another command', hostname:'bbb']
    }
}

问题是下一个可用的“ worker ”如何知道在特定主机上开始下一个工作是否安全。

您可能需要某种可排序(索引)字段来指示作业的到达顺序。如果您使用的是 MongoDB,那么您可以让它生成 _id,因为它的前四个字节是时间戳,所以它已经是唯一的、索引的和按时间顺序排列的。

您现在可以查询是否有为特定主机运行的作业,如下所示:

// pseudo code - shell syntax, not actual code
var jobToRun = db.queue.findOne({hostname:<myHostName>},{},{sort:{_id:1}});
if (jobToRun.running == FALSE) {
    myJob = db.queue.findAndModify({query:{_id:jobToRun._id, running:FALSE},update:{$set:{running:TRUE}}});
    if (myJob == null) print("Someone else already grabbed it");
    else {
        /* now we know that we updated this and we can run it */
    }
} else { /* sleep and try again */ }

这样做是检查特定主机的最旧/最早的作业。然后查看该作业是否正在运行。如果是,则什么都不做(休眠并重试?)否则尝试通过在 _id 上执行 findAndModify 并运行 FALSE 并将运行设置为 TRUE 来“锁定”它。如果返回该文档,则表示此过程更新成功,现在可以开始工作了。由于两个线程可以同时尝试执行此操作,如果您返回 null,则意味着该文档已更改为由另一个线程运行,我们等待并重新开始。

我会建议在某个地方使用时间戳来指示作业何时开始“运行”,这样如果一个 worker 在没有完成任务的情况下死亡,它可以被“找到”——否则它将“阻塞”它后面的所有作业同一个主机。

我所描述的适用于一个队列,在该队列中您可以在作业完成后将其删除,而不是将运行设置回 FALSE - 如果您将运行设置为 FALSE 以便可以完成其他“任务”,那么您可能也会更新任务数组以指示已完成的操作。

关于ruby - 在不同服务器上执行多项任务的作业,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24659669/

相关文章:

ruby-on-rails - 什么决定了 `present?` 的返回值?

mongodb - mongodb $regex 中排序规则的使用

go - 在 Golang 中使用 Redis 配置 gin-gonic session

node.js - 在前台启动 redis 并使用一个命令并行但串行地启动 Node 服务器

asp.net-mvc - 在 Asp Net Core 中使用指定的 Redis 数据库实例

ruby - 字符串中的引用方法名称

ruby-on-rails - 在我的 Rails 应用程序中适本地处理非 UTF8 内容

ruby-on-rails - 无法通过 Rails 3.2 中的关联模型添加或删除

javascript - 使用 Mongoose 时出现错误 'Object has no method xxx '

mysql - Mongodb 查询用于在字段之间搜索一个字母数字邮政编码