Spring+Redis(keyspace notification)實現定時任務(訂單過期自動關閉)


1.起因

最近公司項目要做訂單超期未支付需自動關閉,首先想到的是用spring的定時器(@Schedule),結果領導舉各種例子說會影響性能,只能作罷。后來想能不能基於redis實現,學習(baidu)之后,大概就是使用redis的Keyspace Notifications,大概就是利用該機制可以在key失效之后,提供一個回調,實際上是redis會給客戶端發送一個消息。是需要redis版本2.8以上,conf配置需設置notify-keyspace-events Ex,請示領導之后也得到了同意。

2.整合實現

大致思路就是讓spring做客戶端訂閱'__keyevent@0__:expired'頻道就可以了。在這里給出兩種實現方式。

1.利用MessageListenerAdapter,spring本身已經提供了的實現方式。

首先自定義一個MessageDelegate 接口並實現

 1 public interface MyMessageDelegate {
 2   void handleMessage(String message);
 3   void handleMessage(Map message); void handleMessage(byte[] message);
 4   void handleMessage(Serializable message);
 5   // pass the channel/pattern as well
 6   void handleMessage(Serializable message, String channel);
 7  }
 8 
 9 public class MyRedisKeyExpiredMessageDelegate implements MessageDelegate {
10   // implementation elided for clarity...
11 }

xml增加相關配置

     <bean id="messageListener"
          class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
        <constructor-arg>
            <bean class="com.xxx.MyRedisKeyExpiredMessageDelegate" />
        </constructor-arg>
    </bean>
    <bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="messageListeners">
            <map>
                <entry key-ref="messageListener">
                    <list>
                        <bean class="org.springframework.data.redis.listener.ChannelTopic">
                            <constructor-arg value="__keyevent@0__:expired" />
                        </bean>
                    </list>
                </entry>
            </map>
        </property>
    </bean>    

具體可參考官方文檔:http://docs.spring.io/spring-data/redis/docs/1.7.8.RELEASE/reference/html/#redis:pubsub:subscribe

2.即自定義一個OrderPubSub類繼承自JedisPubSub,然后在spring啟動的時候就訂閱這個OrderPubSub。

 1 public class OrderSubscribe extends JedisPubSub {
 2     
 3     public void onPSubscribe(String pattern, int subscribedChannels) {   
 4         
 5     }  
 6       
 7     public void onPMessage(String pattern, String channel, String message) {    
 8             if ("__keyevent@0__:expired".equals(channel)) {
 9                 //do some thing
10             }
11     }
12 }
13 
14 public class RedisInitSubscrib implements InitializingBean{  
15     
16     JedisPool pool;
17 
18     @Override
19     public void afterPropertiesSet() throws Exception {
20         pool.getResource().psubscribe(new OrderSubscribe(), "*");
21         
22     }
23     
24 } 

當key失效后,收到消息的內容(即方法中的message參數)就是key的值,這樣就可以做自定義的操作了。

3.后記

歡迎大家留言交流,關於訂單自動關閉如果有更好的方式,還望不吝賜教,O(∩_∩)O謝謝。

 

 

 

 

 

Keyspace Notifications


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM