必须用Swoole搭建分布式任务队列系统:安装Swoole扩展或Docker镜像,用MsgPack序列化Task对象(含UUID、job路径、payload等),通过Redis BLPOP或多节点TCP Server消费,结合Consul实现服务发现与心跳管理。

你需要在多台服务器上协同处理高并发任务,比如订单异步通知、日志归档或图片批量压缩,单机队列已无法横向扩展,必须用 Swoole 搭建可水平伸缩的分布式任务队列系统。
安装与初始化 Swoole 环境
确认 PHP 版本 ≥ 8.0,执行 pecl install swoole 安装扩展;若使用 Docker,直接拉取官方 swoole/swoole:latest 镜像即可。这一步跳过源码编译能避免因 OpenSSL 版本不匹配导致的 socket 连接失败。
在项目根目录运行 composer require swoole/ide-helper,补全 IDE 类型提示——没有它,后续写协程客户端时容易因方法名拼错而卡在调试环节。
设计任务结构与序列化协议
定义一个 Task 类,包含 id(UUID v4)、job(类名+方法,如 App\Jobs\SendEmail::handle)、payload(array,经 msgpack_pack() 序列化)、attempts 和 max_attempts 字段。
必须用 MsgPack 而非 JSON:JSON 无法原生支持 PHP 的 DateTime、resource 或闭包,且体积比 MsgPack 大 30% 以上;【反序列化时若用 json_decode 解 MsgPack 数据,会静默返回 null】。
在 Task::dispatch() 中自动生成唯一 id 并调用 Redis::lPush('queue:default', $packed) 入队。
启动多工作进程消费队列
方法一:基于 Swoole Process + Redis BLPOP
创建 worker.php,用 Swoole\Process::fork() 启动 4 个子进程;每个子进程执行 $redis->blPop(['queue:default'], 0) 阻塞监听——这里设为 0 表示永不超时,避免空轮询消耗 CPU。
收到任务后,用 msgpack_unpack($data) 还原对象,再通过反射调用 $task->job 对应方法;失败时自动重推回队首并增加 attempts 计数。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
方法二:用 Swoole Server 承载任务分发中心
启动 TCP 服务监听 0.0.0.0:9502,所有 Worker 进程连接该端口注册为客户端;当新任务入队,Server 主动推送任务数据到空闲 Worker 的 socket 连接。这种方式避免了 Redis 的竞争锁开销,但需自行实现心跳与断线重连逻辑。
跨节点任务去重与幂等保障
第一步:在任务入队前,生成 signature = md5($job . json_encode($payload));
第二步:用 Redis::setex('task:sig:' . $signature, 3600, $task->id) 设置 1 小时有效期的签名锁;
第三步:仅当 Redis::get('task:sig:' . $signature) === $task->id 时才真正入队——否则说明相同任务已在 1 小时内提交过,直接丢弃。
注意:这个签名机制只对「参数完全一致」的任务生效,不适用于含时间戳或随机 ID 的 payload;若业务要求更严格,需在 Job 类中实现 shouldSkipWhenSame() 自定义判断逻辑。
部署多个 Worker 节点并接入 Consul 服务发现
在每台服务器上运行 php worker.php --node-id=web1,Worker 启动后向 Consul 的 KV 存储写入 services/queue-worker/web1 = {"addr":"10.0.1.12:9502","last_heartbeat":1717023456};
所有 Producer 节点从 Consul 拉取在线 Worker 列表,用一致性哈希选择目标节点,再通过 Swoole\Coroutine\Client 发送任务数据包;
Worker 进程每 15 秒向 Consul 更新一次心跳,超时 45 秒未更新则自动剔除——【Consul 健康检查路径必须返回 HTTP 200,否则节点会被标记为不可用】。

















