使用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>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

在application.yml或application.properties中配置Redis连接信息:

spring:
  redis:
    host: localhost
    port: 6379
  • 1.
  • 2.
  • 3.
  • 4.

配置Redis服务器

确保Redis服务器配置文件(redis.conf)中启用了键空间通知。至少需要包含Ex选项来接收键过期事件的通知。可以通过编辑配置文件并重启Redis服务来完成这一步:

notify-keyspace-events Ex
  • 1.

查看notify-keyspace-events Ex设置是否生效

  1. 打开Redis命令行客户端: 首先,你需要通过Redis命令行客户端(如redis-cli)连接到你的Redis服务器。
  2. 查询配置: 执行以下命令来获取notify-keyspace-events的当前配置值:
CONFIG GET notify-keyspace-events
  • 1.

解读结果:

命令执行后,你会看到类似如下输出:

1) "notify-keyspace-events"
   2) "Ex"
  • 1.
  • 2.

重启Redis服务以应用配置变更。

 注意:Windows系统上Redis,配置文件通常命名为redis.windows-service.conf或redis.windows.conf,可能会有修改后不生效的情况,需要通过在(redis-cli)进行配置:

config set notify-keyspace-events Ex
  • 1.

创建订单时设置键过期

当一个新的订单被创建时,除了在数据库中记录订单信息,还应该在Redis中创建一个键来表示这个订单,并设置其过期时间。这个键可以是订单ID,而值可以用来表示订单的状态或者存放一些辅助信息。使用Java Redis客户端(例如Jedis)设置键的过期时间:

// 设置订单键及其过期时间
redisTemplate.opsForValue().set(aliPay.getTraceNo(), "pending_payment", timeoutNum, TimeUnit.MINUTES);
  • 1.
  • 2.

监听键过期事件

虽然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 + " 超时过期.");
        // 处理订单超时逻辑
        
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
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;
    }
 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

注意事项:
Redis配置:确保Redis服务器已开启键空间通知功能,特别是过期事件的通知。

  • 事件监听:在实际应用中,Spring Boot应用启动时会自动注册RedisKeyExpirationListener,监听Redis的键过期事件。

测试效果:

定义一个过期的key(setex k  v expired):

setex a123 10
  • 1.