laravel - Cron vs 排队任务
问题描述
我的应用程序有一个带有execution_datetime属性的Order模型。我想发送一些不同的通知。例如
- execution_datetime减去 12 小时:给运营商的电子邮件
- execution_datetime减去 3 小时:向客户发送短信
- execution_datetime加 1 小时:向客户发送电子邮件
上述时序不严格,可以近似;轻微的偏差是可以接受的。此外,execution_datetime可以同时改变......
我不确定是否为此使用 cron 或排队任务。我个人的一些想法:
克朗:
- 需要编写业务逻辑以获取适用的订单并相应地执行
- 执行有保障吗?是否应该实现某种数据库标志以指示已发送通知,然后可能获取所有未标记为某种故障安全的到期订单?
排队的任务:
- 任务是在创建订单时安排的?如果是这样,假设执行时间已更改。如何修改定时任务?您需要在某个地方跟踪任务 ID?
- 或者可能是每天大量安排适用任务的 cron 作业?
我期待您的建议。
解决方案
好问题!我对这个讨论很感兴趣。让我用我个人经历的一个场景来插话。
在我的应用程序中,我有一个Listing
模型,它们有一个promotion_ends_at
列。显然,上市促销有时会在未来结束。
所以,就像你也提到的,有两种方法可以做到这一点。
- 创建列表后,我可以排队等待将来在列表中结束促销的工作)。那份工作的延迟将是促销必须结束的时间(那可能是我几个月之后)。
- 我还可以有一个定期运行的 cron 作业来管理他们的促销活动应在特定日期结束的列表。
我们将SQS
其用作队列服务,由于最长延迟SQS
为 15 分钟,因此选项 1 不可行。然后,我们搬到了 Redis,在那里我们可以轻松地将延迟的作业排入队列。
但是,就像您所说的那样,该promotion_ends_at
列可能会在此期间更新。因此,要么,您必须跟踪作业以使其出队,或者您可以重新检查作业在即将执行时是否仍应运行。
例如,您可以fresh()
建模并检查您的条件是否仍然有效。fresh
就我而言,我会Listing
检查是否promotion_ends_at
过去。然而,这意味着我们将有很多陈旧的工作可能无论如何都会被丢弃。
我们最终选择了一个简单的 cron 作业,它可以在需要运行的那一天大规模安排作业。我还认为运行延迟的作业是一种业务逻辑,也许队列不应该对将来运行延迟太多的作业负责。