虽然redis也能实现发布订阅, 但术业有专攻, 发布订阅还是要使用mq中间件!
- 虽然redis实现了发布订阅(publish/subscribe)的功能,但是在通常的情况下是不推荐使用的,如果想使用消息队列这种功能,最好还是使用专业的各种MQ中间件,例如rabbitMQ,rockedMQ,activitedMQ等,本文主要讲一下不推荐使用redis的发布订阅功能的原因
- 第一个原因是和redis系统的稳定性有关。对于旧版的redis来说,如果一个客户端订阅了某个或者某些频道,但是它读取消息的速度不够快,那么不断的积压的消息就会使得redis输出缓冲区的体积越来越大,这可能会导致redis的速度变慢,甚至直接崩溃。也可能会导致redis被操作系统强制杀死,甚至导致操作系统本身不可用。新版的redis不会出现这种问题,因为它会自动断开不符合client-output-buffer-limit pubsub配置选项要求的订阅客户端
- 第二个原因是和数据传输的可靠性有关。任何网络系统在执行操作时都可能会遇到断网的情况。而断线产生的连接错误通常会使得网络连接两端中的一端进行重新连接。如果客户端在执行订阅操作的过程中断线,那么客户端将会丢失在断线期间的消息,这在很多业务场景下是不可忍受的。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
// 生产者
@Service
public class MyPublisher {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 跟rabbitmq的 queue是一样的 订阅topic
public static final String test_subscribe_topic = "test-topic";
private ChannelTopic topic = new ChannelTopic(test_subscribe_topic);
public void sendMsg(String msg) {
redisTemplate.convertAndSend(topic.getTopic(), "收到消息了吗!:" + msg);
}
}
// 消费者
@Service
public class MyListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println(new String(message.getBody()));
}
}
// 配置类
@Configuration
public class SubConfig {
@Bean
MessageListenerAdapter messageListener() {
return new MessageListenerAdapter(new MyListener());
}
@Bean
RedisMessageListenerContainer redisContainer(RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
// 支持多个topic
container.addMessageListener(messageListener(), new ChannelTopic(MyPublisher.test_subscribe_topic));
return container;
}
}
测试
@Autowired
private MyPublisher msgPublisher;
@Test
void test1(){
msgPublisher.sendMsg("哈喽啊树哥");
}