Symfony Messenger Redis传输问题:消息被所有队列重复处理
问题核心与解决方案
你遇到的问题根源是Redis传输默认使用同一个Redis键存储所有队列消息,而你当前所有Transport都用了不带queue参数的相同DSN,导致所有Worker监听同一个Redis队列,进而抢着处理所有消息。Doctrine传输靠数据库表区分队列,Redis则需要通过指定独立的队列(Redis键)来实现隔离。
具体解决步骤
给每个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澄清MESSENGER_CONSUMER_NAME的作用
这个环境变量并非用来区分消息队列,它的作用是给每个Worker进程设置唯一标识,方便在日志、监控中区分不同的Worker实例(比如你Supervisor配置里生成的%(program_name)s_%(process_num)02d名称)。队列的隔离完全依赖DSN中的queue参数。使配置生效
- 清除Symfony生产环境缓存:
php bin/console cache:clear --env=prod - 重启所有Supervisor Worker进程:
supervisorctl restart all
- 清除Symfony生产环境缓存:
完成以上操作后,每个Transport会将消息发送到对应名称的Redis队列,每个Worker仅监听自身配置的队列,就不会出现所有Worker处理同一消息的情况了。
内容的提问来源于stack exchange,提问作者Francisco
相关产品推荐
相关产品推荐

