Redis高级:消息队列
1 认识消息队列
什么是消息队列:字面意思就是存放消息的队列。最简单的消息队列模型包括3个角色:
- 消息队列:存储和管理消息,也被称为消息代理(Message Broker)
- 生产者:发送消息到消息队列
- 消费者:从消息队列获取消息并处理消息
使用消息队列的好处在于解耦:生产者将消息发送到消息队列中,不必等待消费者接收消息,而消费者只需要在消息队列中有消息时取出来进行处理即可,这样就实现了消息发送与处理的解耦,因为这个过程是异步实现的
常见的消息队列相信大家都有所了解,例如rabbitmq,kafka等等,其实redis也是可以用来做消息队列的
2 基于List实现消息队列
Redis的List数据结构是一个双向链表,很容易模拟出队列效果。
消息队列的消息入口和消息出口不在同一边,而List数据结构中提供了相应的命令,我们可以在List左侧插入数据然后在右侧取出,或则在右侧插入然后在左侧取出,对应的命令就是LPUSH与RPOP或者RPUSH与LPOP。但是我们需要注意的是如果我们使用RPOP或者LPOP取出数据时,如果队列中没有数据,是会直接返回null的,如果我们想模拟出阻塞队列的效果(即队列中没有数据时会阻塞等待,直到有数据时再取出),这里应该使用BRPOP或者BLPOP
演示如下:
首先开启两个redis客户端,客户端一模拟生产者,客户端二模拟消费者
首先在客户端二输入以下命令:
# 在key为k1的list右侧阻塞式地获取一条数据 等待时间为1000秒
brpop k1 1000
当我们回车后,客户端二会进入阻塞,因为此时k1中是没有数据的
在客户端一中输入以下命令:
# 在k1中插入一条数据
lpush k1 v1
此时再看客户端二,就发现客户端二已经拿到了数据:
基于List实现的消息队列有哪些优点和缺点?
优点:
- 利用Redis服务的内存进行消息存储
- 基于Redis的持久化机制,数据安全性有保证
- 可以满足消息有序性
缺点:
- 无法避免消息丢失,当消息被消费者取出之后,就已经在List中被移除了,如果该消费者出现故障等因素没有处理消息,那么这条消息就永久丢失了
- 只支持单消费者,List中的消息只能被一个消费者接受并消费,无法实现一条消息被很多消费者消费的需求。
3 基于PubSub的消息队列
PubSub(发布订阅)是Redis2.0版本引入的消息传递模型。顾名思义,消费者可以订阅一个或多个channel,生产者向对应channel发送消息后,所有订阅者都能收到相关消息。
相关命令如下:
- subscribe channel [channel] :订阅一个或多个频道
- publish channel msg :向一个频道发送消息
- psubscribe pattern [pattern] :订阅与pattern格式匹配的所有频道
关于 PubSub 的具体命令使用方法可以参看官网:https://redis.io/commands/?group=pubsub
具体演示如下:
首先开启三个客户端,客户端一模拟生产者,客户端二与客户端三模拟消费者
客户端二中执行以下命令:
#