zoukankan      html  css  js  c++  java
  • Redis key过期监听

    通过开启key过期的事件通知,当key过期时,会发布过期事件;我们定义key过期事件的监听器,当key过期时,就能收到回调通知。

    注意:

      1)由于redis key过期删除是定时+惰性,当key过多时,删除会有延迟,回调通知同样会有延迟。

      2)且通知是一次性的,没有ack机制,若收到通知后处理失败,将不再收到通知。需自行保证收到通知后处理成功。

            3)通知只能拿到key,拿不到value

    使用场景:

      1)实现延时队列

        消息作为key,将需要延迟的时间设置为key的TTL,当key过期时,在监听器收到通知,达到延迟的效果。

    步骤:  

      1、修改 redis.conf / redis.window.conf 

      开启 notify-keyspace-events Ex

      2、RedisConfig 中配置 Message Listener Containers (消息订阅者容器)

       类似于Redis pub/sub 中 Message Listener Containers 的配置,区别少了监听器的指定。

        @Bean
        public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
            // redis 消息订阅(监听)者容器
            RedisMessageListenerContainer messageListenerContainer = new RedisMessageListenerContainer();
            messageListenerContainer.setConnectionFactory(redisConnectionFactory);
            messageListenerContainer.addMessageListener(new ProductUpdateListener(), new PatternTopic("*.product.update"));
            return messageListenerContainer;
        }

      3、定义 key过期监听器,继承 KeyExpirationEventMessageListener

    @Component
    public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    
        /**
         * 创建RedisKeyExpirationListener bean时注入 redisMessageListenerContainer
         *
         * @param redisMessageListenerContainer RedisConfig中配置的消息监听者容器bean
         */
        public RedisKeyExpirationListener(RedisMessageListenerContainer redisMessageListenerContainer) {
            super(redisMessageListenerContainer);
        }
    
        @Override
        public void onMessage(Message message, byte[] pattern) {
            String channel = new String(message.getChannel()); // __keyevent@*__:expired
            String pa = new String(pattern); // __keyevent@*__:expired
            String expiredKey = message.toString();
            System.out.println("监听到过期key:" + expiredKey);
        }
    }

      可以看到,其本质是Redis的发布订阅,当key过期,发布过期消息(key)到Channel :__keyevent@*__:expired中,再看KeyExpirationEventMessageListener 源码:

    public class KeyExpirationEventMessageListener extends KeyspaceEventMessageListener implements ApplicationEventPublisherAware {
    
        // 发布key过期频道的topic
        private static final Topic KEYEVENT_EXPIRED_TOPIC = new PatternTopic("__keyevent@*__:expired");
    
        private @Nullable
        ApplicationEventPublisher publisher;
    
        /**
         * 子类在由Spring容器创建bean的时候调用父类的此构造器,并传入容器中的RedisMessageListenerContainer bean作为参数
         */
        public KeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer) {
            super(listenerContainer);
        }
    
        /**
         * doRegister 在 KeyspaceEventMessageListener(实现了InitializingBean和 MessageListener) 中的init方中被调用
         * 将我们自定义的key过期监听器添加到 消息监听容器中
         */
        @Override
        protected void doRegister(RedisMessageListenerContainer listenerContainer) {
            listenerContainer.addMessageListener(this, KEYEVENT_EXPIRED_TOPIC);
        }
    
        /**
         * 发布key过期事件
         *
         * @param message 过期key
         */
        @Override
        protected void doHandleMessage(Message message) {
            publishEvent(new RedisKeyExpiredEvent(message.getBody()));
        }
    
        /**
         * 由Spring RedisKeyExpiredEvent事件监听器执行实际上的redis key过期消息的发布
         */
        protected void publishEvent(RedisKeyExpiredEvent event) {
    
            if (publisher != null) {
                this.publisher.publishEvent(event);
            }
        }
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
            this.publisher = applicationEventPublisher;
        }
    }

      因此,我们定义的继承了KeyExpirationEventMessageListener的redis key 过期监听器本质上就是一个消息监听器,监听来自channel为__keyevent@*__:expired 上发布的消息

    END.

  • 相关阅读:
    asp.net页面刷新后样式就发生了改变
    ASP.NET MVC 入门系列教程
    javascript打开邮箱服务器
    jquery验证邮箱
    MySQL数据库的索引类型
    JS判断浏览器
    Silverlight 3 新特性
    moss 2007 添加关键字及最佳匹配
    vs2008 常用快捷键
    Microsoft Enterprise Library 5.0正式版本已经发布
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/14399707.html
Copyright © 2011-2022 走看看