如何监听Redis过期缓存

1. 监听某个key过期

  • 修改redis.windows.conf配置文件中notify-keyspace-events的值

默认配置notify-keyspace-events的值为" ", 表示关闭
修改为 notify-keyspace-events Ex 这样便开启了过期事件

在这里插入图片描述

  • config配置类
@Configuration
public class RedisListenerConfig {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}
  • 继承KeyExpirationEventMessageListener创建redis过期事件的监听类
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    @Resource
    private KeyExpireFactory keyExpireFactory;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        // message为任何过期key
        String expiredKey = message.toString();

        // 根据key的前缀 去匹配过期策略
        String implCode = KeyExpireStrategyEnum.getImplByPreFix(expiredKey);
        if (StringUtils.isBlank(implCode)) {
            return;
        }

        // 根据不同策略执行不同处理方式
        keyExpireFactory.getHandleService(implCode).handleExpiredKey(expiredKey);
    }

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

重写的onMessage()方法, 入参 message 是过期的key, 但是有一点需要注意, 任何过期的key, 都会被监听器捕捉到.
只要能拿到key, 就可以针对不同的key, 做不同的处理.

2.redis订阅事件类型

// 键空间
PUBLISH __keyspace@__:mykey
PUBLISH __keyspace@*__:com.*
@后指定的是redis的库 如果不填则默认是0库
@*指定的是全库
keyspace 是根据key的name去监听, key* 表示监听以com.开头的所有key 所有动作都会监听, 比如 set, delete, expired

// 键事件
PUBLISH __keyevent@2__:del
对事件进行监听 2库所有key被删除时会触发事件

keyspace监听到的message内容是key的事件
keyevent监听到的message内容是key的名称

"__keyspace@__:mykey"
"set"

"__keyevent@2__:del"
"mykey"

3. 监听set , delete事件

  • config类
@Configuration
public class RedisConfig {
 
    @Autowired
    private RedisUpdateAndAddListener redisUpdateAndAddListener;
 
    @Autowired
    private RedisDeleteListener redisDeleteListener;
 
    @Autowired
    private RedisExpiredListener redisExpiredListener;
 
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //监听所有的key的set事件
        container.addMessageListener(redisUpdateAndAddListener, redisUpdateAndAddListener.getTopic());
        //监听所有key的删除事件
        container.addMessageListener(redisDeleteListener,redisDeleteListener.getTopic());
        //监听所有key的过期事件
        container.addMessageListener(redisExpiredListener,redisExpiredListener.getTopic());
        return container;
    }
}
  • set事件
@Component
@Data
public class RedisUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:set");
 
    @Override
    public void onMessage(Message message,byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }
 
}

在这里插入图片描述

  • delete 事件
@Component
@Data
public class RedisDeleteListener implements MessageListener {
 
    //监听主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:del");
 
    /**
     *
     * @param message 消息
     * @param pattern 主题
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key的删除,消息主题是:"+ topic+",消息内容是:"+msg);
    }
}

在这里插入图片描述

  • 弊端及解决办法
    目前暂不支持订阅 keyspace + keyevent, keyevent会监听所有的key, 如果redis库中的key比较多, 则会耗redis资源, 且删除事件也会触发的不及时. 不及时原因可以参考redis的删除策略
    可以开辟一个库, 比如库16, 专门用来存放需要被监听的key, 这样可以有效降低库中key的总数

  • redis的三种删除策略
    1.定时删除: key带有ttl, redis会开启定时器, 定时删除. 准确性高但是耗费性能
    2.定期删除: 以某个频率去删除过期的key, 比如一次扫20个key, 删除其中已过期的. 如有过期的超过1/4, 则会再次扫描, 知道小于阈值.这些参数都可以在redis配置中修改
    3.惰性删除: key过期了不会主动删除, 直到被访问时才删除. 如果一直不被访问, 就一直占用空间无法删除
    redis默认采用的过期策略是 定期删除 + 惰性删除

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值