news 2026/7/30 16:59:17

redis 自定义事件监听,支持单机、集群、哨兵

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
redis 自定义事件监听,支持单机、集群、哨兵

为什么要自定义事件监听呢?当然是为了在redis进行某些事件动作的时候增加一些咱们自己的业务逻辑处理,比如:当key失效的时候,处理业务逻辑--支付订单半小时未支付就自动取消订单。这就可以用key失效事件监听来实现。下面就来讲解怎么实现:

1.首先自定义一个消息工厂

此处不要自己再重新获取连接自定义连接池。直接使用redis现有的连接池即可。

package com.liu.redisexpired; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import reactor.util.annotation.NonNull; /** * 自定义Redis键空间监听器⼯⼚ * @author kevin * @date 2022/6/7 */ @Slf4j public class RedisMessageListenerFactory implements BeanFactoryAware, ApplicationListener<ContextRefreshedEvent> { //spring bean工厂 private DefaultListableBeanFactory beanFactory; //redis连接工厂 private RedisConnectionFactory redisConnectionFactory; //redis消息监听 @Autowired private MessageListener messageListener; public void setBeanFactory(@NonNull BeanFactory beanFactory) { this.beanFactory = (DefaultListableBeanFactory) beanFactory; } public void setRedisConnectionFactory(RedisConnectionFactory redisConnectionFactory) { this.redisConnectionFactory = redisConnectionFactory; } /** * 自定义事件监听 * @author kevin * @date 2022/5/27 */ @Override public void onApplicationEvent(@NonNull ContextRefreshedEvent contextRefreshedEvent) { //定义一个单例bean,设置连接工厂为redis的连接工厂,然后注册到spring容器 BeanDefinitionBuilder containerBeanDefinitionBuilder = BeanDefinitionBuilder .genericBeanDefinition(RedisMessageListenerContainer.class); containerBeanDefinitionBuilder.addPropertyValue("connectionFactory", redisConnectionFactory); containerBeanDefinitionBuilder.setScope(BeanDefinition.SCOPE_SINGLETON); containerBeanDefinitionBuilder.setLazyInit(false); beanFactory.registerBeanDefinition("myRedisKeyListenerContainer", containerBeanDefinitionBuilder.getRawBeanDefinition()); //从spring工厂容器获取消息监听容器,配置消息监听器 RedisMessageListenerContainer container = beanFactory.getBean("myRedisKeyListenerContainer", RedisMessageListenerContainer.class); //设置监听正则,监听节点所有key的所有事件 container.addMessageListener(messageListener, new PatternTopic("__keyevent@*__:*")); container.afterPropertiesSet(); //开始监听 container.start(); } }

2.将消息工厂注入spring容器

在你的redisconfig配置中加入代码,主要看最后一个方法:

package com.liu.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import com.liu.redisexpired.RedisMessageListenerFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { /** * 配置第一个数据源的RedisTemplate * 注意:这里指定使用名称=factory 的 RedisConnectionFactory * 并且标识第一个数据源是默认数据源 @Primary * @author kevin * @param redisConnectionFactory : * @return org.springframework.data.redis.core.RedisTemplate * @date 2022/5/26 */ @Bean("redisTemplate") @Primary public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { return getRedisTemplate(redisConnectionFactory); } /** * redis操作工具获取redisTemplate * @author kevin * @param factory : redis连接工厂 * @return org.springframework.data.redis.core.RedisTemplate<java.lang.String,java.lang.Object> * @date 2022/5/27 12:00 */ private RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL) //过期方法 om.activateDefaultTyping( LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } /** * 自定义redis消息监听工厂 * @author kevin * @date 2022/5/27 */ @Bean public RedisMessageListenerFactory redisMessageListenerFactory( BeanFactory beanFactory, RedisConnectionFactory redisConnectionFactory) { RedisMessageListenerFactory beans = new RedisMessageListenerFactory(); beans.setBeanFactory(beanFactory); beans.setRedisConnectionFactory(redisConnectionFactory); return beans; } }

3.编写消息监听:

编写一个监听器,实现MessageListener接口,实现onMessage方法,得到的message就可以监听所有的key的事件了。此处只监听了key的过期事件,然后打印了一句日志,如果需要其他操作,可直接在此处改写即可

package com.liu.redisexpired; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.stereotype.Component; /** * 事件触发监听器 * @author kevin * @date 2022/5/27 */ @Slf4j @Component public class KeyEventMessageListener implements MessageListener { /** * 监听获取redis键消息 * @author kevin * @param message : 事件消息体 * @param pattern : 事件监听,消息主题(订阅频道),如: * __keyevent@*__:* 所有key的所有事件 __keyevent@a__:* key为a的所有事件 * __keyevent@a__:expired key为a的key过期事件 * @date 2022/5/27 11:05 */ @Override public void onMessage(Message message, byte[] pattern) { //获取redis操作类型: set、expire、expired等操作 String action = new String(message.getChannel()); action = action.split(":")[1]; //获取redis操作的key String key = new String(message.getBody()); //判断失效的key,且是请求限流的key if("expired".equals(action) && key.startsWith("request_limit_")){ log.info("监听到的键:{},已经失效,请求限流已取消!", key); } } }

此处作者监听的是以request_limit_开头的键失效事件(做接口限流的时候,顺便整了一下键事件监听)。

4. 然后验证:

启动你的项目,然后使用你的项目设置一个键并设置失效事件;

或者直接连接redis命令行,先通过如下命令连接redis命令行:

redis-cli -h 127.0.0.1 -p 6379 -a xxx

在命令行中执行命令添加一个键值,并设置过期时间为2秒:

set request_limit_test 1 PX 2000

然后查看项目的控制台是否有对应的输出:

以上就是所有内容

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/30 16:54:27

想选箱式变电站预制舱制造厂家?这些挑选要点你知道吗?

引言预制舱在电力系统中应用广泛&#xff0c;尤其箱式变电站预制舱&#xff0c;其质量对电力供应稳定性至关重要。面对众多制造商&#xff0c;如何做出正确选择成为关键问题。泰安市宏正电器有限公司作为此类产品的专业制造商&#xff0c;在行业内表现出色。制造实力与规模选择…

作者头像 李华
网站建设 2026/7/30 16:49:03

OAuth 2.0安全增强与FIPS合规:MCP场景下的JARM、JOSE、DPoP实战指南

1. 项目概述&#xff1a;当“合规”成为技术升级的硬约束最近和几个负责企业身份认证与API安全的老朋友聊天&#xff0c;大家不约而同地提到了一个词&#xff1a;焦虑。焦虑的来源&#xff0c;正是OAuth 2.0安全增强框架&#xff08;OAuth 2.0 Security Best Current Practice&…

作者头像 李华
网站建设 2026/7/30 16:48:35

热敏电阻深度解析:从NTC/PTC原理到硬件设计实战

你有没有遇到过这样的情况&#xff1a;一个电路板在常温下工作正常&#xff0c;一到夏天就频繁重启&#xff1b;或者一个充电器在冬天充电速度明显变慢&#xff0c;甚至无法正常充电&#xff1f;这些看似玄学的问题&#xff0c;背后往往藏着一个关键元件——热敏电阻。作为硬件…

作者头像 李华
网站建设 2026/7/30 16:47:52

GHelper终极指南:如何用轻量级控制工具完美替代Armoury Crate

GHelper终极指南&#xff1a;如何用轻量级控制工具完美替代Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenb…

作者头像 李华
网站建设 2026/7/30 16:47:50

Input Leap终极指南:3分钟实现跨平台键鼠共享

Input Leap终极指南&#xff1a;3分钟实现跨平台键鼠共享 【免费下载链接】input-leap Open-source KVM software 项目地址: https://gitcode.com/gh_mirrors/in/input-leap Input Leap是一款功能强大的开源KVM软件&#xff0c;让你能够用一套键盘鼠标无缝控制多台计算机…

作者头像 李华