Webman Redis队列积压需立即检查消费者进程状态、调整并发数、修复阻塞任务。1.用ps查进程并php webman restart;2.调process.php中count值;3.加耗时监控与超时设置;4.手动清理分流;5.定期检查failed队列并重试。

Webman 的 Redis 队列积压不是“等它自己消化”,而是进程、配置、逻辑三处同时出问题的信号。必须立刻查进程、调并发、盯耗时。
怎么确认消费者进程还在跑
积压第一反应不是改代码,是看 ps 有没有真正在干活的消费者。很多线上问题其实只是进程挂了没人发现。
- 进项目根目录,执行
ps aux | grep redis-queue,重点看有没有php webman start拉起的Consumer进程 - 如果只看到
defunct(僵尸进程)或 CPU 占用长期为0.0,说明已卡死或退出 - 别直接
kill -9,先php webman stop再php webman start -d,避免残留连接干扰 - 确保
plugin/webman/redis-queue插件已启用,且config/plugin/webman/redis-queue/process.php中的count不是0
并发数调多少才够用
count 不是越大越好,得结合队列长度、单条处理耗时和 Redis 响应能力来配。盲目设成 16 可能反而压垮 Redis 连接池。
- 先用
redis-cli llen send-mail查当前积压量(比如1248) - 再看单条任务平均耗时:在
app/queue/Handler.php的handle()开头加microtime(true),结尾算差值 - 若平均 800ms,目标 5 秒内清完积压,则理论最小并发 ≈
1248 × 0.8 / 5 ≈ 200—— 显然不现实,所以得先优化单条耗时,再设count => 4或8观察下降斜率 - 每次调整后等 2 分钟再查
llen,避免误判瞬时抖动
为什么加了并发还是积压
常见错觉:开了 4 个消费者,就等于吞吐翻 4 倍。实际瓶颈常在任务内部 —— 一条阻塞,整条进程就停摆。
- 典型阻塞点:
file_get_contents同步 HTTP、mysqli_query无超时查询、fopen大文件写入、未设timeout的 Redis 调用 - 检查
app/queue/Handler.php是否用了Redis::send()或Client::send()等可能触发同步等待的操作 - 所有外部调用必须带超时:
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 3000)、PDO 设置PDO::ATTR_TIMEOUT - 日志里一旦出现连续多条相同
handle()开始时间,基本可断定某条消息卡死了整个进程
失败队列里的消息怎么救回来
积压严重时,redis-queue-failed 里往往堆着几百条重试失败的消息。它们不会自动重投,也不能直接 LPOP 扔回去 —— 缺少重试元数据会丢重试次数。
- 先用
redis-cli lrange redis-queue-failed 0 9抽样看失败原因(常见是Connection refused或业务异常) - 修复对应 bug 后,用插件提供的命令重试:
php webman redis-queue:retry --queue=send-mail --max=50 - 如果要全量重试,别用
LRANGE + LREM,而应执行php webman redis-queue:retry --all,它会按原max_attempts和retry_seconds规则重建延迟队列 - 手动清理前务必备份:
redis-cli lrange redis-queue-failed 0 -1 > failed-backup.json
最易被忽略的是:消费者进程本身没有健康探活机制。哪怕它卡在某个 sleep(300) 里不动,ps 看起来仍是“运行中”。必须在 handle() 里加耗时告警,而不是只依赖外部监控。


















