Redis 配置

方法一、更改配置文件,以配置文件启动

进入 Redis 安装目录,修改 redis.windows.conf (Linux 下配置文件是 redis.conf)

在第892行找到 notify-keyspace-events (Windows 系统,Redis 版本 5.0.10)

notify-keyspace-events ""

上面有配置项的注释

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.

配置此项为键事件过期通知

notify-keyspace-events Ex

以配置文件启动

redis-server redis.windows.conf

方法二、在 redis-cli 中配置

运行 redis-cli,运行命令

config set notify-keyspace-events Ex

或在终端直接运行命令

redis-cli config set notify-keyspace-events Ex

Spring Boot 监听

引入依赖

<!-- maven -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
// gradle
compile("org.springframework.boot:spring-boot-starter-data-redis")

RedisMessageListener.java

@Component
public class RedisMessageListener implements MessageListener {
    @Resource
    private RedisTemplate<String, Object> redis;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        System.out.println("----------- " + new String(pattern));
        // 使用了 fastjson 来打印对象
        System.out.println(JSONObject.toJSONString(message, true));
        System.out.println("-------------------------------");
        // 获取过期的键
        System.out.println(redis.getKeySerializer().deserialize(message.getBody()));
    }
}

RedisConfig.java

@Configuration
public class RedisConfig {
    @Resource
    private RedisMessageListener messageListener;

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        template.setKeySerializer(new StringRedisSerializer());
        final Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        template.setValueSerializer(serializer);

        return template;
    }

    @Bean
    public ChannelTopic channelTopic() {
        // 监听 Redis 键过期事件通知
        return new ChannelTopic("__keyevent@0__:expired");
    }

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
        redisMessageListenerContainer.addMessageListener(messageListener, channelTopic());
        return redisMessageListenerContainer;
    }
}

运行测试

方法1、在 redis-cli 中操作

set 123 456 PX 100

键 123,值 456,100ms 后过期,若 PX 设为 EX 则时间单位为秒。

方法2、使用 Spring Boot 操作


@RestController
public class TestController {
    @Resource
    private RedisTemplate<String, Object> redis;

    @GetMapping("/redis")
    public void re() {
        ValueOperations<String, Object> ops = redis.opsForValue();
        ops.set("123", "456");
        // 设置需要过期的键,过期时间,时间单位
        redis.expire("123", 100L, TimeUnit.MILLISECONDS);
    }
}

运行结果

控制台打印

----------- __keyevent@0__:expired
{
	"body":"MTIz",
	"channel":"X19rZXlldmVudEAwX186ZXhwaXJlZA=="
}
-------------------------------
123

成功拿到过期的键 123。

注意事项

Spring Boot 2.6 默认禁止了循环引用,需要配置开启循环引用。

spring:
  main:
    allow-circular-references: true