相关推荐recommended
监听Redis中Key值的变化(SpringBoot整合)
作者:mmseoamin日期:2024-04-29

一、概念

当Redis中的值发生改变时,通过配置来监听key值的变化。

事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 因此所有支持订阅与发布功能的客户端都可以在无须做任何修改的情况下, 直接使用键空间通知功能。

二、配置

因为开启键空间通知功能需要消耗一些 CPU , 所以在默认配置下, 该功能处于关闭状态。

可以通过修改 redis.conf 文件, 或者直接使用 CONFIG SET 命令来开启或关闭键空间通知功能。

notify-keyspace-events 的参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知:

监听Redis中Key值的变化(SpringBoot整合),第1张

第一种方式:直接使用命令

第一步:开启

config set notify-keyspace-events KEA

监听Redis中Key值的变化(SpringBoot整合),第2张

第二步:订阅

另起一个窗口,用于监听。

psubscribe '__key*__:*'                   #对所有库键空间通知
psubscribe '__keyspace@5__:*'             #是对db5数据库键空间通知
psubscribe '__keyspace@5__:order*'        #是对db5数据库,key前缀为order所有键的键空间通知

监听Redis中Key值的变化(SpringBoot整合),第3张

出现以上形式表明订阅成功。

第三步:添加数据

set k1 v1

监听Redis中Key值的变化(SpringBoot整合),第4张

监听Redis中Key值的变化(SpringBoot整合),第5张

这就是配置成功了。

【推荐】第二种方式:修改配置文件

如果使用第一种方式的话,当关闭窗口时,再次使用的话,还需要重新输入,而修改配置文件则不用重复操作。

第一步:找配置文件

在安装的路径中找到redis.windows.conf

点击快捷键"ctrl+F",输入:notify-keyspace-events

监听Redis中Key值的变化(SpringBoot整合),第6张

第二步:修改配置文件

改为:notify-keyspace-events KEA

点击"ctrl+S"保存并关闭

第三步:使用命令启动Redis

将Redis注册成一个服务启动,这样就不用每次开机手动启动了,而且不用一直用黑窗口打开了。

找到Redis的安装路径,然后进入,输入cmd

监听Redis中Key值的变化(SpringBoot整合),第7张

输入命令:

redis-server.exe --service-install redis.windows.conf 

这样在服务中就可以找到了。

监听Redis中Key值的变化(SpringBoot整合),第8张

三、整合SpringBoot

1.加入依赖


     org.springframework.boot
     spring-boot-starter-data-redis

2.配置文件

spring:
    redis:
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器端口号
        port: 6379
        # 使用的数据库索引,默认是0
        database: 0
        # 连接超时时间
        timeout: 1800000
        # 设置密码
        password: 
        lettuce:
            pool:
                # 最大阻塞等待时间,负数表示没有限制
                max-wait: -1
                # 连接池中的最大空闲连接
                max-idle: 5
                # 连接池中的最小空闲连接
                min-idle: 0
                # 连接池中最大连接数,负数表示没有限制
                max-active: 20

3.配置类

package com.redisDemo.config;
import com.example.redisDemo.controller.RedisReceiver;
import com.example.redisDemo.listener.*;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.net.UnknownHostException;
/**
 * @author lenovo
 */
@Configuration
public class RedisConfig {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedisUpdateAndAddListener redisUpdateAndAddListener;
    @Autowired
    private RedisDeleteListener redisDeleteListener;
    @Autowired
    private RedisHashUpdateAndAddListener redisHashUpdateAndAddListener;
    @Autowired
    private RedisListUpdateAndAddListener redisListUpdateAndAddListener;
    @Autowired
    private RedisSetUpdateAndAddListener redisSetUpdateAndAddListener;
    @Autowired
    private RedisSortUpdateAndAddListener redisSortUpdateAndAddListener;
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //监听所有的key的set事件
        container.addMessageListener(redisUpdateAndAddListener, redisUpdateAndAddListener.getTopic());
        //监听所有key的删除事件
        container.addMessageListener(redisDeleteListener,redisDeleteListener.getTopic());
        container.addMessageListener(redisHashUpdateAndAddListener,redisHashUpdateAndAddListener.getTopic());
        container.addMessageListener(redisListUpdateAndAddListener,redisListUpdateAndAddListener.getTopic());
        container.addMessageListener(redisSetUpdateAndAddListener,redisSetUpdateAndAddListener.getTopic());
        container.addMessageListener(redisSortUpdateAndAddListener,redisSortUpdateAndAddListener.getTopic());
        //监听所有key的过期事件
//        container.addMessageListener(redisExpiredListener,redisExpiredListener.getTopic());
        return container;
    }

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        // 创建模板
        RedisTemplate redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // key和 hashKey采用 string序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // value和 hashValue采用 JSON序列化
        redisTemplate.setValueSerializer(RedisSerializer.string());
        redisTemplate.setHashValueSerializer(RedisSerializer.string());
        return redisTemplate;
    }
}

4.监听类

监听所有类型的删除操作:

package com.redisDemo.listener;
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisDeleteListener implements MessageListener {
 
    //监听主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:del");
 
    /**
     *
     * @param message 消息
     * @param pattern 主题
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key的删除,消息主题是:"+ topic+",消息内容是:"+msg);
    }
}

监听hash类型新增/修改: 

package com.redisDemo.listener;
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisHashUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:hset");
 
    @Override
    public void onMessage(Message message, byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }
 
}

监听list类型的添加/修改: 

package com.redisDemo.listener;
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisListUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:lpush");
 
    @Override
    public void onMessage(Message message, byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }
 
}

 监听set类型新增/修改:

package com.redisDemo.listener;
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisSetUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:sadd");
 
    @Override
    public void onMessage(Message message, byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }
 
}

监听zset类型新增/修改: 

package com.redisDemo.listener;
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisSortUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:zadd");
 
    @Override
    public void onMessage(Message message, byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }
 
}

监听string类型新增/修改: 

package com.redisDemo.listener;
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:set");
 
    @Override
    public void onMessage(Message message, byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }
 
}

5.启动项目

在Redis图形化界面添加一个数据

监听Redis中Key值的变化(SpringBoot整合),第9张

监听Redis中Key值的变化(SpringBoot整合),第10张

这下就成功监听到了。

如果没有监听到,请确保Redis正常启动了。

分享就到这里了,欢迎各位批评指正。