美文网首页
Redis监听新增、修改、删除、过期事件

Redis监听新增、修改、删除、过期事件

作者: 黄宝玲_1003 | 来源:发表于2019-10-28 10:15 被阅读0次

前言

项目中需要监听redis的一些事件比如键删除,修改,过期等。过期事件网上有很多例子可以参考,但修改或删除事件却很少。因为redis支持发布订阅所以其他的事件类型应该也是能实现的,通过过期事件监听结合上文键空间通知,我整理了相关代码,希望帮助需要的人快速解决问题。

代码实践

网上示例的失效事件监听代码

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    /**
     * 针对redis数据失效事件,进行数据处理
     * @param message message.toString()获取失效的key
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expiredKey = message.toString();
        // 获得key之后可以做自己的逻辑操作
        }
    }
}

可以看到继承了KeyExpirationEventMessageListener ,这是spring框架已经集成实现的。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.redis.listener;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisKeyExpiredEvent;
import org.springframework.lang.Nullable;

public class KeyExpirationEventMessageListener extends KeyspaceEventMessageListener implements ApplicationEventPublisherAware {
    private static final Topic KEYEVENT_EXPIRED_TOPIC = new PatternTopic("__keyevent@*__:expired");
    @Nullable
    private ApplicationEventPublisher publisher;

    public KeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    protected void doRegister(RedisMessageListenerContainer listenerContainer) {
        listenerContainer.addMessageListener(this, KEYEVENT_EXPIRED_TOPIC);
    }

    protected void doHandleMessage(Message message) {
        this.publishEvent(new RedisKeyExpiredEvent(message.getBody()));
    }

    protected void publishEvent(RedisKeyExpiredEvent event) {
        if (this.publisher != null) {
            this.publisher.publishEvent(event);
        }

    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

其他的比如删除事件他没有实现,那我就考虑模仿spring也写个这样的Listener。

简单了解redis键空间通知是怎么回事:
参考文档http://redisdoc.com/topic/notification.html

键空间通知,所有通知以 keyspace@<db> 为前缀
键事件通知,所有通知以 keyevent@<db> 为前缀
所有命令都只在键真的被改动了之后,才会产生通知,比如删除foo会产生
键空间通知
"pmessage","__ key__:","__ keyspace@0__:foo","set"
和键事件通知
"pmessage","__ key__:","__ keyevent@0__:set","foo"

如果要监听某个key的执行了什么操作,就订阅 keyspace@<db>,监听某种操作动了哪些key,就订阅keyevent@<db>。
这里我们需要监听哪些键被删除了,所以要监听删除动作"__ keyevent@0__:del"

对比上文spring写的listener有这么一句
private static final Topic KEYEVENT_EXPIRED_TOPIC = new PatternTopic("__keyevent@*__:expired");
其他都是模式化的代码,只要修改对应的topic类型就能实现监听了。


import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisKeyExpiredEvent;
import org.springframework.data.redis.listener.KeyspaceEventMessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.lang.Nullable;

public class KeyDeleteEventMessageListener extends KeyspaceEventMessageListener implements ApplicationEventPublisherAware {
    private static final Topic KEYEVENT_DELETE_TOPIC = new PatternTopic("__keyevent@*__:del");
    @Nullable
    private ApplicationEventPublisher publisher;

    public KeyDeleteEventMessageListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    protected void doRegister(RedisMessageListenerContainer listenerContainer) {
        listenerContainer.addMessageListener(this, KEYEVENT_DELETE_TOPIC);
    }

    protected void doHandleMessage(Message message) {
        this.publishEvent(new RedisKeyExpiredEvent(message.getBody()));
    }

    protected void publishEvent(RedisKeyExpiredEvent event) {
        if (this.publisher != null) {
            this.publisher.publishEvent(event);
        }

    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

类似的新增和修改也一样

package cn.fatri.jarvis.device.shadow.listener;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisKeyExpiredEvent;
import org.springframework.data.redis.listener.KeyspaceEventMessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.lang.Nullable;

public class KeyUpdateEventMessageListener extends KeyspaceEventMessageListener implements ApplicationEventPublisherAware {
    private static final Topic KEYEVENT_DELETE_TOPIC = new PatternTopic("__keyevent@*__:set");
    @Nullable
    private ApplicationEventPublisher publisher;

    public KeyUpdateEventMessageListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    protected void doRegister(RedisMessageListenerContainer listenerContainer) {
        listenerContainer.addMessageListener(this, KEYEVENT_DELETE_TOPIC);
    }

    protected void doHandleMessage(Message message) {
        this.publishEvent(new RedisKeyExpiredEvent(message.getBody()));
    }

    protected void publishEvent(RedisKeyExpiredEvent event) {
        if (this.publisher != null) {
            this.publisher.publishEvent(event);
        }

    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

我们同样继承这些类就能拿到监听的message了

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.stream.Collectors;

@Component
@Slf4j
public class RedisKeyDeleteListener extends KeyDeleteEventMessageListener {

    public RedisKeyDeleteListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    /**
     * 针对redis数据删除事件,进行数据处理
     * @param message message.toString()获取失效的key
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String deleteKey = message.toString();
        // ......
        }
    }
}

相关文章

  • Redis监听新增、修改、删除、过期事件

    前言 项目中需要监听redis的一些事件比如键删除,修改,过期等。过期事件网上有很多例子可以参考,但修改或删除事件...

  • Redis过期事件真的不能用吗?

    曾经用Redis的过期监听事件做过一些事情,比如定时通知的发送等等。但是最近看到一些文章说,Redis的过期监听事...

  • Redis 过期策略

    redis 过期策略 redis 过期策略是:定期删除+惰性删除。 所谓定期删除,指的是 redis 默认是每隔 ...

  • 9、.Net Core监听Linux下文件夹变化

    .Net Core提供了一个很强大的文件处理,并封装关于文件新增、修改、重命名、删除的事件监听。 官方示例代码:F...

  • redis数据淘汰机制

    redis的过期策略 redis有两种过期策略,定期删除和惰性删除 定期删除:redis每个100ms随机抽取一些...

  • 提前10分钟提醒信息

    1.修改redis配置文件 2.修改datebase配置文件 3.创建过期key 4.创建监听队列 PS:之所以用...

  • Redis key过期事件的监听

    redis自2.8.0之后版本提供Keyspace Notifications功能,允许客户订阅Pub / Sub...

  • redis 高级功能,过期事件监听

    一、前言: 不谈应用场景的技术都是道听途说; 二、应用场景 1.1 需求一: 一个交易系统里面有一个价格提醒的功能...

  • Redis学习笔记(一)过期策略

    redis支持两种过期删除策略:定期扫描删除和惰性删除 定期扫描策略 redis会将所有设置了过期时间的key放到...

  • redis过期数据删除策略

    过期数据删除策略  redis的过期数据删除策略使用了惰性删除和定期删除两种策略: 惰性删除发生在redis处理读...

网友评论

      本文标题:Redis监听新增、修改、删除、过期事件

      本文链接:https://www.haomeiwen.com/subject/pbmkvctx.html