Redis队列其实没那么难,教你几招用起来更顺手点
- 问答
- 2025-12-29 21:49:21
- 2
说到Redis,大家可能最先想到的是用它来存缓存,让网站或者应用跑得更快,但其实Redis的列表结构,拿来当消息队列用,那可是相当顺手的一件利器,你可能觉得“队列”这个词听起来有点技术化,有点复杂,但其实它的想法特别简单直接,就像我们去超市买东西排队结账一样,先来的人先结账,后来的人排在后面,在程序世界里,队列干的就是这个活儿:把一个个需要处理的任务排好队,然后让处理程序(我们一般叫它消费者)一个一个按顺序来取、来处理。
那为什么用Redis而不用专业的队列软件呢?原因很简单:轻便、快速、够用,很多项目一开始可能并不需要像RabbitMQ、Kafka那样重量级的消息中间件,它们功能强大但同时也更复杂,而Redis通常项目里已经在用了,直接用它的列表功能来实现队列,不用引入新的技术组件,运维起来也简单,而且Redis本身速度极快,对于大多数中小规模的应用场景,性能完全不是问题。
第一招:学会最基本的“推”和“拉”
Redis队列用起来最核心的两个命令就是LPUSH和RPOP(或者BRPOP)。
- LPUSH:意思是“从左边推入”,比如你的程序产生了一个发送邮件的任务,你就执行
LPUSH task_queue "send_email_to_user123",把这个任务消息塞到名叫task_queue的队列的最左边(也就是头部)。 - RPOP:意思是“从右边弹出”,另一边,你有一个专门发邮件的后台程序,它就不停地执行
RPOP task_queue,从队列的最右边(也就是尾部)取出一个任务来处理。
这样一来,就形成了一个标准的先进先出队列:先被LPUSH进去的任务,会慢慢地被挤到队列的右边,然后被RPOP取走,这就是最基础的队列模型了,非常简单直观。
第二招:让消费者“聪明”地等待,别傻等着

上面说的RPOP有个小问题:如果队列是空的,它立马就返回一个空值,那你的后台消费者程序可能就会写成一个死循环,不停地执行RPOP,队列空的时候就空转,这纯粹是在浪费CPU资源,我们管这个叫“忙等待”。
Redis提供了一个更聪明的命令:BRPOP,这个B代表的是“Blocking”(阻塞),用法和RPOP差不多,但是可以设置一个超时时间,比如BRPOP task_queue 30,它的意思是:去队列task_queue里取任务,如果队列里有任务,立马取出来;如果队列是空的,那我就在这儿阻塞等待,最多等30秒,在这30秒内,只要一有任务被LPUSH进来,我马上就能拿到并返回,如果等了30秒还没任务,它才返回空。
这样一来,你的消费者程序就不用傻乎乎地空转了,可以安心“睡大觉”,有活来了再干,极大地减少了系统资源的消耗,这是使用Redis队列时必须掌握的一个关键技巧。
第三招:处理任务时要做到“万无一失”

想象一个场景:消费者程序用RPOP或者BRPOP从队列里取走了一个任务,正准备处理的时候,突然这个程序崩溃了!这下糟了,任务已经从队列里移走了,但又没处理成功,这个任务就彻底丢失了。
为了解决这个问题,Redis提供了一个更稳妥的方案,我们可以不用RPOP,而是用LRANGE之类的命令看一眼任务,但先不删除它,但这样自己实现起来有点麻烦,Redis有更好的原生支持吗?有的,不过这可能稍微涉及到一点点进阶概念,但我们尽量简单说。
你可以把任务从一个队列(比如task_queue)用LMOVE命令(或者旧版本用RPOPLPUSH)原子性地移动到另一个“进行中”的队列(比如processing_queue),原子性的意思是这个操作一步完成,不会被打断,这样,后台程序从task_queue取任务的同时,任务已经被安全地转移到了processing_queue,等任务处理成功后,程序再自己把任务从processing_queue里删除。
如果中途程序崩溃了,没关系,这个任务还安然无恙地待在processing_queue里,你可以再写一个监控程序,定期去检查processing_queue里有哪些任务停留时间太长了,说明处理它们的程序可能出问题了,就把这些任务重新放回主队列task_queue,让其他健康的消费者重新处理,这样就保证了即使处理失败,任务也不会丢,这个模式通常被称为“可靠队列”。(根据开源社区最佳实践和Redis官方文档中关于模式设计的思路)

第四招:来点“优先级”,让紧急任务插个队
标准的队列是严格先进先出的,但有时候会有特殊情况,有一个普通订单任务在排队,突然来了一个VIP用户的加急订单,希望能优先处理。
在Redis里实现优先级队列有很多种方法,这里说一种最简单易懂的:创建多个队列,你创建三个队列:queue_high(高优先级)、queue_normal(普通优先级)、queue_low(低优先级)。
你的后台消费者程序在取任务的时候,不再只盯着一个队列了,而是按照优先级顺序来检查:BRPOP queue_high queue_normal queue_low 30,这个命令的意思是:先检查queue_high有没有任务,有就取出来;如果没有,再检查queue_normal有没有;如果还没有,最后检查queue_low,如果所有队列都为空,就阻塞等待30秒。
这样,只要高优先级队列里有任务,就会一直被优先处理,只有当高优先级队列清空时,才会去处理普通优先级的任务,实现起来非常简洁有效。
总结一下
你看,Redis队列的核心思想就是这么几步:生产者用LPUSH发任务,消费者用BRPOP(或配合LMOVE实现可靠队列)取任务,如果需要优先级就多建几个队列,它没有想象中那么神秘和复杂,对于很多项目来说,用上这几招已经完全足够应对日常开发中的异步处理需求了,而且能让你系统的响应速度和稳定性都得到很大的提升,下次当你需要解耦系统、削峰填谷或者处理异步任务时,不妨先考虑一下这个轻量又强大的Redis队列方案。
本文由度秀梅于2025-12-29发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/70887.html
