简介
Redis的发布订阅是一种消息通信模式,发送者发布消息,订阅者接收消息。
它们的关系如下图所示:
对于消息发布者和订阅者来说,其实都是多对多关系。发布者可以向多个channel发布消息,订阅者自然也可以从多个channel接收消息。
这种发布订阅模式其实很像各种MQ,但是相对于这些MQ,redis则更为轻量化,当业务压力不大的时候,可以考虑采用Redis来代替MQ实现消息队列。
下面我们用SpringBoot来写个小demo体验一把Redis的发布订阅。这里的环境,redis本地启动,没有密码。
代码实现-发布者
@RestController
public class PublisherController {
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping("/publish/{channel}/{message}")
public String publishMessage(@PathVariable("channel") String channel, @PathVariable("message") String message) {
redisTemplate.convertAndSend(channel, message);
return "success";
}
}
发布者的功能很简单,提供一个接口,可以实现往指定的channel发送消息即可。这里发送消息采用 redisTemplate
的 convertAndSend
功能来实现。
代码实现-订阅者
@Component
public class RedisSubscriber {
public void onMessage(String message, String pattern) {
System.out.println("订阅者1收到信息:" + message + ", 来自" + pattern + "频道");
}
}
@Component
public class AnotherRedisSubscriber {
public void onMessage(String message, String pattern) {
System.out.println("订阅者2收到信息:" + message + ", 来自" + pattern + "频道");
}
}
这里我们弄两个发布者,后面分别订阅不同的channel进行对比
代码实现-配置类
这里的配置类是最关键的,在配置类里面指定订阅者,以及订阅者要订阅的channel。
@Configuration
public class RedisConfig {
@Bean(name = "listener1")
public MessageListenerAdapter listener1Adapter(RedisSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
@Bean(name = "listener2")
public MessageListenerAdapter listener2Adapter(AnotherRedisSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
@Bean
public RedisMessageListenerContainer container(@Qualifier("listener1") MessageListenerAdapter adapter1,
@Qualifier("listener2") MessageListenerAdapter adapter2,
RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener(adapter1, Arrays.asList(new PatternTopic("channel1"), new PatternTopic("channel2")));
container.addMessageListener(adapter2, Arrays.asList(new PatternTopic("channel2"), new PatternTopic("channel3")));
return container;
}
}
可以看到,我们分别声明了两个订阅者listener1和2,然后让listener1订阅channel1和channel2,listener2订阅channel2和channel3。这样两个listener各自有自己独自订阅的channel,也有共同订阅的channel。这里由于同时声明了两个相同类型的bean,所以在注入的时候要用 @Qualifier
注解来指明。
效果演示
分别调用如下链接:
http://localhost:8080/publish/channel1/hello
http://localhost:8080/publish/channel2/hello
http://localhost:8080/publish/channel3/hello
http://localhost:8080/publish/channel4/hello
也就是分别向1,2,3,4这4个channel发送一条消息“hello”,这个时候我们查看日志
可以看到channel1和channel3,分别只有订阅者1和订阅者2接收到消息。channel2则是两个订阅者都能接收到消息。而channel4没有订阅者进行订阅,所以没有收到消息。到这里,redis的发布订阅功能就算是完成了。