自学内容网 自学内容网

spring boot整合Redis监听数据变化

一、前言

Redis提供了数据变化的通知事件,可以实时监测key和value的变化,客户端可以通过订阅相关的channel来接收这些通知事件,然后做相应的自定义处理,详细的介绍可以参考官方文档Redis keyspace notifications | Docs

使用Redis时,可以在配置文件中管理相应的配置,默认配置是不开启事件通知的。

############################# Event notification ##############################

# Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at http://redis.io/topics/notifications
#
# For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key "foo" stored in the Database 0, two
# messages will be published via Pub/Sub:
#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  K     Keyspace events, published with __keyspace@<db>__ prefix.
#  E     Keyevent events, published with __keyevent@<db>__ prefix.
#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
#  $     String commands
#  l     List commands
#  s     Set commands
#  h     Hash commands
#  z     Sorted set commands
#  x     Expired events (events generated every time a key expires)
#  e     Evicted events (events generated when a key is evicted for maxmemory)
#  A     Alias for g$lshzxe, so that the "AKE" string means all the events.
#
#  The "notify-keyspace-events" takes as argument a string that is composed
#  of zero or multiple characters. The empty string means that notifications
#  are disabled.
#
#  Example: to enable list and generic events, from the point of view of the
#           event name, use:
#
#  notify-keyspace-events Elg
#
#  Example 2: to get the stream of the expired keys subscribing to channel
#             name __keyevent@0__:expired use:
#
#  notify-keyspace-events Ex
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
notify-keyspace-events ""

二、整合方案

1、自定义监听事件

该方案是自定义监听器messageListener,监听指定的频道"__keyevent@*",表示监听所有事件,这种方案比较灵活,可以自定义监听的事件频道。但是,这种需要redis服务配置开启通知,例如配置notify-keyspace-events为AKE,表示开启全部事件通知。如果redis配置不正确,是不会通知指定事件的。另外,如果修改了该配置还需要重启Redis服务,所以慎重选择该方式。

redis配置如下:

# redis配置开启全部事件通知
notify-keyspace-events AKE

 代码部分如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@Configuration
public class RedisListenerConfig {

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        // 订阅一个全部变化事件频道 __keyevent@*
        container.addMessageListener(listenerAdapter, new PatternTopic("__keyevent@*"));

        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter() {
        // 如果使用自定义方法myHandleMessage,就把方法名作为第二个参数添入
        // return new MessageListenerAdapter(new RedisKeyChangeSubscriber(), "myHandleMessage");
        // 如果不传入第二个参数,则会使用默认方法handleMessage
        return new MessageListenerAdapter(new RedisKeyChangeSubscriber());
    }

    public static class RedisKeyChangeSubscriber {
        // 自定义处理方法
        public void myHandleMessage(String message) {
            System.out.println("RedisKeyChangeSubscriber Received message: " + message);
            // 在这里处理收到的消息
        }

        // message对应redis数据的key
        public void handleMessage(String message) {
            System.out.println("RedisKeyChangeSubscriber Received message: " + message);
            // 在这里处理收到的消息
        }
    }
}

测试效果:

①创建键值对{"key1": "val1"}

2、继承spring boot集成的监听器KeyspaceEventMessageListener

spring官方提供的redis starter依赖包含了事件变化监听器KeyspaceEventMessageListener,是个抽象类,可以通过继承这个抽象类重写doHandleMessage方法来自定义数据变化的处理逻辑。这种方式不需要关注Redis配置,简化了监听事件变化的处理,容易上手。没有特别要求的话,也推荐使用这种方式。同样的,该依赖也提供了redis数据过期事件的监听器KeyExpirationEventMessageListener,用于监听redis数据过期的事件,使用方法和KeyspaceEventMessageListener大体一致,但是KeyExpirationEventMessageListener不是抽象类。

import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.KeyspaceEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@Configuration
public class RedisListenerConfig {

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);

        return container;
    }

    @Bean
    RedisKeyChangerHandler redisKeyChangerHandler(RedisMessageListenerContainer container) {
        return new RedisKeyChangerHandler(container);
    }

    public static class RedisKeyChangerHandler extends KeyspaceEventMessageListener {
        /**
         * Creates new {@link KeyspaceEventMessageListener}.
         *
         * @param listenerContainer must not be {@literal null}.
         */
        public RedisKeyChangerHandler(RedisMessageListenerContainer listenerContainer) {
            super(listenerContainer);
        }

        @Override
        // message对应redis数据的key
        protected void doHandleMessage(@NotNull Message message) {
            System.out.println("KeyspaceEventMessageListener Received message: " + message);
        }
    }
}

测试效果同方案一。 


原文地址:https://blog.csdn.net/jrx1995/article/details/137675309

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!