重复Laravel活动/工作

时间:2017-12-14 11:26:34

标签: php mysql laravel redis laravel-4.2

我有一个处理产品和订单更新的应用程序,并使用事件和作业的混合来响应两者中的更改。

已经对此进行了近两年的工作并观察它的实际情况我发现最大的瓶颈是当重复事件(可能导致重复的工作等)由任何其他互连系统发送时。

在正常操作下,这很好,我们有足够的空间来容纳尖峰,但是当它真的很忙时,它会滚雪球并导致未处理的事件和工作积压。

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

我想知道是否有人可以提出一种方法来阻止laravel添加与同一行动相关的事件和/或工作。

工作的一个例子是:

{
"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,但这看起来真的很麻烦,我考虑过让我自己的队列/堆栈可能在数据库上有更多的控制权但是这个这似乎是一项艰巨的任务,我觉得我错过了使用Laravel库存设置所获得的一些功能。

1 个答案:

答案 0 :(得分:1)

解决方法是,它可能涉及应用程序结构的变化。在推入队列之前,您应该创建一个表来记录作业信息,例如作业ID,作业名称,作业数据等。当队列工作者处理作业时,作业处理程序应该查找表并查看是否存在重复作业。如果是这样,请立即终止作业。它应该对事件做同样的事情。

有很多实现:

  1. 对于Laravel 4,修改所有作业处理程序的fire事件,或继承一个抽象类,如果此tuple($job, $data)已存在,则记录和查找。如果已存在,请立即终止作业。

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