从数据库中间隔调度任务的最佳方法

时间:2015-09-04 14:35:41

标签: mongodb asynchronous cron redis scheduling

我有一个带有Tasks的MongoDB集合。每个任务都有一个以秒为单位的间隔,任务标识符和有效负载,应通过HTTP POST发送以收集结果并将其存储到另一个集合中。

可能是数千个不同间隔的任务,我无法弄清楚如何安排它们。

目前我每隔10毫秒使用一次上次执行时间进行简单轮询,但它会对数据库产生很大的负担。

它看起来像这个

mongo.MongoClient.connect(MONGO_URL, (err, db) ->
  handle_error(err)

  schedule = (collection) ->
collection.find({isEnabled:true, '$where': '((new Date()).getTime() - this.timestamp) > (this.checkInterval * 60 * 1000)'}).toArray((err, docs) ->
  handle_error(err)
  for i, doc of docs
    collection.update({_id: doc._id}, {'$set': {timestamp: (new Date()).getTime()}}, {w: 1})
        task = prepare(doc)
        request.post({url: url, formData: {task: JSON.stringify(prepare(doc))}}, (err,httpResponse,body) ->
          result = JSON.parse(body)
          console.log(result)
          db.collection(MONGO_COLLECTION_RESULTS).save({
        task: result.id,
        type: result.type,
        data: result
          })
        )

      setTimeout((() -> schedule(collection)), 10)
    )

  setTimeout((() -> schedule(db.collection(MONGO_COLLECTION_TASKS))), 10)
)

任务可以添加,更新,删除,我必须处理它。 用redis怎么样?但我不知道当一些任务等待结果,间隔改变等时如何将数据从mongo同步到redis

请为此建议最佳策略

2 个答案:

答案 0 :(得分:0)

我认为这不是解决您的用例的正确方法。

我建议不要将任务存储在任何数据库中,而是在它们进入时直接安排它们并保存结果,无论是否有原始任务信息。

为什么不使用Quartz来安排任务?

答案 1 :(得分:0)

如果您知道要运行的任务,则可以使用unix crontab进行计划,该计算机运行连接到DB或发送HTTP请求的脚本。

如果每个任务都是唯一的,并且您无法以这种方式预先安排它们,那么您可以使用当前的数据库集合,但不要经常轮询数据库。

如果在正确的时间完成任务并不重要,我会每隔10秒进行一次数据库查找,看看自上次查找以来应该执行哪些任务。

解决数据库负载的一种方法是创建一个查询,该查询在应该执行它们时获取所订购的任务,所有任务都应在下一分钟左右执行。然后你(希望)在内存中有少量的任务,并且可以设置javascript超时以便它们应该运行。如果应该同时运行太多任务,那么一次从db中获取可能会有问题。

本质上是将几个任务从db批处理到内存中,并处理那里的一些调度。