likes
comments
collection
share

【Redis】浅谈Redis的发布(Push)和订阅(sub)

作者站长头像
站长
· 阅读数 16

Hi,大家好,我是抢老婆酸奶的小肥仔。

上一篇我们讲了下Linux下安装redis及五大数据类型,详情参见:juejin.cn/post/723317… 下面我们来看看redis的发布/订阅。

在日常开发中我们很多时候会用到发布/订阅这种模式,例如常用的一些消息中间件就会有这种模式,redis中也提供了这种模式,让我们来看下吧。

redis发布订阅(push/sub)是一种消息通信模式:发布者(push)发布消息,订阅者(sub)接收消息。

客户端可以订阅任意数量的频道。

1、发布订阅流程

【Redis】浅谈Redis的发布(Push)和订阅(sub)

1、客户端订阅消息频道

2、发布者将消息发布到频道

3、频道将消息发送给订阅的客户端

2、发布/订阅命令

2.1 订阅

订阅命令:subscribe/psubscribe

//订阅一个活多个频道
subscribe channel1 channel2 ...

//订阅一个或多个符合给定模式的频道,以"*"作为匹配符,如:it*则表示匹配以it开头的所有频道
psubscribe pattern [pattern ...]

【Redis】浅谈Redis的发布(Push)和订阅(sub)

2.2 发布

发布命令:publish

//将msg发送到指定的频道
publish channel1 msg

【Redis】浅谈Redis的发布(Push)和订阅(sub)

切换订阅窗口,可看到接收到的信息

【Redis】浅谈Redis的发布(Push)和订阅(sub)

3、SpringBoot实现redis发布订阅

SpringBoot是我们常用的开发框架,也会经常用到redis做各种数据的缓存,而redis的发布订阅也在日常开发中常用到。

3.1 引入redis包

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3.2 配置消息监听类

3.2.1 实现MessageListener接口

/**
 * @author: jiangjs
 * @description: redis消息监听类
 * @date: 2023/4/7 11:10
 **/
@Slf4j
@Component
public class RedisMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
        byte[] body = message.getBody();
        byte[] channel = message.getChannel();
        log.info("------频道名称------:"+new String(channel));
        log.info("------消息内容------:"+new String(body));
    }
}

redis的start类中提供的MessageListener接口中的onMessage方法可以接收到用户发布的信息,我们获取到信息后就可以编写自己的业务。

3.2.2 创建MessageListenerAdapter适配的类

/**
 * @author: jiangjs
 * @description:
 * @date: 2023/4/7 14:32
 **/
@Slf4j
@Component
public class MessageReceiver {

    public void receive(String message,String channel) {
        log.info("------频道名称------:"+ channel);
        log.info("------消息内容------:"+ message);
    }
}

3.3 redis配置类,并监听渠道

配置文件配置订阅渠道信息:

#redis订阅频道
redis:
  channel: jiashn,lovejiashn

3.3.1 监听MessageListener

@Configuration
public class RedisConfig {
    
    @Value("${redis.channel}")
    private String channel;

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                                   RedisMessageListener listener){
        List<String> channels = Arrays.asList(StringUtils.split(channel, ","));
        List<ChannelTopic> topics = new ArrayList<>(channels.size());
        channels.forEach(cha -> topics.add(new ChannelTopic(cha)));
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        //订阅频道
        container.addMessageListener(listener,topics);
        return container;
    }
}

channel在配置文件中配置的渠道,创建container方法的参数中包含了第二步中的监听器,将监听器与频道进行绑定。RedisMessageListenerContainer redis消息监听容器可以将监听器与频道进行绑定,完成订阅频道。

3.3.2 监听MessageListenerAdpater

/**
 * @author: jiangjs
 * @description: redis配置类
 * @date: 2023/4/7 11:16
 **/
@Configuration
public class RedisConfig {
    
    @Value("${redis.channel}")
    private String channel;

    @Bean
    public MessageListenerAdapter adapter(MessageReceiver receiver){
        return new MessageListenerAdapter(receiver, "receive");
    }

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                                   MessageListenerAdapter adapter){
        List<String> channels = Arrays.asList(StringUtils.split(channel, ","));
        List<ChannelTopic> topics = new ArrayList<>(channels.size());
        channels.forEach(cha -> topics.add(new ChannelTopic(cha)));
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        //订阅频道
        container.addMessageListener(adapter,topics);
        return container;
    }
}

在redis配置里面中创建MessageListenerAdapter,通过该构造函数创建时需要绑定监听类(如:MessageReceiver)及监听的方法(如:MessageReceiver中的receive方法),然后再通过RedisMessageListenerContainer进行频道订阅。

3.4 发布信息

 @Autowired
private RedisTemplate<String,String> template;

@GetMapping("/send/{channel}/{msg}")
public ResultUtil<String> sendMessage(@PathVariable("channel") String channel,
                                      @PathVariable("msg") String msg){
    template.convertAndSend(channel,msg);
    return ResultUtil.success();
}

3.5 执行结果

在浏览器上访问接口地址,如:http://localhost:8000/send/jiashn/loveQueena 执行结果如下:

【Redis】浅谈Redis的发布(Push)和订阅(sub) 从执行结果,我们看到MessageReceiver类中的receive接收到了渠道/信息,实现了消息的发布/订阅。

上述就是redis的消息的发布/订阅,谢谢大家,希望对大家有所帮助,谢谢!