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();
    }
}
相关推荐
juniperhan9 分钟前
Flink 系列第 3 篇:核心概念精讲|分布式缓存 + 重启策略 + 并行度 底层原理 + 代码实战 + 生产规范
大数据·分布式·缓存·flink
紫青宝剑21 分钟前
向量数据库 Milvus
数据库·milvus
雪碧聊技术22 分钟前
数据库系统基础知识
数据库
Elastic 中国社区官方博客22 分钟前
如何使用 LogsDB 降低 Elasticsearch 日志存储成本
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索·可用性测试
Dreamboat-L23 分钟前
HBase远程访问配置(详细教程)
大数据·数据库·hbase
架构师老Y23 分钟前
012、缓存架构设计:Redis高级应用与优化
redis·python·架构
難釋懷24 分钟前
Nginx实现本地缓存查询
nginx·spring·缓存
刘~浪地球24 分钟前
数据库与缓存--Redis 集群架构与优化
数据库·redis·缓存
羊小蜜.26 分钟前
Mysql 11: 存储过程全解——从创建到使用
android·数据库·mysql·存储过程
A__tao27 分钟前
一键实现 SQL 转 Elasticsearch Mapping(支持字段注释 + meta 描述)
数据库·sql·elasticsearch