# 業務場景
我們以訂單功能為例說明下:生成訂單后一段時間不支付訂單會自動關閉,最簡單的想法是設定定時任務輪詢,但是每個訂單的創建時間不一樣,定時任務的規則無法設定,如果將定時任務執行的間隔設定的過短,太影響效率,還有一種想法,在用戶進入訂單界面的時候,判斷時間執行相關操作,方式可能有很多,在這里介紹一種監聽 Redis 鍵值對過期時間來實作訂單自動關閉,整理了一份Java面試寶典完整版PDF
# 實作思路
在生成訂單時,向 Redis 中增加一個 KV 鍵值對,K 為訂單號,保證通過 K 能定位到資料庫中的某個訂單即可,V 可為任意值,假設,生成訂單時向 Redis 中存放 K 為訂單號,V 也為訂單號的鍵值對,并設定過期時間為 30 分鐘,如果該鍵值對在 30 分鐘過期后能夠發送給程式一個通知,或者執行一個方法,那么即可解決訂單關閉問題,實作:通過監聽 Redis 提供的過期佇列來實作,監聽過期佇列后,如果 Redis 中某一個 KV 鍵值對過期了,那么將向監聽者發送訊息,監聽者可以獲取到該鍵值對的 K,注意,是獲取不到 V 的,因為已經過期了,這就是上面所提到的,為什么要保證能通過 K 來定位到訂單,而 V 為任意值即可,拿到 K 后,通過 K 定位訂單,并判斷其狀態,如果是未支付,更新為關閉,或者取消狀態即可,
# 開啟 Redis key 過期提醒
修改 redis 相關事件配置,找到 redis 組態檔 redis.conf,查看 notify-keyspace-events 配置項,如果沒有,添加 notify-keyspace-events Ex,如果有值,則追加 Ex,相關引數說明如下:
-
K:keyspace 事件,事件以 keyspace@ 為前綴進行發布
-
E:keyevent 事件,事件以 keyevent@ 為前綴進行發布
-
g:一般性的,非特定型別的命令,比如del,expire,rename等
-
$:字串特定命令
-
l:串列特定命令
-
s:集合特定命令
-
h:哈希特定命令
-
z:有序集合特定命令
-
x:過期事件,當某個鍵過期并洗掉時會產生該事件
-
e:驅逐事件,當某個鍵因 maxmemore 策略而被洗掉時,產生該事件
-
A:g$lshzxe的別名,因此”AKE”意味著所有事件
# 引入依賴
在 pom.xml 中添加 org.springframework.boot:spring-boot-starter-data-redis 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
# 相關配置
定義配置 RedisListenerConfig 實作監聽 Redis key 過期時間
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.RedisMessageListenerContainer;
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
定義監聽器 RedisKeyExpirationListener,實作KeyExpirationEventMessageListener 介面,查看原始碼發現,該介面監聽所有 db 的過期事件 keyevent@*:expired"整理了一份Java面試寶典完整版PDF
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* 監聽所有db的過期事件__keyevent@*__:expired"
*/
@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) {
// 獲取到失效的 key,進行取消訂單業務處理
String expiredKey = message.toString();
System.out.println(expiredKey);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/250454.html
標籤:Java
上一篇:java開發學習路線~
