很多业务场景,例如订单过期自动删除,订单几天后自动好评,这些常用操作可以通过定时任务,数据库轮询做,但是订单量大的情况可能会对数据库产生大的压力。
所以今天介绍的就是 redis 缓存过期通知。
注: 楼主技术提升的同时, 这个博文失效吧, 这个只能适用于单机redis, 订单过期删除这些操作还是通过rocketMq, 或者时间轮, 或者Zset进行操作吧
1. 事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 故需要开启 redis 的事件监听与发布
2. 修改 redis.conf 文件
打开 notify-keyspace-events Ex 的注释,开启过期通知功能
# 我这边开启事件监听
notify-keyspace-events Ex
3. 重启redis , 即可测试失效事件的触发, 监听获取的值为 key
进入redis-client,进入监听
127.0.0.1:6379> PSUBSCRIBE __keyevent@*__:expired
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyevent@*__:expired"
3) (integer) 1
再打开一个 redis-client,发送过期数据
127.0.0.1:6379> setex test 2 2
OK
返回之前的 client,监听到过期事件
127.0.0.1:6379> PSUBSCRIBE __keyevent@*__:expired
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyevent@*__:expired"
3) (integer) 1
1) "pmessage"
2) "__keyevent@*__:expired"
3) "__keyevent@0__:expired"
4) "test"
至此,redis 环境配置完毕;
接下来是服务端配置监听事件:
/**
* Description: Redis超时监听器
* User: zhouzhou
* Date: 2019-04-07
* Time: 9:02 PM
*/
@Service
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
private static Logger log = LoggerFactory.getLogger(RedisKeyExpirationListener.class);
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
//获取过期的key
String expireKey = message.toString();
System.out.println("终于失效了");
log.debug("key is:"+ expireKey);
System.out.println(expireKey);
}
}
配置 redis 远程监听配置:
/**
* Description: redis 远程监听
* User: zhouzhou
* Date: 2019-04-17
* Time: 3:04 PM
*/
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer listenerContainer(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory);
return listenerContainer;
}
@Bean
KeyExpirationEventMessageListener redisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
return new RedisKeyExpirationListener(listenerContainer);
}
}
redis 连接的配置我就不发了。
启动项目,当我们再次通过 redis-client 进行测试;可以看到 console打印一下日志:
终于失效了
test