计划任务/消息以供以后处理/交付

时间:2018-09-09 07:28:59

标签: go scheduled-tasks publish-subscribe

我正在创建一个新服务,为此我有一个带有状态字段的数据库条目(Mongo),我需要根据当前时间进行更新,因此,例如,开始时间设置为两个从现在开始的几个小时,我需要从数据库中的“已创建”->“已开始”更改状态,并且可以有多个此类状态。

我想到的方法:

  1. 保留查询当前时间为<=的数据库条目,然后相应地更改其状态。这会无缘无故地导致额外的读取,而导致空读取的时间将减少一半,并且随着更多状态的进入,它将变得非常复杂。

  2. 我编写了一个作业调度程序(我正在使用go,这样就不会那么难了),并调度所有作业,但是如果出现紧急情况/崩溃,我可能会丢失队列数据。

  3. 我使用了诸如芹菜之类的某些产品,已经找到了https://github.com/gocelery/gocelery

  4. 的go实施方案。

我发现的另一个任务计划程序位于Google Cloud https://cloud.google.com/solutions/reliable-task-scheduling-compute-engine上,但我不想陷入专有技术中。

我想为此使用一些PubSub服务,但是我找不到延迟消息的消息(如果是这样的话)。我的问题主要是无法找到该问题的实际名称,为了能够正确搜索它,我什至尝试搜索Microsoft文档。如果有人可以向我指出正确的方向,或者如果我编写的任何方法都是我应该使用的方法,请告诉我,那将是很大的帮助!

更新: 发现了Netflix针对同一问题的另一种解决方案 https://medium.com/netflix-techblog/distributed-delay-queues-based-on-dynomite-6b31eca37fbc

1 个答案:

答案 0 :(得分:1)

我认为您是对的,因为您要解决的问题是作业或任务调度问题。

许多公司使用的一种方法是您提出的系统:将作业插入到具有一定执行时间的数据存储中,然后可以轮询该数据存储以查找要运行的作业。有一些优化可以防止额外的读取,例如定期轮询数据库并使用指数补偿。该系统的优点是它可以容忍节点故障,而缺点是增加了系统的复杂性。

环顾四周,除了您链接的(https://github.com/gocelery/gocelery)之外,还有该模型的其他实现方式(https://github.com/ajvb/kalahttps://github.com/rakanalh/scheduler是我在快速搜索后发现的)。< / p>

您所描述的“正在处理计划作业”的另一种方法非常简单,因为停放的goroutine非常便宜。廉价地为您的工作生成一个goroutine很简单。这很简单,但缺点是,如果流程终止,工作就会丢失。

go func() {
    <-time.After(expirationTime.Sub(time.Now()))

    // do work here.
}()

我见过但不推荐使用的最后一种方法是回调模型(类似于https://gitlab.com/andreynech/dsched)。这是您的服务调用另一个服务(通过http,grpc等)并计划特定时间的回调的地方。好处是,如果您拥有多种使用不同语言的服务,则它们可以使用相同的调度程序。

总体而言,在决定解决方案之前,我会考虑一些权衡因素:

  • 失业情况如何?如果可以将某些工作丢掉一小部分时间,那么可以采用一种在线解决方案。
  • 工作需要等待多长时间?如果它比主机的关闭时间长,那么基于数据存储的解决方案可能会更好。
  • 您是否需要在多台计算机上分配作业负载?如果您需要分配负载,则分片和调度是棘手的事情,您可能需要考虑使用更现成的解决方案。

祝你好运!希望有帮助。