redis发布订阅

命令行使用发布订阅:

springboot使用发布订阅

redisTemplate.convertAndSend(channel名字,数据)

springboot中监听redis发布的内容,,有两种方式:

  • 实现MessageListener类
java 复制代码
/**
 * 实现接口  消费
 */
@Component
public class MyConsumer01 implements MessageListener {
    @Autowired
    RedisTemplate redisTemplate;


    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 消息的内容
        byte[] body = message.getBody();
        String s = new String(body);

        // 用默认的序列化器,,序列化
        Book book = (Book) redisTemplate.getValueSerializer().deserialize(body);
        System.out.println("book = " + book);
        System.out.println("s = " + s);
    }
}
  • 自定义类,,因为是自定义的类,,所以需要一个适配器把他转换成 MessageListener 才能使用
java 复制代码
@Component
public class MyConsumer02 {

    /**
     * 这个方法你想怎么写怎么写,,但是需要配置注册进去 ===》 通过一个适配器,,去适配
     * @param message
     * @param channel
     */
    public void receiveMessage(Book message, String channel){
        System.out.println("message = " + message);
    }
}

这个自定义的监听器需要通过适配器适配:

java 复制代码
  /**
     * 给自定义的 MyConsumer02 来适配
     * @return
     */
    @Bean
    MessageListenerAdapter messageListenerAdapter(){
        // 告诉他 接收消息的方法
        MessageListenerAdapter receiveMessage = new MessageListenerAdapter(myConsumer02, "receiveMessage");

        // 这个反序列化不会平白无故的转成  想要的类型 ===> 设置反序列化方式
        // 将来收到消息之后,,会通过这里设置的序列化方案,,进行反序列化
        receiveMessage.setSerializer(new GenericJackson2JsonRedisSerializer());
        return receiveMessage;
    }

想让这两个监听器生效,,还需要配置监听器,,设置这两个监听器,,去监听,,哪些通道:

java 复制代码
   @Bean
    RedisMessageListenerContainer container(MyConsumer01 myConsumer01, MessageListenerAdapter messageListenerAdapter, RedisConnectionFactory redisConnectionFactory){
        // 注册监听器
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.addMessageListener(myConsumer01,new ChannelTopic(CHANNEL_01));
        container.addMessageListener(messageListenerAdapter,new PatternTopic(CHANNEL_02));

        return container;

    }

收发对象可以定义序列化方案,,, 对象的序列化和反序列化,,一般都用GenericJackson2JsonRedisSerializer

java 复制代码
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        return redisTemplate;
    }

redisTemplate 里面有方法能直接处理二进制,,redisTemplate.getValueSerializer().deserialize(body); 可以直接将二进制按照 value的序列化器去 序列化


队列

redis中list可以做队列,,它里面有block开头的,,,阻塞队列,,,阻塞多少时间才去执行,,,

list做队列,,必须自己去通过死循环,,或者定时器,,去拉取list中的内容,,,, 他没有自己的监听器,,没法监听,,,

但是list中有一种阻塞队列,,,就是阻塞多少时间,,如果这个时间到了,,才放弃阻塞,,,这就能避免无限空死循环,,,

java 复制代码
package com.cj.pub_sub_demo.consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class MyConsumerList01 {

    @Autowired
    StringRedisTemplate redisTemplate;


    public void receive(){

        while (true){
            // 延迟获取消息
            String o = (String) redisTemplate.opsForList().rightPop("list_mq",10, TimeUnit.SECONDS);
            if (o != null){
                System.out.println("收到消息 = " + o);
            }else{
                System.out.println("111");
            }
        }

    }


    public void blockReceive() throws InterruptedException {
        // bound 之后不用绑定key
        BoundListOperations listMq = redisTemplate.boundListOps("list_mq");

        // 接下来都是绑定key的
        while (true){
            Object o = listMq.rightPop();
            if (o != null){
                System.out.println(o);
            }else{
                Thread.sleep(1000);
            }
        }

    }
}

这个队列,可以在springboot刚启动的时候,就开启这个死循环:

java 复制代码
/**
 * 1. 数据预加载 :  在启动时向数据库插入默认数据,配置信息,,或者测试数据
 * 2. 缓存预热 :从数据库加载热点数据到redis缓存中
 * 3. 资源检查: 验证外部服务,,如邮件服务器,文件存储是否可用
 * 4. 执行命令行逻辑: 对于非web应用,,如批处理任务,,在这里编写主要的业务逻辑
 * 5. 发送启动通知,通知监控系统或日志系统 已启动成功
 */
@Component

public class MyCommandRunner implements CommandLineRunner {
    @Autowired
    MyConsumerList01 myConsumerList01;
    @Override
    public void run(String... args) throws Exception {

        myConsumerList01.receive();
    }
}
相关推荐
lusklusklusk11 分钟前
Oracle数据库基础之11_Duplicate和Dataguard和RAC
数据库·oracle
hweiyu0015 分钟前
Redis命令:HPERSIST
redis·缓存
hweiyu0021 分钟前
Redis命令:HPEXPIRE
redis·缓存
PHP实战开发录1 小时前
MySQL字段加索引为什么没变快
数据库·mysql·php·开发
红红谈说3 小时前
标签化推送与已读统计怎么做?一次通知链路的工程复盘
数据库·消息推送·数字乡村·集合运算·已读回执·标签体系·写入放大
Shadow(⊙o⊙)3 小时前
MySQL索引
数据库·mysql
starzy19904 小时前
Flink 优化之网络缓存优化及参数详解:从数据传输机制到反压原理的生产调优指南
网络·缓存·flink
ShineWinsu4 小时前
对于Redis:string类型的解析
java·c++·redis·分布式·缓存·面试·string
倔强的石头_5 小时前
多环境配置治理:开发、测试、生产连接信息如何隔离
数据库
杨云龙UP5 小时前
一次数据库查询缓慢故障复盘:大表数据增长、SQL全表扫描导致系统响应异常
linux·运维·服务器·数据库·sql·mysql