为什么需要Redis作为消息队列
有些简单的业务场景,可能不需要重量级的 MQ 组件(相比 Redis 来说,Kafka 和 RabbitMQ 都算是重量级的消息队列)。 公司某个微服务中只有一个地方需要用到消息队列(中的发布/订阅场景),并且场景也不复杂,就可以使用Redis作消息队列。
消息队列的模式
两大类:
- 点对点(point to point queue)
- 每个消息只有一个接收者(Consumer),一旦被消费,消息就不再存在于消息队列中。
- 发送者和接收者间没有依赖性,发送者发送消息之后,不管有没有接收者在运行,都不会影响到发送者下次发送消息。
- 接收者在成功接收消息之后需要向队列应答成功,以便消息队列删除当前接收的消息。
- 发布/订阅(publish/subscribe,topic)
- 每个消息可以有多个订阅者。
- 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
- 为了消费消息,订阅者需要提前订阅该角色主题,并保持在线运行。
点对点
发布/订阅
"发布/订阅"模式同样可以实现进程间的消息传递。
"发布/订阅"模式包含两种角色,分别是发布者和订阅者。订阅者可以订阅一个或者多个频道(channel),而发布者可以向指定的频道(channel)发送消息,所有订阅此频道的订阅者都会收到此消息。
Redis 通过 PUBLISH 、 SUBSCRIBE 等命令实现了订阅与发布模式, 这个功能提供两种信息机制, 分别是订阅/发布到频道和订阅/发布到模式。
这个 频道 和 模式 有什么区别呢?
频道我们可以先理解为是个 Redis 的 key 值,而模式,可以理解为是一个类似正则匹配的 Key,只是个可以匹配给定模式的频道。这样就不需要显式的去订阅多个名称了,可以通过模式订阅这种方式,一次性关注多个频道。
发布订阅 代码实现方式
除了redis基本依赖和配置,主要分为三部分:
- 配置
@Configuration
public class RedisConfig {
@Autowired
AConsumerRedisListener aConsumerRedisListener;
@Autowired
BConsumerRedisListener bConsumerRedisListener;
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
//将消息侦听器添加到(可能正在运行的)容器中。 如果容器正在运行,则侦听器开始接收(匹配)消息。
container.addMessageListener(messageListener(), new PatternTopic("topica"));
return container;
}
}
- 发送方
redisTemplate.convertAndSend("TopicName", message);
- 消费方
@Service
public class RedisMessageSubscriber implements MessageListener {
public static List<String> messageList = new ArrayList<String>();
public void onMessage(Message message, byte[] pattern) {
messageList.add(message.toString());
System.out.println("Message received: " + message.toString());
}
}
当我们调用 convertAndSend 时,内容被发送到 Redis,在那里它被路由到我们的发布者中定义的消息队列主题。然后将它分发给该主题的订阅者。 RedisMessageSubscriber 是一个侦听器,它将自己注册到队列以检索消息。 消息到达时,订阅者定义的 onMessage() 方法被触发。