🌈简介
Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分:发布者
、订阅者
和Channel
。发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。Redis的这种发布订阅机制与基于主题的发布订阅类似,Channel相当于主题。
下图展示了频道 channel,以及订阅这个频道的三个客户端:client1 、 client2 和 client3 之间的关系:
当有新消息通过PUBLISH
命令发送给频道channel
时,这个消息就会被发送给订阅它的三个客户端:
🎈命令
发布消息PUBLISH
时间复杂度:O(N+M),其中 N 是频道 channel 的订阅者数量,而 M 则是使用模式订阅(subscribed patterns)的客户端的数量。
✏️语法:PUBLISH channel message
📃说明:将信息message发送到指定的频道channel。
🆗返回值:接收到信息message的订阅者数量。
上图中,我们使用 publish 指令向 pay_result_channel 这个频道发送了一条消息。我们可以看到 redis 向我们返回0,这其实代表当前订阅者个数,由于此时没有订阅,所以返回结果为0。
订阅频道消息: SUBSCRIBE
✏️语法:SUBSCRIBE channel [channel ...]
📃说明:订阅一个或者多个频道
🆗返回值:返回订阅的频道信息和消息内容。
如上图所示,我们订阅 pay_result_channel 这个频道,当有其他客户端往这个频道发送消息,当前订阅者就会收到消息。
模拟发布一条消息message is comming
到频道channel:
当前订阅者就会接收到一条消息:
另外,我们在使用订阅命令的时候,需要注意几点:
1️⃣ 客户端执行订阅指令之后,就会进入订阅状态,之后就只能接收 subscribe
、psubscribe
、unsubscribe
、punsubscribe
这四个命令。
2️⃣ 新订阅的客户端,是无法收到这个频道之前的消息,这是因为 Redis 并不会对发布的消息持久化的。
除了上面的功能以外的,Redis 还支持模式匹配的订阅方式。简单来说,客户端可以订阅一个带 *
号的模式,如果某些频道的名字与这个模式匹配,那么当其他客户端发送给消息给这些频道时,订阅这个模式的客户端也将会到收到消息
使用 Redis 订阅模式,我们需要使用一个新的指令 psubscribe
:
psubscribe pay.*
那么一旦有其他客户端往 pay
开头的频道,比如 pay_result_channel
、pay_xxx
,我们都可以收到消息。
如果需要取消订阅模式,我们需要使用相应punsubscribe
指令,比如取消上面订阅的模式:
punsubscribe pay.*
🔥Redis 客户端发布订阅使用方式
基于 Jedis 开发发布/订阅
聊完 Redis 发布订阅指令,我们来看下 Java Redis 客户端如何使用发布订阅。
Maven版本:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.0</version>
</dependency>
使用jedis
实现发布订阅很简单,只需要调用Jedis
类的publish
方法即可实现:
// 生产环境不建议这么使用哦,推荐使用 JedisPool 线程池的方式
Jedis jedis = new Jedis("localhost", 6379);
jedis.auth("xxxxx");
jedis.publish("pay_result_channel", "pay success!");
订阅的代码也不复杂,我们只需要继承 JedisPubSub
实现里面的相关方法,一旦有其他客户端往订阅的频道上发送消息,将会调用 JedisPubSub
相应的方法。
/**
* 自定义消息监听对象
*
* @author: jacklin
* @date: 2022-05-04 22:43
*/
@Component
public class MyCustomListener extends JedisPubSub {
@Override
public void onMessage(String channel, String message) {
System.out.println("收到订阅频道:" + channel + "的消息:" + message);
super.onMessage(channel, message);
}
@Override
public void onPMessage(String pattern, String channel, String message) {
System.out.println("收到具体订阅频道:" + channel + "订阅模式:" + pattern + " 的消息:" + message);
super.onPMessage(pattern, channel, message);
}
}
当有其他客户端往 pay_result_channel
频道发送消息时,订阅将会收到消息。
Connected to the target VM, address:'127.0.0.1:6379',transport:'socket'
收到订阅频道:pay_result_channel的消息:pay_suceess!
收到订阅频道:pay_result_channel的消息:pay_suceess_again!
以上仅仅是简单的实现逻辑,正式项目可以根据自己的业务场景加以实现~
总结
今天我们主要介绍 Redis 发布订阅功能,主要对应的 Redis 命令为:
subscribe channel [channel ...]
订阅一个或多个频道unsubscribe channel
退订指定频道publish channel message
发送消息psubscribe pattern
订阅指定模式punsubscribe pattern
退订指定模式
我们可以利用 Redis 发布订阅功能,实现的简单 MQ 功能,实现上下游的解耦。 不过需要注意了,由于 Redis 发布的消息不会被持久化,这就会导致新订阅的客户端将不会收到历史消息。
所以,如果当前的业务场景不能容忍这些缺点,那还是用专业消息队列MQ来实现。
收藏⭐️+关注👨🎓+留言📃