前言
在开发中我们经常会遇到这样的业务需求,某一条数据需要在xxx时间后处理,比如说未支付的订单,30分钟后过期。能够实现这一功能的技术有很多,但需要你根据系统的大小、业务的量的大小以及公司给到该项目的资源而决定。
比如说这是一个大商城,开始之初就已经部署了rabbitmq,那毫无疑问可以使用延时队列实现这一功能。如果说没有提供mq,一般情况下我们就定时轮询订单表了,这是非常最简单的一种实现方式。如果说你怕数据库压力大,那不妨可以选择redis。这篇文章介绍的就是如何利用redis处理过期事件。
实现
1.开启配置
打开redis.conf,开启如下配置
notify-keyspace-events Ex
这是为了使 Redis Key 过期事件能够被监听 ,需要启用 Redis 的键空间通知功能
2.创建监听器类
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;@Slf4j
public class RedisKeyExpiredListener implements MessageListener {@Overridepublic void onMessage(Message message, byte[] pattern) {String expiredKey = message.toString();log.info("获取数据:"+expiredKey);if (expiredKey.startsWith("order:")) {// 一般来说,我们会这样设置过期订单的key:"order:255 "String orderId = expiredKey.split(":")[1];log.info("订单ID:"+orderId);// 处理实际业务}}
}
3.将监听器注册为 Bean
import com.gpt.dc.web.listener.RedisKeyExpiredListener;
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;@Configuration
public class RedisConfig {@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,RedisKeyExpiredListener listener) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);// 配置监听的 Redis Key 过期事件的频道container.addMessageListener(listener, new PatternTopic("__keyevent@*__:expired"));return container;}@Beanpublic RedisKeyExpiredListener redisKeyExpiredListener() {return new RedisKeyExpiredListener();}
}
我们在配置类 RedisConfig
中将监听器注册为 Bean,并通过 RedisMessageListenerContainer
配置监听容器。我们使用 addMessageListener()
方法来添加监听器,并指定要监听的 Redis Key 过期事件的频道(__keyevent@*__:expired
)
接下来测试一下
@GetMapping("save")
public void saveOrder(Long id){RedisUtil.set("order:"+id, id.toString(), 10L);
}
10后过期,RedisKeyExpiredListener中的onMessage方法会自动监听,并在控制台上打印如下信息
c.g.d.w.l.RedisKeyExpiredListener:17 redisMessageListenerContainer-1 获取数据:order:2
c.g.d.w.l.RedisKeyExpiredListener:20 redisMessageListenerContainer-1 订单ID:2