redis key 事件通知

参考 : http://www.redis.cn/topics/notifications.html

redis key space 通知允许客户端订阅发布/订阅频道,以某种方式接收影响 Redis 数据集的事件。但是只能接收客户端连接期间发生的事件,如果客户端断开连接,并在稍后重连,那么所有在客户端断开期间发送的事件将会丢失。比较常用的是 key 过期通知。

介绍

默认情况下,键空间事件通知是不启用的,可以使用 redis.conf 中的 notify-keyspace-events 或者使用 CONFIG SET 命令来开启通知。

将参数设置为空字符串会禁用通知。 为了开启通知功能,使用了一个非空字符串,由多个字符组成,每一个字符都有其特殊的含义,具体参见下表:

K     键空间事件,以__keyspace@<db>__前缀发布。
E     键事件事件,以__keyevent@<db>__前缀发布。
g     通用命令(非类型特定),如DEL,EXPIRE,RENAME等等
$     字符串命令
l     列表命令
s     集合命令
h     哈希命令
z     有序集合命令
x     过期事件(每次键到期时生成的事件)
e     被驱逐的事件(当一个键由于达到最大内存而被驱逐时产生的事件)
A     g$lshzxe的别名,因此字符串AKE表示所有的事件。

字符串中应当至少存在K或者E,否则将不会传递事件,不管字符串中其余部分是什么。

例如,要为列表开启键空间事件,则配置参数必须设置为Kl,以此类推。字符串KEA可以用于开启所有可能的事件。

# 监听过期 key 
redis-cli CONFIG SET notify-keyspace-events Ex
redis-cli --csv psubscribe '__key*__:*'

另一个终端 : 
# SET key value EX second
SET key1 value1 EX 10

# 等 10 秒后,可以在前一个终端发现
root@dreamboy:~# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> CONFIG SET notify-keyspace-events Ex
OK
127.0.0.1:6379> psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__key*__:*"
3) (integer) 1
1) "pmessage"
2) "__key*__:*"
3) "__keyevent@0__:expired"
4) "key1"

springboot 实现监听过期 key

测试之前需要保证 redis server 中的属性 notify-keyspace-events 中包含有 Ex

springboot 有实现 redis key 过期时间监听 : org.springframework.data.redis.listener.KeyExpirationEventMessageListener, 那么只需要重写它的 onMessage 方法即可以自己监听过期 key。

pom.xml :


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

config 配置 :

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.RedisMessageListenerContainer;

/**
 * RedisListenerConfig
 *
 * @author xh
 * @date 2020/5/9
 */
@Configuration
public class RedisListenerConfig {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }

}

监听 key 过期 :

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;

/**
 * RedisKeyExpirationListener
 *
 * <p>
 *     redis 中需设置 : CONFIG SET notify-keyspace-events Ex
 * </p>
 * 
 * <p>
 * 监听所有db的过期事件__keyevent@*__:expired"
 * </p>
 *
 * @author xh
 * @date 2020/5/9
 */
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

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

    /**
     * Callback for processing received objects through Redis.
     *
     * <p>
     * 这里是针对 redis 数据失效事件
     * </p>
     *
     * @param message message must not be {@literal null}.
     * @param pattern pattern matching the channel (if specified) - can be {@literal null}.
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 获取到失效的 key,进行取消订单业务处理
        String expiredKey = message.toString();
        // new String(pattern) ==> __keyevent@*__:expired
        System.out.println("expired key --> " + expiredKey);
    }
}

使用 redis 发布订阅模式订阅 key 过期

测试之前需要保证 redis server 中的属性 notify-keyspace-events 中包含有 Ex

redis 事件通知是使用 Redis 普通发布订阅层传递,因此可以直接订阅 key 失效时间。

使用普通的 java 类接收消息 :

/**
 * RedisReceiver
 *
 * @author xh
 * @date 2020/5/9
 */
public class RedisKeyExpireReceiver {

    public void receiveMessage(String message) {
        System.out.println("receive message -> " + message);
    }

}

把前面的 java 类注入 redis 配置 :

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;

/**
 * RedisListenerConfig2
 *
 * @author xh
 * @date 2020/5/9
 */
@Configuration
public class RedisListenerConfig2 {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        // 如果只匹配 可以过期事件,那么正则表达式是 : __keyevent@*__:expired
        // 如果匹配其他的,用对应的表达式就好
        container.addMessageListener(listenerAdapter, new PatternTopic("__keyevent@*__:expired2"));
        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter(RedisKeyExpireReceiver receiver) {
        // 这里注入 bean 和 方法名
        // redis 的默认方法名是 handleMessage
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    @Bean
    RedisKeyExpireReceiver redisKeyExpireReceiver() {
        return new RedisKeyExpireReceiver();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值