php 消息队列Redis
别硬扛同步请求:用 Redis 搭一套稳当的 PHP 消息队列
业务突然跑不动了,多半是同步逻辑把主线程拖垮了。电商大促时用户下单,如果发通知、写审计日志、清缓存全部塞进同一个 HTTP 请求里,接口响应能直接干到三十秒以上,数据库连接池也跟着见底。这时候把耗时操作抽离成异步任务,是最省力的解法。不用硬上 Kafka 或 RabbitMQ,Redis 的列表结构完全能撑起中小型项目的消息队列需求。
很多人上手直接用 LPUSH 丢数据、BRPOP 拿数据,看起来流程很顺,实际生产环境一碰就碎。BRPOP 一旦取出消息,客户端宕机或处理超时,这条记录就凭空蒸发。消息丢了顶多补录,要是库存扣了而发货单没生成,客诉电话能把运营打爆。所以,真正的 Redis 消息队列不是“取走即销毁”,而是“取走暂存+手动确认”。
落地这套逻辑,核心在于维护三个队列节点。生产者端通过 LPUSH queue:task payload 把 JSON 序列化后的指令拍进待处理区。先别急着在消费者里直接删数据,而是用 RPOPLPUSH 实现原子转移,把任务从“待处理”挪到“处理中”状态。这一步切断了重复消费的隐患,也为后续异常兜底铺好了轨道。
进入具体的业务执行层,数据库写入、外部接口调用都集中在这里。跑通成功的话,直接 REM queue:task:processing message_id 彻底清理;遇到异常则按性质分流。如果是网络抖动导致的临时失败,将任务扔进带分数字段的 ZSET 里,配合定时器按分值批量捞起重试;若是参数错误这类硬伤,直接推入 queue:task:deadletter,保留原始载荷供人工复核。整条链路不依赖重型组件,纯 Redis 命令就能闭环。
代码逻辑再严密,连接稳定性也是命门。长轮询的 BRPOP 如果频繁因网络闪断丢失,消费者极易陷入假死。建议在运行层采用短周期脚本配合 Crontab 滚动消费,而非强求 PHP 常驻后台。每次循环前执行 PING 探测存活状态,断线自动重建连接。PHP 天生不适合长时间挂起的守护进程,用调度器驱动高频短任务的模式,反而比硬保长连接更抗造。
当然,Redis 做队列有明确的边界。它不支持开箱即用的死信回溯路由,海量堆积时内存成本会线性飙升,复杂的多条件过滤也玩不转。但如果你的诉求只是削峰填谷、解耦非核心链路,或者团队暂时没人专职运维中间件,这套方案足够体面地托住日常流量。技术选型从来不是追新,而是看场景匹配度。把边界摸清楚,用对工具,剩下的就是踏实把业务逻辑写稳,让服务安安静静跑起来。


还没有评论,来说两句吧...