当前位置:首页 > 问答 > 正文

Redis里头消息队列那些事儿,聊聊它怎么用和为啥挺实在

Redis里头消息队列那些事儿,聊聊它怎么用和为啥挺实在 主要参考自官方文档、Redis实战书籍及相关技术社区讨论)

Redis这玩意儿,别看它主要是个内存数据库,用来缓存数据快得飞起,但它里面那个叫“列表”(List)的数据结构,稍微变通一下,就能变成一个特别简单、好用的消息队列,咱们今天就聊聊这个,不整那些高大上的专业术语,就说点实在的。

它到底是个啥?咋工作的?

你可以把Redis的消息队列想象成一个长长的管道,或者一个真实的队伍,有人从队伍的一头往里放东西(这叫生产者),另一个人从队伍的另一头取东西(这叫消费者),在Redis里,这个“队伍”就是一个列表(List)。

放东西有两个主要命令:

  • LPUSH:从队伍的左边(头部)把消息塞进去,好比有人插队插到了最前面。
  • RPUSH:从队伍的右边(尾部)把消息加进去,这是正常排队,排在最后。

取东西也有两个对应的命令:

  • RPOP:从队伍的右边(尾部)取走一条消息,就像队伍末尾的人办完事离开了。
  • LPOP:从队伍的左边(头部)取走一条消息。

最常见的用法就是,生产者用 LPUSH 把任务塞进队列(这样新任务总是在最前面),消费者用 BRPOP 从队列尾部取任务,这个 BRPOP 里的“B”很关键,它代表“阻塞”,意思是:如果队伍是空的,我没东西可拿,那我就在这儿等着,直到有东西进来或者等到超时,这比傻乎乎地不停用 RPOP 去问“有吗有吗?”要高效得多,不会浪费资源。

这玩意儿具体能干啥用?

这东西在项目里可实用了,举几个接地气的例子:

  1. 削峰填谷,防止系统被冲垮:比如你的网站有个“秒杀”活动,一瞬间几万人都点按钮下单,如果你的系统直接去处理每个下单请求,数据库可能瞬间就挂了,这时候可以用Redis队列,秒杀请求来了,不直接处理,而是飞快地 LPUSH 扔进队列,然后告诉用户“正在排队中”,后台有几个消费者程序用 BRPOP 不紧不慢地从队列里取请求,一个一个地处理,这样,巨大的流量洪峰就被这个队列这个“水库”给缓冲了,后端系统平稳运行。

    Redis里头消息队列那些事儿,聊聊它怎么用和为啥挺实在

  2. 异步处理,不让用户干等着:比如用户上传个视频,你马上转码成各种清晰度,这个转码过程很慢,如果让用户上传后一直等着转码完成,体验太差了,这时候就可以用队列,用户上传成功后,就把“需要转码这个视频”的任务扔进队列,然后立刻告诉用户“上传成功,正在处理”,后台的转码程序再去队列里取任务慢慢处理,用户不用等,系统吞吐量也高了。

  3. 系统之间解耦:比如A系统完成了一件事,需要通知B、C两个系统,如果A系统直接去调用B和C的接口,万一B系统挂了或者改了接口,A系统就麻烦了,用消息队列就简单了,A系统只需要把通知消息往队列里一丢,它的任务就完成了,B系统和C系统自己订阅这个队列,各自取消息处理,A系统根本不用关心B和C到底是谁、在干嘛、有没有挂,它们之间就“解耦”了。

为啥说它挺实在?有啥好?

  1. 简单到没朋友:上手极其容易,就用几个基本的Redis命令,几分钟就能搭起一个能用的消息队列,对于很多中小项目来说,没必要一开始就上RabbitMQ、Kafka那种重型武器,Redis队列够用且高效。

  2. 速度是王牌:因为Redis的数据都在内存里,所以消息的写入和读取速度极快,延迟极低,每秒处理几万条消息很轻松,这对于需要快速响应的场景非常关键。

  3. 持久化是个安心丸:Redis虽然主打内存,但它支持把数据持久化到硬盘上(虽然这会影响一点性能),这意味着即使Redis服务重启了,队列里的消息一般也不会丢(取决于配置),这比纯内存队列靠谱多了。

    Redis里头消息队列那些事儿,聊聊它怎么用和为啥挺实在

也得知道它有哪些不尽如人意的地方

Redis消息队列也不是万能的,它比较“轻量”,所以有些高级功能是没有的。

  • 没有ACK确认机制:消费者用 RPOP 取走消息,这条消息就在队列里彻底消失了,如果消费者拿到消息后,还没来得及处理就崩溃了,那这条消息就永远丢失了,专业的消息队列一般有“确认”机制,消费者处理完才告诉队列可以删了。

    • 变通办法:Redis也有办法,比如可以用 BRPOPLPUSH 命令,把消息从一个主队列取出来,同时塞进一个“进行中”的队列,等消费者处理完了,再从“进行中”队列删掉,如果消费者挂了,我们可以手动把“进行中”队列的消息重新放回主队列,但这需要自己写代码实现,比较麻烦。
  • 严格来说不算“发布订阅”:Redis的列表队列是“点对点”的,一条消息只能被一个消费者取走,如果你想实现一条消息被多个消费者同时收到(比如群发通知),Redis有另一个叫“发布/订阅(Pub/Sub)”的功能,但那个功能消息是“即时的”,不持久化,消费者掉线就收不到历史消息了。

  • 消息堆积能力有限:因为Redis依赖内存,如果生产者速度远大于消费者,消息在队列里大量堆积,会把内存撑爆,而Kafka那种消息队列是把消息存在硬盘上的,堆积能力要强得多。

总结一下

Redis提供的消息队列是一个非常轻量、高速、简单的解决方案,它特别适合那些消息量不大、对速度要求高、允许极少量消息丢失、或者作为项目初期原型的场景,它能实实在在地解决“削峰填谷”、“异步处理”、“系统解耦”这些核心问题,但如果你需要 guaranteed delivery(消息保证送达)、复杂的路由规则、海量消息堆积,那还是得上专业的消息中间件,先拿Redis队列上手,体会一下消息队列的好处,等业务真的复杂到它扛不住了,再升级也不迟。