【问题标题】:Laravel Redis Queue and supervisor worker - job gets executed multiple timesLaravel Redis 队列和主管工作者 - 作业多次执行
【发布时间】:2021-05-22 06:51:41
【问题描述】:

我使用 Redis 作为队列驱动程序并调度一个向用户发送通知的作业。问题是用户多次收到相同的通知。

Laravel 8.0,标准 Redis 配置。

主管配置:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/vhosts/website.com/httpdocs/artisan queue:work --sleep=0 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
numprocs=10
redirect_stderr=true
stdout_logfile=/var/www/vhosts/website.com/httpdocs/storage/logs/worker.log
stopwaitsecs=3600

工作:

class NotifySubscribersOfReply implements ShouldQueue, ShouldBeUnique
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $thread;
    public $reply

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($thread, $reply)
    {
        $this->thread = $thread;
        $this->reply = $reply;
    }

    /**
     * The unique ID of the job.
     *
     * @return string
     */
    public function uniqueId()
    {
        return "reply-" . $this->reply->id . "-notification";
    }

    /**
     * The number of seconds after which the job's unique lock will be released.
     *
     * @var int
     */
    public $uniqueFor = 3600;

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // send notification
    }
}

队列配置:

'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => env('REDIS_QUEUE', 'default'),
            'retry_after' => 1800,
            'block_for' => null,
        ],

如果有任何提示,我会非常高兴,谢谢!

【问题讨论】:

  • 您可以在handle()函数中检查通知是否已经发送。如果它已经发送,不要做任何事情。在这种情况下,您需要将推送通知存储在数据库中。
  • @RifatBinReza 是的,我可以做到。但我想知道这是否有必要?
  • 根据我的经验,这是必要的。如果您的工作需要更长的时间才能完成,然后它会再次开始,并且在一段时间后完成前一个工作怎么办。执行作业时始终检查是安全的。

标签: laravel redis queue supervisord


【解决方案1】:

尝试更新config/queue.php中redis配置的retry_after。将其更改为您的作业可以执行的最大值。您的工作正在执行多次,因为您的工作需要超过1800 秒才能完成,并且您有多个工作人员正在运行。 因此,发生的情况是一个工作人员在第一次分派时选择该作业,然后在 1800 秒后另一个工作人员选择执行相同的作业,因为它没有完成或从队列中删除。

【讨论】:

  • 谢谢,但没有。我的工作不应该超过 1 秒。
  • 您可以尝试在您的工作中添加public $timeout = {timeout};。可能您的作业已完成执行,但未从队列中删除。
猜你喜欢
  • 2019-11-28
  • 1970-01-01
  • 1970-01-01
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 2018-07-15
  • 1970-01-01
相关资源
最近更新 更多