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

Redis消息队列传输体验有啥新变化,和以前那些差别到底在哪儿呢

要聊Redis消息队列的新变化和旧差别,咱们得先看看它以前是啥样的,以前提到Redis做消息队列,大家脑子里蹦出来的基本上就是两个东西:ListPub/Sub(发布/订阅),这两种方式简单直接,但用久了就会发现各有各的“坑”。

(来源:基于Redis官方文档及社区长期实践共识) 先说老的List,它就像是邮局寄信,生产者用LPUSH命令把消息“塞进”列表的头部,消费者用BRPOP命令从列表尾部“取出”消息,这种方式的好处是消息不会丢,因为数据是持久化在Redis里的,消费者没来取,信就一直在邮局等着,这就是所谓的“可靠队列”,但它的毛病也很明显:一个消息只能被一个消费者处理,如果你想搞成多个消费者同时干活儿的“工作组”模式,那就得想别的办法,比如给每个消费者分配一个单独的列表,管理起来很麻烦。

(来源:基于Redis官方文档及社区长期实践共识) 再说老的Pub/Sub,它更像是一个广场上的大喇叭广播,生产者发布一条消息到一个频道(Channel),所有订阅了这个频道的消费者都能同时收到,这解决了“一对多”广播的问题,但它的“坑”更大:消息是即时的,不持久化,如果某个消费者当时不在线,或者网络闪断了一下,那对不起,这条消息就永远错过了,喇叭只喊一遍,所以它只适合那种丢了也没关系的场景,比如实时推送在线用户的状态更新。

新变化的核心是什么呢?就是Redis在5.0版本推出的 Stream 数据类型。(来源:Redis 5.0 Release Notes) Stream的出现,就是为了弥补List和Pub/Sub的不足,它把两者的优点结合了起来,并且加了很多强大的新功能。

差别到底在哪儿?咱们一项项对比看:

第一,从“单播”到“多播”且可靠。 这是最核心的差别,List是可靠的“单播”(一对一),Pub/Sub是不可靠的“多播”(一对多),而Stream实现了可靠的“多播”,它就像一个有组织的快递站,生产者发送的每一条消息都会被持久化下来,并且有一个唯一的、递增的ID(比如时间戳-序列号),消费者们可以组成一个“消费者组”(Consumer Group)。(来源:Redis官方文档关于Streams和Consumer Groups的说明)

这个组的概念是革命性的,同一个组内的消费者是竞争关系,一条消息只会被组内的一个消费者拿到并处理,这就实现了负载均衡,多个工人可以一起干活儿,不同的消费者组之间是隔离的,同一个消息可以被多个不同的组各自独立地消费一遍,一条“用户下单成功”的消息,A组(负责发短信)和B组(负责更新库存)可以同时收到并处理,互不干扰,这就既实现了Pub/Sub的广播能力,又保证了List的可靠性。

第二,消息处理有了“回执”机制。 用老的List,消费者用BRPOP取出消息后,Redis就把消息删了,如果消费者处理到一半崩溃了,这条消息就永远丢失了,Stream引入了“待处理消息列表”(Pending Entries List, PEL)的概念。(来源:Redis官方文档关于XPENDING命令的说明) 消费者从组里领取一条消息后,这条消息并不会立刻从Stream中删除,而是标记为“待处理”状态,只有当消费者明确发送一个“确认完成”(XACK)的命令后,Redis才会认为这条消息处理成功了,并将其从待处理列表中移除。

如果消费者挂了,超过一定时间没有确认,这条消息就会被重新放回队列,分配给组内其他健康的消费者去处理,这就确保了“至少处理一次” 的可靠性,再也不用担心因为程序崩溃而丢消息了。

第三,可以“回溯”消费,就像看直播回放。 这是以前完全不具备的能力,对于Stream,新消费者可以随时“上车”,它可以选择从最新的消息开始消费,也可以说“我想从三天前的第一条消息开始看”,直接回溯历史,这在业务上非常有用,比如今天上线了一个新的数据分析程序,它可以轻松地把过去几天的数据重新处理一遍,而不用去打扰生产数据库。

第四,功能更精细,更像专业的消息队列。 Stream还提供了一些很细致的功能,比如可以限制Stream的最大长度,实现一个“循环队列”,避免内存无限增长;可以查看消费者组的状态,有多少消息待处理,哪个消费者卡住了等等,运维起来 visibility (可见性)非常好。

Redis消息队列的体验,从以前需要开发者自己用List或Pub/Sub“凑合”、并处理各种边界问题的“手工模式”,进化到了Stream提供的“一站式”解决方案。(来源:基于对Redis Streams设计目标的业界普遍理解) 它带来的新变化,本质上是让Redis从一个简单的缓存和数据存储,真正变成了一个功能完备、高可靠、支持复杂业务场景的消息中间件,差别就在于,以前你需要操心怎么保证消息不丢、怎么实现多消费者,现在这些底层烦恼,Stream都给你包了,你只需要关心业务逻辑本身就行。

Redis消息队列传输体验有啥新变化,和以前那些差别到底在哪儿呢