关于redis的发布订阅模式,大家应该都有听过,具体的我就不阐述了,其实本质和传统的MQ的发布订阅是差不多的,但是相对于其它几款MQ产品来说,redis的使用更加便捷,也更加轻量化,不需要单独去搭建集成一套繁重的MQ框架,但缺点也很明显,redis发布的消息不会持久化,所以当某一台服务器出现问题的时候,这个消息会被丢失掉,就会导致数据问题,所以在考虑使用之前要慎重,当前的业务是否对数据一致性要求很高,如果要求很高,还是建议使用MQ产品。


简单记录一下的使用方法。


首先是环境,注意redis的版本需要在2.0以上就可以支持发布订阅模式了,项目环境就不说了,一个简单的springBoot工程,我的版本是2.1.1。


其实整个使用过程比较简单,只需要明白几个点就可以了,第一点是消息发布给谁?第二点是订阅消息的主体是谁?解决这两个问题之前,我们先看一下redisTemplate中发布消息的方法convertAndSend(),这个方法有两个参数:channelmessagemessage自然就是我们发送的消息内容,channel顾名思义即一个消息通道,用来连接订阅者的通道,这里需要有一个Topic(主题)的概念,Topic分为指定主题ChannelTopic和模糊主题PatternTopic,两者的区别就是一个明确指定订阅主体,一个可以模糊匹配订阅主体。所以当有了一个Topic后在发布消息的时候就可以知道是发给谁的了,也就知道了订阅方是谁了。

所以下一步需要做的就是将Topic订阅者绑定起来。在redis的配置文件中将二者关联起来。

首先我们构建一个监听类用来订阅消息

@Slf4j
public class SubListener {


}

redis配置文件

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
   


    /** redis发布/订阅模式配置*/

    @Bean
    public ChannelTopic pubTopic() {
        return new ChannelTopic("pub");
    }

    @Bean
    public SubListener subListener() {
        return new SubListener();
    }


    /**
     * redis消息容器
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        // 设置redis连接工厂
        container.setConnectionFactory(redisConnectionFactory);
        // 绑定订阅主题和监听器
        container.addMessageListener(subListener(), pubTopic());
        return container;
    }

}

在绑定主题和订阅者的时候会报错提示需要实现MessageListener接口中的onMessage方法,所以我们过去实现就可以了,当你收到订阅消息时,就可以在onMessage中进行处理。

至此,发布与订阅的关系就绑定上了,当在发布消息时使用该主题"pub"时,对应的SubListener就会收到消息。


主题可以配置多个,以用来处理不同的业务,使用上只需要注入主题选择对应的主题发送消息即可。

@Component
public class RedisCache {
    @Autowired
    public RedisTemplate redisTemplate;

    @Autowired
    @Qualifier("channelTopic")
    public ChannelTopic channelTopic;

    @Autowired
    @Qualifier("simpleDataTopic")
    public ChannelTopic simpleDataTopic;

    @Autowired
    @Qualifier("settingTopic")
    public ChannelTopic settingTopic;


    /**
     * redis发布消息 使用对应的主题发送消息,对应的订阅者便会收到消息
     */
    public void convertAndSend(Object message) {
        redisTemplate.convertAndSend(channelTopic.getTopic(), message);
    }

    public void simpleDataTopicSend(Object message) {
        redisTemplate.convertAndSend(simpleDataTopic.getTopic(), message);
    }

    public void settingTopicSend(Object message) {
        redisTemplate.convertAndSend(settingTopic.getTopic(), message);
    }

不足之处,或有问题之处还请指出。