使用Redis实现订单超时自动关闭,一种常见的方式是利用Redis的键过期(key expiration)特性结合发布/订阅模式(Pub/Sub)。以下是具体步骤:
准备Redis环境
确保你的Spring Boot项目中加入了以下依赖:
- Spring Data Redis
- Lettuce客户端(或Jedis,根据个人偏好选择)
在pom.xml中添加依赖:
<dependencies>
<!-- Spring Boot Starter Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
在application.yml或application.properties中配置Redis连接信息:
spring:
redis:
host: localhost
port: 6379
配置Redis服务器
确保Redis服务器配置文件(redis.conf)中启用了键空间通知。至少需要包含Ex选项来接收键过期事件的通知。可以通过编辑配置文件并重启Redis服务来完成这一步:
notify-keyspace-events Ex
查看notify-keyspace-events Ex设置是否生效
- 打开Redis命令行客户端: 首先,你需要通过Redis命令行客户端(如redis-cli)连接到你的Redis服务器。
- 查询配置: 执行以下命令来获取notify-keyspace-events的当前配置值:
CONFIG GET notify-keyspace-events
解读结果:
命令执行后,你会看到类似如下输出:
1) "notify-keyspace-events"
2) "Ex"
重启Redis服务以应用配置变更。
注意:Windows系统上Redis,配置文件通常命名为redis.windows-service.conf或redis.windows.conf,可能会有修改后不生效的情况,需要通过在(redis-cli)进行配置:
config set notify-keyspace-events Ex
创建订单时设置键过期
当一个新的订单被创建时,除了在数据库中记录订单信息,还应该在Redis中创建一个键来表示这个订单,并设置其过期时间。这个键可以是订单ID,而值可以用来表示订单的状态或者存放一些辅助信息。使用Java Redis客户端(例如Jedis)设置键的过期时间:
// 设置订单键及其过期时间
redisTemplate.opsForValue().set(aliPay.getTraceNo(), "pending_payment", timeoutNum, TimeUnit.MINUTES);
监听键过期事件
虽然Redis本身不直接支持键过期事件的推送,但可以间接实现。你需要编写一个监听器,通过订阅特定的键空间通知频道来捕捉到键过期的事件。
1.实现MessageListener并发布自定义事件:
RedisKeyExpirationListener.java (实现MessageListener接口):
package com.smile.framework.manager;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class RedisKeyExpirationListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
// 解析
String channel = new String(message.getChannel());
// 获取订单号
String orderSn = new String(message.getBody());
String orderExpiredStr = channel.substring(channel.lastIndexOf(':') + 1);
System.out.println("订单 " + orderSn + " 超时过期.");
// 处理订单超时逻辑
}
}
2. 注册了监听器
Redis配置类 (RedisConfig.java):
通过MessageListenerAdapter和RedisMessageListenerContainer来设置监听器,这是处理Redis键过期事件
/**
* redis配置
*
* @author smile
*/
@Configuration
@EnableCaching
public class RedisConfig
{
@Autowired
private RedisConnectionFactory connectionFactory;
@Bean
MessageListenerAdapter messageListenerAdapter(RedisKeyExpirationListener listener) {
System.out.println("监听redis过期处理器");
return new MessageListenerAdapter(listener, "onMessage");
}
@Bean
RedisMessageListenerContainer redisContainer(MessageListenerAdapter listenerAdapter) {
System.out.println("监听redis过期容器");
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
// 监听所有数据库上的__keyevent@*__:expired频道
container.addMessageListener(listenerAdapter, new PatternTopic("__keyevent@*__:expired"));
return container;
}
}
注意事项:
Redis配置:确保Redis服务器已开启键空间通知功能,特别是过期事件的通知。
- 事件监听:在实际应用中,Spring Boot应用启动时会自动注册RedisKeyExpirationListener,监听Redis的键过期事件。
测试效果:
定义一个过期的key(setex k v expired):
setex a 123 10