我正在创建一个新服务,为此我有一个带有状态字段的数据库条目(Mongo),我需要根据当前时间进行更新,因此,例如,开始时间设置为两个从现在开始的几个小时,我需要从数据库中的“已创建”->“已开始”更改状态,并且可以有多个此类状态。
我想到的方法:
保留查询当前时间为<=的数据库条目,然后相应地更改其状态。这会无缘无故地导致额外的读取,而导致空读取的时间将减少一半,并且随着更多状态的进入,它将变得非常复杂。
我编写了一个作业调度程序(我正在使用go,这样就不会那么难了),并调度所有作业,但是如果出现紧急情况/崩溃,我可能会丢失队列数据。
我使用了诸如芹菜之类的某些产品,已经找到了https://github.com/gocelery/gocelery
我发现的另一个任务计划程序位于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
答案 0 :(得分:1)
我认为您是对的,因为您要解决的问题是作业或任务调度问题。
许多公司使用的一种方法是您提出的系统:将作业插入到具有一定执行时间的数据存储中,然后可以轮询该数据存储以查找要运行的作业。有一些优化可以防止额外的读取,例如定期轮询数据库并使用指数补偿。该系统的优点是它可以容忍节点故障,而缺点是增加了系统的复杂性。
环顾四周,除了您链接的(https://github.com/gocelery/gocelery)之外,还有该模型的其他实现方式(https://github.com/ajvb/kala或https://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等)并计划特定时间的回调的地方。好处是,如果您拥有多种使用不同语言的服务,则它们可以使用相同的调度程序。
总体而言,在决定解决方案之前,我会考虑一些权衡因素:
祝你好运!希望有帮助。