需求:
處理訂單過期自動取消,比如下單30分鍾未支付自動更改訂單狀態
解決方案1:
可以利用redis天然的key自動過期機制,下單時將訂單id寫入redis,過期時間30分鍾,30分鍾后檢查訂單狀態,如果未支付,則進行處理但是key過期了redis有通知嗎?答案是肯定的。
開啟redis key過期提醒
修改redis相關事件配置。找到redis配置文件redis.conf,查看“notify-keyspace-events”的配置項,如果沒有,添加“notify-keyspace-events Ex”,如果有值,添加Ex,相關參數說明如下:
K:keyspace事件,事件以__keyspace@<db>__為前綴進行發布;
E:keyevent事件,事件以__keyevent@<db>__為前綴進行發布;
g:一般性的,非特定類型的命令,比如del,expire,rename等;
$:字符串特定命令;
l:列表特定命令;
s:集合特定命令;
h:哈希特定命令;
z:有序集合特定命令;
x:過期事件,當某個鍵過期並刪除時會產生該事件;
e:驅逐事件,當某個鍵因maxmemore策略而被刪除時,產生該事件;
A:g$lshzxe的別名,因此”AKE”意味着所有事件。
pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>compile</scope>
<version>2.9.7</version>
</dependency>
在springboot中使用
1.定義配置RedisListenerConfig
@Configuration
public class RedisListenerConfig {
@Autowired
private RedisTemplate redisTemplate;
/**
* 處理亂碼
* @return
*/
@Bean
public RedisTemplate redisTemplateInit() {
// key序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
//val實例化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
2.定義監聽器,實現KeyExpirationEventMessageListener
接口
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/**
* 針對redis數據失效事件,進行數據處理
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 用戶做自己的業務處理即可,注意message.toString()可以獲取失效的key
String expiredKey = message.toString();
if(expiredKey.startsWith("orderNo:")){
//如果是order:開頭的key,進行處理
System.out.println(expiredKey);
String substring = expiredKey.substring(8); //去掉orderNo
System.out.println(substring);
}
}
}
public class Test(){
@Resource
private RedisTemplate redisTemplate;
redisTemplate.opsForValue().set("orderNo:156556263124101022","dadada" ,5, TimeUnit.SECONDS );
}