You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony Messenger Redis传输问题:消息被所有队列重复处理

问题核心与解决方案

你遇到的问题根源是Redis传输默认使用同一个Redis键存储所有队列消息,而你当前所有Transport都用了不带queue参数的相同DSN,导致所有Worker监听同一个Redis队列,进而抢着处理所有消息。Doctrine传输靠数据库表区分队列,Redis则需要通过指定独立的队列(Redis键)来实现隔离。

具体解决步骤

  1. 给每个Redis Transport配置独立的Queue参数
    修改messenger.yaml中每个Redis Transport的DSN,添加?queue=唯一队列名后缀,确保每个队列对应唯一的Redis键:

    #messenger.yaml:
    framework:
        messenger:
            failure_transport: failed
            transports:
                async: 
                    dsn: '%env(MESSENGER_TRANSPORT_DSN)%?queue=async'
                audit: 
                    dsn: '%env(MESSENGER_TRANSPORT_DSN)%?queue=audit'
                    retry_strategy:
                        max_retries: 3
                async_backup_task:
                    dsn: '%env(MESSENGER_TRANSPORT_DSN)%?queue=async_backup_task'
                    retry_strategy:
                        max_retries: 0
                failed: 
                    dsn: '%env(MESSENGER_TRANSPORT_DSN)%?queue=failed'
                sync: 'sync://'
            routing:
                Symfony\Component\Mercure\Update: async
                App\Message\UsuarioTraceMessage: audit
                App\Message\BackupDirectoryToRemoteStorageMessage: async_backup_task
    
  2. 澄清MESSENGER_CONSUMER_NAME的作用
    这个环境变量并非用来区分消息队列,它的作用是给每个Worker进程设置唯一标识,方便在日志、监控中区分不同的Worker实例(比如你Supervisor配置里生成的%(program_name)s_%(process_num)02d名称)。队列的隔离完全依赖DSN中的queue参数。

  3. 使配置生效

    • 清除Symfony生产环境缓存:php bin/console cache:clear --env=prod
    • 重启所有Supervisor Worker进程:supervisorctl restart all

完成以上操作后,每个Transport会将消息发送到对应名称的Redis队列,每个Worker仅监听自身配置的队列,就不会出现所有Worker处理同一消息的情况了。

内容的提问来源于stack exchange,提问作者Francisco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:47:23