业务场景
咱们以订单性能为例阐明下:生成订单后一段时间不领取订单会主动敞开。最简略的想法是设置定时工作轮询,然而每个订单的创立工夫不一样,定时工作的规定无奈设定,如果将定时工作执行的距离设置的过短,太影响效率。还有一种想法,在用户进入订单界面的时候,判断工夫执行相干操作。形式可能有很多,在这里介绍一种监听 Redis 键值对过期工夫来实现订单主动敞开
实现思路
在生成订单时,向 Redis 中减少一个 KV 键值对,K 为订单号,保障通过 K 能定位到数据库中的某个订单即可,V 可为任意值。假如,生成订单时向 Redis 中寄存 K 为订单号,V 也为订单号的键值对,并设置过期工夫为 30 分钟,如果该键值对在 30 分钟过期后可能发送给程序一个告诉,或者执行一个办法,那么即可解决订单敞开问题。实现:通过监听 Redis 提供的过期队列来实现,监听过期队列后,如果 Redis 中某一个 KV 键值对过期了,那么将向监听者发送音讯,监听者能够获取到该键值对的 K,留神,是获取不到 V 的,因为曾经过期了,这就是下面所提到的,为什么要保障能通过 K 来定位到订单,而 V 为任意值即可。拿到 K 后,通过 K 定位订单,并判断其状态,如果是未领取,更新为敞开,或者勾销状态即可。
开启 Redis key 过期揭示
批改 redis 相干事件配置。找到 redis 配置文件 redis.conf,查看 notify-keyspace-events 配置项,如果没有,增加 notify-keyspace-events Ex,如果有值,则追加 Ex,相干参数阐明如下:
- K:keyspace 事件,事件以 keyspace@ 为前缀进行公布
- E:keyevent 事件,事件以 keyevent@ 为前缀进行公布
- g:一般性的,非特定类型的命令,比方 del,expire,rename 等
- $:字符串特定命令
- l:列表特定命令
- s:汇合特定命令
- h:哈希特定命令
- z:有序汇合特定命令
- x:过期事件,当某个键过期并删除时会产生该事件
- e:驱赶事件,当某个键因 maxmemore 策略而被删除时,产生该事件
- A:g$lshzxe 的别名,因而”AKE”意味着所有事件
引入依赖
在 pom.xml 中增加 org.springframework.boot:spring-boot-starter-data-redis 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
复制代码
相干配置
定义配置 RedisListenerConfig 实现监听 Redis key 过期工夫
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;
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
复制代码
定义监听器 RedisKeyExpirationListener,实现 KeyExpirationEventMessageListener 接口,查看源码发现,该接口监听所有 db 的过期事件 keyevent@*:expired”
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;
/**
* 监听所有 db 的过期事件__keyevent@*__:expired"
*/
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {super(listenerContainer);
}
/**
* 针对 redis 数据生效事件,进行数据处理
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 获取到生效的 key,进行勾销订单业务解决
String expiredKey = message.toString();
System.out.println(expiredKey);
}
}
参考:《2020 最新 Java 根底精讲视频教程和学习路线!》
链接:https://juejin.cn/post/691909…