Redis Spring Data监听指定key的hset事件失败,求正确配置方案
如何监听Redis指定Key的HSet命令事件?
问题描述
使用Spring Data Redis配置消息监听器时,希望仅监听前缀为SampleProj:Message:*的Key的hset命令事件,但当前配置能接收该Key的所有事件(如del、hset等),尝试多种PatternTopic模式均无效:
现有配置:
@Bean public RedisMessageListenerContainer redisMessageListenerContainer( RedisConnectionFactory connectionFactory, MyMessageListener myMessageListener) { RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer(); listenerContainer.setConnectionFactory(connectionFactory); listenerContainer.addMessageListener(myMessageListener, new PatternTopic("__keyspace@*__:SampleProj:Message:*")); return listenerContainer; }
尝试过的无效模式:
new PatternTopic("__keyevent*:hset SampleProj:Message:*") new PatternTopic("__keyevent@*__:hset:SampleProj:Message:*")); new PatternTopic("__keyevent@*__:hset SampleProj:Message:*"));
甚至尝试组合模式列表:
Arrays.asList(new PatternTopic("__keyevent@*__:hset SampleProj:Message:"), new PatternTopic("__keyspace@*__:SampleProj:Message:* hset")));
解决方案
要实现仅监听指定Key的hset事件,需结合Redis的键空间/键事件通知机制,以及监听器内的过滤逻辑,以下两种方案均可实现:
方案1:监听键空间通知,在监听器内过滤命令
Redis的键空间通知频道格式为__keyspace@db__:key,消息内容为触发的命令名。保持原有频道订阅,在监听器中仅处理hset命令:
- 容器配置保持不变:
@Bean public RedisMessageListenerContainer redisMessageListenerContainer( RedisConnectionFactory connectionFactory, MyMessageListener myMessageListener) { RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer(); listenerContainer.setConnectionFactory(connectionFactory); listenerContainer.addMessageListener(myMessageListener, new PatternTopic("__keyspace@*__:SampleProj:Message:*")); return listenerContainer; }
- 修改
MyMessageListener的onMessage方法,过滤命令:
@Override public void onMessage(Message message, byte[] pattern) { // 获取触发的命令 String command = new String(message.getBody()); // 仅处理hset命令 if ("hset".equals(command)) { // 编写业务逻辑,可提取目标Key String targetKey = new String(message.getChannel()).split(":")[2]; System.out.println("收到指定Key的hset事件:" + targetKey); } }
方案2:监听键事件通知,在监听器内过滤Key
Redis的键事件通知频道格式为__keyevent@db__:command,消息内容为触发事件的Key名。订阅hset命令的事件频道,再在监听器中过滤符合前缀的Key:
- 修改容器配置,订阅hset的键事件频道:
@Bean public RedisMessageListenerContainer redisMessageListenerContainer( RedisConnectionFactory connectionFactory, MyMessageListener myMessageListener) { RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer(); listenerContainer.setConnectionFactory(connectionFactory); // 订阅所有数据库的hset命令事件 listenerContainer.addMessageListener(myMessageListener, new PatternTopic("__keyevent@*__:hset")); return listenerContainer; }
- 修改
MyMessageListener的onMessage方法,过滤Key:
@Override public void onMessage(Message message, byte[] pattern) { // 获取触发事件的Key String key = new String(message.getBody()); // 仅处理前缀为SampleProj:Message:*的Key if (key.startsWith("SampleProj:Message:")) { // 编写业务逻辑 System.out.println("收到指定Key的hset事件:" + key); } }
关键注意事项
- Redis服务器配置:必须确保Redis开启了键空间/键事件通知,修改Redis配置文件(redis.conf)中的
notify-keyspace-events参数,例如设置为EA(E表示开启键事件通知,A表示监听所有命令)或EH(仅监听哈希相关命令)。若使用Spring Boot,可在application.properties中配置:
spring.redis.notify-keyspace-events=EA
- 无效模式原因:Redis的订阅频道格式是固定的,键事件频道仅支持
__keyevent@db__:command格式,键空间频道仅支持__keyspace@db__:key格式,无法直接在频道中同时指定命令和Key,因此之前尝试的混合模式均无法生效。
内容的提问来源于stack exchange,提问作者Prabhakaran
相关产品推荐
相关产品推荐

