1、开启Redis的 notify-keyspace-events 功能
redis.conf配置文件中,添加notify-keyspace-events Ex;
E是键空间通知, x代表过期事件。需要重启redis
用redis-cli测试
1.订阅0号数据库的过期事件
127.0.0.1:6379> psubscribe __keyevent@0__:expired
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyevent@0__:expired"
3) (integer) 1
2设置name的过期时间
127.0.0.1:6379> setex name 10 77777
3.name过期后查看第一步的控制台,会收到如下消息
1) "pmessage"
2) "__keyevent@0__:expired"
3) "__keyevent@0__:expired"
4) "name"
2、在spring-boot中使用
推荐使用spring-boot-starter-data-redis
1.在applicatio.yml,配置reidis相关属性属性,listen-pattern: keyevent@7:expired是用来订阅0号数据库,所有键过期时事件
spring:
redis:
database: 0 # Redis数据库索引(默认为0)
host: localhost # Redis服务器地址
port: 6379 # Redis服务器连接端口
password: 123456 # Redis服务器连接密码(默认为空)
listen-pattern: __keyevent@7__:expired
2.redis消息监听器容器
@Configuration
public class MessageListenerConfiguration {
public String pattern = __keyevent@7__:expired;
@Autowired
private TopicMessageListener topicMessageListener;
/**
* redis消息监听器容器
* 监听redis键空间通知配 监听key过期事件 __keyevent@7__:expired
* @param redisConnectionFactory spring-boot redis链接信息
*/
@Bean
public RedisMessageListenerContainer listenerContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
//订阅了一个叫 __keyevent@7__:expired 的通道
Topic topic = new PatternTopic(this.pattern);
container.addMessageListener(this.topicMessageListener, topic);
return container;
}
}
3.接收redis消息的类
/** 接收redis消息的类 */
@Component
public class TopicMessageListener implements MessageListener {
/** 监听redis 键空间通知, key过期会执行这个方法 */
@Override
public void onMessage(Message message, byte[] bytes) {
// redis回传的键名信息
byte[] body = message.getBody();
byte[] channel = message.getChannel();
String expiredKey = new String(body);
String topic = new String(channel);
System.out.println(expiredKey);
System.out.println(topic);
}
}
4.把用户id+订单id作为key存到redis 如: 1,12作为key
@Service
public class OrderService {
@Value("${snack.order.pay-time-limit}")
private Integer payTimeLimit = 60;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/** 写入redis */
private void sendToRedis(Long oid, Long uid) {
String key = uid.toString() + "," + oid.toString();
try {
stringRedisTemplate.opsForValue().set(key, "1", this.payTimeLimit, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
}
当支付时间过期时,会触发上面的onMessage方法,进行库存归还(业务逻辑自行编写)