重复删除 Laravel 个事件/作业

Deduplicating Laravel events / jobs

我有一个应用程序可以处理产品和订单更新,并使用事件和作业的组合来响应其中任何一个的变化。

在这方面工作了近 2 年并观察了它的运行情况,我发现最大的瓶颈是任何其他互连系统发送重复事件(这可能会导致重复的作业等)。

在正常操作下,这很好,我们有足够的空闲时间来应对峰值,但当它真的很忙时,它会滚雪球,导致未处理的事件和作业积压。

我使用的设置是 Laravel 4.2 的标准安装,带有 MySQL (mariadb) 一个 redis 支持的作业和事件队列,具有多个队列来处理不同类型的事件(产品库存更新,订单发货等)。

我想知道是否有人可以建议一种方法来防止 laravel 添加与同一操作相关的事件 and/or 作业。

工作的一个例子是:

{
"job": "Illuminate\Queue\CallQueuedHandler@call",
"data": {
    "commandName": "Staw\Magento\Jobs\AddTrackingNumber",
    "command": "O:40:\"Staw\Magento\Jobs\AddTrackingNumber\":6:{s:17:\"\u0000*\u0000trackingNumber\";s:14:\"[Tracking Number]\";s:14:\"\u0000*\u0000orderNumber\";s:19:\"[Order NUmber]\";s:10:\"connection\";N;s:5:\"queue\";s:8:\"despatch\";s:5:\"delay\";N;s:6:\"\u0000*\u0000job\";N;}"
},
"id": "xGmsi6vo458cYGeJHDfpGCZG8QuAJXB7",
"attempts": 1
}

还有一个事件侦听器(来自事件)

{
"job": "Illuminate\Events\CallQueuedHandler@call",
"data": {
    "class": "Staw\Magento\Listeners\OrderEventListener",
    "method": "onOrderChangeAlert",
    "data": "a:1:{i:0;O:49:\"Staw\HiveEvent\Events\Order\OrderChangeAlert\":6:{s:10:\"eventstart\";O:13:\"Carbon\Carbon\":3:{s:4:\"date\";s:26:\"2017-12-14 11:20:04.000000\";s:13:\"timezone_type\";i:3;s:8:\"timezone\";s:13:\"Europe/London\";}s:8:\"chain_id\";s:13:\"5a325e64510ce\";s:10:\"channel_id\";i:1;s:11:\"channel_key\";N;s:9:\"entity_id\";s:19:\"[Order Number]\";s:5:\"queue\";s:5:\"event\";}}"
},
"id": "0GLUt1O9y6jaZ56yHKA8Vn9si1QNnmlf",
"attempts": 1
}

我知道我可以使用 predis/predis 包搜索 redis 但这看起来真的很麻烦,我考虑过在数据库上制作自己的 queue/stack 以便更好地控制事情但这似乎是一项艰巨的任务,我觉得我会错过使用原厂 Laravel 设置获得的一些功能。

解决方法是,它可能涉及更改应用程序结构。你应该做一个 table 来记录作业信息,如作业 ID、作业名称、作业数据等,然后再推入队列。当队列工作者处理作业时,作业处理程序应该查找 table 并查看是否有重复的作业。如果是这样,立即终止作业。它应该对事件做同样的事情。

有多种实现方式:

  1. 对于Laravel 4,修改所有作业处理程序的fire事件,或者继承一个抽象class,如果这个tuple($job, $data) 已经存在。如果已经存在,则立即终止作业。

  2. 对于laravel 5,有一个方便的实现方法。我们可以使用 Queues Job EventsQueue::before 来记录作业。如果复制作业已经存在,则修改每个作业处理程序以进行查找。如果已经存在,则立即终止作业。