一、前言:
不談應用場景的技術都是道聽途說;
二、應用場景
1.1 需求一:
-
一個交易系統里面有一個價格提醒的功能,用戶可以設置一組價格並設置一個周期,后台需要在交易的時間內進行價格掃描一旦觸發用戶設置的價格的周期就需要下發消息提醒給用戶,提醒用戶交易做單;
-
具體要求如下:交易系統都需要考慮實時性,所以后台的掃描周期為2s,用戶量為公司所管理的宇宙第一行的先行客戶
-
從上述的描述中我們可以發現,用戶量還是比較大,其實實時性要求比較高,所以如果我們把數據落庫,然后每次定時的時候從數據庫里面去取然后做邏輯的判斷,這樣肯定是無法達到實時性的要求的,所以我們准備采用redis來管理這批數據。但是也有一個問題,當這批數據過期的時候,一、要提醒用戶,二、從redis刪除后,要設置數據庫的狀態。要解決這個功能就需要使用到redis的一個高級的功能:redis 的訂閱/發布功能,只不過超時的事件時有系統進行分發。
1.2 需求二:
- 訂單超時自動關閉的問題,這個就不詳細的描述了,因為大家購物相信都能體驗的到。與此相關的問題還有一個就是庫存鎖定的問題,問題都是一樣的。
- 這個問題解決的方案就有多種了,我們可以通過MQ來進行,現在大多的MQ都帶有死信隊列的機制,我們可以通過這個機制來完成,其次也可以通過quartz的輪詢方式的完成,過程不表選擇合適的應對當前的需求即可。當然本次主要是解決第一個需求,所以只談如何使用redis來解決。
三、具體實施:
3.1 修改 redis.conf配置文件:
- K Keyspace events, published with keyspace@ prefix事件
- E Keyevent events, published with keyevent@ prefix
- g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, …
- $ String commands
- l List commands
- s Set commands
- h Hash commands
- z Sorted set commands
- x Expired events (events generated every time a key expires)
- e Evicted events (events generated when a key is evicted for maxmemory)
- A Alias for g$lshzxe, so that the “AKE” string means all the events.
redis.conf 的默認的配置是:notify-keyspace-events “”
我們需要改為:notify-keyspace-events Ex
即對應上面的鍵的過期事件。修改玩這個重啟一下redis
3.2 客戶端來監聽redis的過期事件:
3.2.1 springboot + redis 的情況下的監聽:
3.2.1.1 springboot 配置 redis
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
3.2.1.2 書寫一個監聽器
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
System.out.println(expiredKey);
}
}
需要注意的是:
過期監聽消息中返回的是,過期的鍵的key值,是沒有返回value的
3.2.2 spring+ redis+ jedis 的情況下的監聽:
class KeyExpiredListener extends JedisPubSub {
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
System.out.println("onPSubscribe " + pattern + " " + subscribedChannels);
}
@Override
public void onPMessage(String pattern, String channel, String message) {
System.out.println(
"pattern = [" + pattern + "], channel = [" + channel + "], message = [" + message + "]");
}
}
然后在配置文件中配置 KeyExpiredListener 即可
四、思考:
就如同我們上述的例子,訂單和商品鎖定5分鍾的例子,我們兩個地方都是需要進行監聽的,但是有可能還有其他的地方需要使用的到,所以我們只寫一個監聽,然后采用類似觀察者的模式,將需要處理這種key過期的處理程序進行注冊,在監聽里面去調用就好了。下一篇博文在講個這。