一架梯子,一头程序猿,仰望星空!
Redis面试题 > 内容正文

Redis如何实现消息队列?


问题简答

Redis实现消息队列主要有下面3种方案:
1、List:使用Redis的List数据结构,将消息作为列表中的元素,通过LPUSH/RPUSH和LPOP/RPOP等命令进行消息的入队和出队操作。
2、Pub/Sub:使用Redis的发布订阅机制,将生产者发送的消息发布到一个频道,消费者通过订阅该频道来获取消息。
3、Stream:使用Redis 5.0引入的Stream数据结构,可以实现更复杂的消息队列功能,支持消息的按照时间顺序排序、多消费者并发消费、消息持久化等特性。

问题详解:

1.基于List实现队列

将数据放入队列尾部

LPUSH queue_name data

从队列头部取出数据

RPOP queue_name

获取队列长度

LLEN queue_name

2.基于发布订阅实现队列

作为消费者订阅一个频道(channel_name),接收消息

SUBSCRIBE channel_name

发布消息到频道

PUBLISH channel_name message

3.基于Stream原生队列

假设有多个服务器需要向一个日志中心发送日志,那么可以将日志写入一个Redis Stream中,具体步骤如下:

3.1.创建一个 Redis Stream

XGROUP CREATE logs consumer_group $ MKSTREAM

其中,logs 为 Stream 的名称,consumer_group 为消费者组名称,$ 表示没有消费者时自动创建,MKSTREAM 表示创建一个新的 Stream。

3.2.服务器向 Stream 中写入日志

XADD logs * server_name "server-1" log_content "this is a log message"

其中,* 表示使用当前最大的 ID 作为消息 ID,server_name 和 log_content 是消息的键值对。

3.3.消费者从 Stream 中读取日志

XREADGROUP GROUP consumer_group consumer_id COUNT 1 STREAMS logs >

其中,consumer_id 为消费者的名称,COUNT 1 表示每次最多读取一条消息,STREAMS logs > 表示从 logs 这个 Stream 中读取所有消息。

3.4.消费者确认已经消费了消息

XACK logs consumer_group message_id

其中,message_id 为消息的 ID,表示消费者已经处理了这条消息。

3种方案的优缺点对比

方案 优点 缺点
基于 List 的队列 实现简单,易于理解和维护 不支持消息广播,被多个业务订阅消息
发布订阅 支持消息广播,消费者可以自由订阅和取消订阅,可以支持多个消费者并发消费。 不支持消息的持久化,消息只能广播到所有订阅者,无法点对点发送,无法限制队列大小
基于 Stream 的队列 支持消息的持久化,支持消息的顺序消费,支持消费者分组,是功能完备的消息队列,推荐使用 相对于其他两种方案,使用起来相对复杂