使用Redis实现消息队列有两种方式:list队列模式以及发布订阅模式。
一、list队列模式
1、list队列的原理
在上一篇文章《Redis(一):Redis数据类型和常用命令》中已经详细讲解了Redis中list相关的操作。list底层是个双向链表,头部和尾部的操作效率非常高,其操作命令也符合队列API的行为方式。我们在使用list作为消息队列的时候,会使用lpush
命令将消息放入队列,使用rpop
命令将消息出队列。

需要注意的是rpop
命令是一次性命令,它在执行前并不知道消息队列中是否有消息,可以预料到的是,如果队列中一直没有消息,只能通过rpop
命令一直轮询。为了解决这个问题,可以使用brpop命令:
brpop key [key ...] timeout
brpop命令中的timeout参数是必传的,当它为0的时候表示无限期阻塞等待;不为零的时候计时结束就会自动放弃阻塞等待。
brpop命令返回值有两个值,第一个值是key的名字,第二个值是弹出的元素值,如果从队列中取不出来数据,会一直阻塞,在一定范围内没有取出则返回null。需要注意brpop命令并不会阻塞主线程,brpop虽然是个阻塞命令,但是它会通过如下机制避免阻塞主线程:
-
非忙等待:当
BRPOP
监听列表为空时,Redis 会将客户端连接标记为“阻塞状态”,并将其从活跃客户端列表中移除,主线程不会持续轮询或等待,而是继续处理其他请求 -
事件驱动:Redis 使用事件循环(如
epoll
)管理客户端连接。阻塞的客户端会被挂起,直到目标列表有新元素插入时,Redis 通过事件回调唤醒对应的客户端连接
2、list队列演示
第一步:进入容器
我在6.2.1版本的redis下做个演示。由于我使用了docker,所以需要先进入我的redis容器(容器名为redis):
docker exec -it redis /bin/bash
然后进入redis-cli命令所在的目录:
cd /usr/local/bin
运行redis-cli命令:
./redis-cli
进入redis交互命令行,执行auth命令做个认证:
auth 123456
依照此步骤打开三个会话页面:

第二步:发送/接收消息
三个会话中,第一个会话用于向队列发送消息,第二个和第三个会话使用brpop命令接收消息。

可以看到,brpop命令即使key不存在,也可以持续监听,并且当key被创建而且list中有值时会自动将值取出来。多个监听者可以同时监听同一个消息队列,但是同一个值只能被一个监听者获取到。
二、发布订阅模式
1、发布订阅模式简介
发布订阅模式和rabbitmq消息队列的topic模式很像,多个客户端订阅同一个channel,channel发布消息的时候,每个客户端都能收到相同的消息。

消息订阅命令:subscribe channel [channel ...]
,也就是说该命令可以订阅多个channel。

消息发送命令:publish channel message
该命令只能向一个channel发送命令。
全部命令如下所示:
命令 | 描述 |
---|---|
publish channel message |
将信息发送到指定的频道。 |
subscribe channel [channel ...] |
订阅给定的一个或多个频道的信息。 |
pubsub subcommand [argument [argument ...]] |
查看订阅与发布系统状态。PUBSUB CHANNELS :列出当前活跃的频道PUBSUB NUMSUB [channel ...] :返回指定频道的订阅者数量 |
unsubscribe [channel [channel ...]] |
指退订给定的频道。 目前还不知道如何在redis-cli中执行该命令,因为ctrl+c就已经实现退订了。 |
psubscribe pattern [pattern ...] |
订阅一个或多个符合给定模式的频道。 |
punsubscribe [pattern [pattern ...]] |
退订所有给定模式的频道。 |
2、发布订阅模式演示
接下来打开三个客户端,一个用于发布,另外两个用来订阅。

3、发布订阅模式分析
发布订阅模式的优点:发布者和订阅者不需要知道彼此的存在,功能解耦。
发布订阅模式的缺点:
- 消息没有持久化,如果消费者不在线,消息会丢失
- 没有ack机制,无法保证消息被成功消费。
- 同样因为没有持久化,如果消费者断线重连,中间的消息会丢失。
- Redis服务重启后消息会丢失。
综合来看,redis在消息队列方面功能并不完善,如果需要用到消息队列,最好使用专业的消息队列中间件,比如rabbitmq、kafka等。
当然,redis5中引入了Stream,Stream做了数据的持久化处理,一定方面弥补了发布订阅模式的缺点。。。建议还是不要用。
注意:本文归作者所有,未经作者允许,不得转载