Redis消息列队实操,帮你搞定异步那些烦人的问题,直接上手不绕弯
- 问答
- 2026-01-12 23:02:14
- 1
主要参考了我在实际项目中的经验,以及一些像“菜鸟教程”这样的网站对Redis列表命令的基础讲解,还有像“掘金”这类技术社区里一些开发者分享的用Redis做简单消息队列的案例,我不会讲那些复杂的Stream类型,就聚焦在最基本、最实用的列表操作上,保证你能立刻看懂并用起来。
想象一下这个场景,你写了一个网站,用户注册成功后,你需要做两件事:一是发一封欢迎邮件,二是给用户塞几张优惠券,如果你在用户点击“注册”按钮的那个请求里,直接把发邮件和发优惠券的代码都写完,那用户可能得等上好几秒才能看到注册成功的页面,因为发邮件、调优惠券接口都是比较慢的操作,用户才不管你呢,他只会觉得你的网站“卡死了”。
这时候,消息队列就来帮大忙了,它的核心思想就四个字:异步处理,别让用户干等着,我们先快速把最重要的活儿干了(比如把用户数据存进数据库),然后把那些耗时的“琐事”(发邮件、发优惠券)写一张“小纸条”,扔进一个“盒子”里,接着就可以马上告诉用户“注册成功啦!”,后面我们再找个“专人”(另一个程序)去“盒子”里取“小纸条”,一条一条地去处理这些琐事,这样,用户的感觉就流畅多了。
Redis的List(列表)数据结构,天生就是干这个的,它就像一个长长的管子,我们可以从一头塞东西(生产者),从另一头取东西(消费者)。
第一步:把任务塞进队列(生产者干活)
假设我们用一个叫 task_queue 的List作为消息队列,用户注册成功后,我们不用真的去发邮件,而是创建一个任务数据,为了方便,我们一般把任务内容写成JSON字符串。
可能是:{"type": "send_email", "user_id": 12345, "email": "user@example.com"}
在Redis里,我们用一个非常简单的命令把这个任务塞到队列的右边(尾部):
RPUSH task_queue '{"type": "send_email", "user_id": 12345, "email": "user@example.com"}'
RPUSH 命令就是往列表的右边添加一个元素,你甚至可以一口气塞多个任务,这一步非常快,因为只是往内存里写点数据,瞬间就完成了,做完这一步,处理用户注册请求的那个程序就可以立刻返回结果给用户了,它已经完成了它的使命。
第二步:找个专人处理队列(消费者干活)
“琐事”的任务已经躺在 task_queue 这个队列里了,我们需要另写一个程序,或者启动一个后台进程,让它专门盯着这个队列,这个“专人”就是消费者。
消费者会不停地问Redis:“task_queue 队列里有新任务吗?” 它使用的命令是:
BLPOP task_queue 0
这个命令很关键,得仔细说说:
BLPOP是LPOP的阻塞版本。LPOP是从列表左边取出一个元素,如果列表是空的,它就立刻返回空。- 但
BLPOP不一样,后面的0代表阻塞时间(单位是秒),如果队列是空的,它不会走开,而是会一直等在那里,直到有新的任务被塞进来,或者等到超过指定的时间(比如设成5,就等5秒),我们这里设成0,意思就是“死等”,永远不超时,直到有新任务来为止。
这样做的好处是,消费者程序不会傻乎乎地不停用LPOP命令去问(这叫做“轮询”,浪费CPU资源),而是安安静静地等待,一旦有活来了,Redis会立刻通知它,它再起来干活,非常高效。
第三步:消费者处理任务
当 BLPOP 命令从队列里拿到一个任务字符串(就是我们之前塞进去的JSON)后,消费者程序就开始它的工作了。
- 解析任务:把JSON字符串解析成对象,看看
type是什么,是发邮件还是发优惠券。 - 执行逻辑:根据任务类型,调用不同的函数,如果
type是send_email,就调用发邮件的代码;如果是send_coupon,就调用发优惠券的代码。 - 处理异常:这一步很重要!发邮件可能会失败(比如邮件服务器抽风了),所以一定要用
try...catch把处理逻辑包起来,如果失败了,你有几种选择:- 重试:把任务重新放回队列(再用
RPUSH塞回去),但最好记录一下重试次数,超过3次就别再试了,可能是有无法修复的错误。 - 记录错误:把失败的任务和错误信息记录下来,比如写到一个特殊的“失败队列”或者日志文件里,方便以后人工处理。
- 重试:把任务重新放回队列(再用
处理完一个任务后,消费者会自动进行下一次 BLPOP,继续等待新任务,这样,它就成了一个不知疲倦的“打工人”,7x24小时地帮你处理这些异步任务。
实际动手的小提示
- 启动消费者:这个消费者程序需要是一个长期运行的后台进程,在你自己的电脑上开发时,你可以直接跑一个脚本,在服务器上,你可以用
systemd之类的工具来管理它,确保它挂了能自动重启。 - 多个消费者:如果一个消费者处理得太慢,任务堆积起来了怎么办?很简单,多启动几个消费者进程就行了!它们会同时用
BLPOP去监听同一个task_queue,Redis会保证一个任务只会被其中一个消费者拿到,不会出现重复处理的情况,这就是所谓的“负载均衡”,非常简单就实现了。 - 缺点也要知道:用Redis列表做简单消息队列非常棒,但它不像RabbitMQ、Kafka那些专业的消息队列软件,它不提供“消息确认(Ack)”机制,也就是说,万一消费者拿到任务后,还没来得及处理就崩溃了,这个任务就永远丢失了(因为已经被
BLPOP移出队列了),对于要求绝对不丢消息的场景,这可能是个问题,但在很多可靠性要求不是极端高的场景下(比如发通知、更新缓存),它的简单和高效是最大的优点,如果你需要更可靠,可以去研究Redis的Stream数据类型,但那会复杂一些。
核心流程就是:Web程序快速RPUSH任务 -> 后台消费者用BLPOP死等任务 -> 拿到任务后处理 -> 处理完继续等,这个模式能解决你绝大部分“不想让用户等待”的烦人问题,赶紧找个例子试试看吧!

本文由度秀梅于2026-01-12发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/79582.html
