0
点赞
收藏
分享

微信扫一扫

【Redis系列】Spring boot实现监听Redis key失效事件

雷亚荣 2023-06-05 阅读 116



文章目录

  • 一、开启Redis key过期提醒
  • 二、notify-keyspace-events
  • 三、Coding
  • 四、测试输出
  • 五、一直增加的线程数
  • 六、参考


talk is cheap, show me the code.

一、开启Redis key过期提醒

  • 方式二:修改配置文件
    redis.conf

# 默认 notify-keyspace-events ""
notify-keyspace-events Ex

  • 方式二:命令行开启

CONFIG SET notify-keyspace-events Ex
CONFIG GET notify-keyspace-events

二、notify-keyspace-events

notify-keyspace-events 选项的默认值为空

notify-keyspace-events 的参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知。

字符

发送的通知

K

键空间通知,所有通知以 keyspace@ 为前缀

E

键事件通知,所有通知以 keyevent@ 为前缀

g

DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知

$

字符串命令的通知

l

列表命令的通知

s

集合命令的通知

h

哈希命令的通知

z

有序集合命令的通知

x

过期事件:每当有过期键被删除时发送

e

驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送

A

参数 g$lshzxe 的别名

三、Coding

  1. 初始化一个Spring Boot项目
  2. pom.xml

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

  1. 定义配置类RedisListenerConfig

@Configuration
public class RedisListenerConfig {

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

}

  1. 定义数据生产类ProviderDataToRedis

@Slf4j
@Component
public class ProviderDataToRedis implements CommandLineRunner {

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Override
	public void run(String... args) throws Exception {
		int[] num = new int[]{1};
		Random random = new Random();
		while (true) {
			int max = random.nextInt(5);
			IntStream.range(0, max).forEach(n -> stringRedisTemplate.opsForValue().set(String.format("mq:s1:%s", ++num[0]), "已预订", 5, TimeUnit.SECONDS));
			log.info("放了 {} 条数据到redis...", max);
			TimeUnit.SECONDS.sleep(3);
		}
	}
}

  1. 定义监听器 实现KeyExpirationEventMessageListener接口
    查看源码发现,该接口监听所有db的过期事件keyevent@*:expired"定义Status1ExpirationListener监听状态1到期

@Slf4j
@Component
public class Status1ExpirationListener extends KeyExpirationEventMessageListener {

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

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Override
	public void onMessage(Message message, byte[] pattern) {
		// 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
		String expiredKey = message.toString();
		if (expiredKey.startsWith("mq:s1:")) {
			log.info("-----------------------------------");
			log.info(String.format("过期key[%s]", expiredKey));
			String newKey = String.format("mq:s2:%s", expiredKey.substring(6));
			String newValue = "行程中";
			stringRedisTemplate.opsForValue().set(newKey, newValue, 3, TimeUnit.SECONDS);
			log.info(String.format("%s: %s", newKey, newValue));
			log.info("-----------------------------------");
		}
	}

}

定义Status2ExpirationListener监听状态2到期

@Slf4j
@Component
public class Status2ExpirationListener extends KeyExpirationEventMessageListener {

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

	@Override
	public void onMessage(Message message, byte[] pattern) {
		// 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
		String expiredKey = message.toString();
		if (expiredKey.startsWith("mq:s2:")) {
			log.info("***********************************");
			log.info(String.format("过期key[%s]", expiredKey));
			log.info("[{}]行程已完成,修改数据库状态。", newKey);
			log.info("***********************************");
		}
	}

}

四、测试输出

...
2021-01-25 23:16:58.012  INFO 55511 --- [           main] n.y.tools.listener.ProviderDataToRedis      : 放了 4 条数据到redis...
2021-01-25 23:17:00.037  INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener        : -----------------------------------
2021-01-25 23:17:00.037  INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener        : 过期key[mq:s1:272]
2021-01-25 23:17:00.037  INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener        : -----------------------------------
2021-01-25 23:17:00.037  INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener        : 过期key[mq:s1:271]
2021-01-25 23:17:00.039  INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener        : mq:s2:272: 行程中
2021-01-25 23:17:00.039  INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener        : mq:s2:271: 行程中
2021-01-25 23:17:00.039  INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener        : -----------------------------------
2021-01-25 23:17:00.039  INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener        : -----------------------------------
2021-01-25 23:17:00.140  INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.140  INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener        : 过期key[mq:s2:270]
2021-01-25 23:17:00.140  INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener        : [270]行程已完成,修改数据库状态。
2021-01-25 23:17:00.140  INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener        : 过期key[mq:s2:269]
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener        : 过期key[mq:s2:268]
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener        : [269]行程已完成,修改数据库状态。
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener        : [268]行程已完成,修改数据库状态。
2021-01-25 23:17:00.242  INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.546  INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener        : ***********************************
2021-01-25 23:17:00.546  INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener        : 过期key[mq:s2:267]
2021-01-25 23:17:00.546  INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener        : [267]行程已完成,修改数据库状态。
2021-01-25 23:17:00.546  INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener        : ***********************************
...

五、一直增加的线程数

从测试输出的日志中可以看出,线程一直在增加,这个问题还有待解决!

六、参考

http://redisdoc.com/topic/notification.html


举报

相关推荐

0 条评论