Spring-data-redis: 分布式隊列

來源:互聯網
上載者:User
Spring-data-redis: 分布式隊列 返回指令碼百事通

Redis中list資料結構,具有“雙端隊列”的特性,同時redis具有持久資料的能力,因此redis實現分布式隊列是非常安全可靠的。它類似於JMS中的“Queue”,只不過功能和可靠性(事務性)並沒有JMS嚴格。

Redis中的隊列阻塞時,整個connection都無法繼續進行其他動作,因此在基於串連池設計是需要注意。

我們通過spring-data-redis,來實現“同步隊列”,設計風格類似與JMS。

一.設定檔:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"><bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"><property name="maxActive" value="32"></property><property name="maxIdle" value="6"></property><property name="maxWait" value="15000"></property><property name="minEvictableIdleTimeMillis" value="300000"></property><property name="numTestsPerEvictionRun" value="3"></property><property name="timeBetweenEvictionRunsMillis" value="60000"></property><property name="whenExhaustedAction" value="1"></property></bean><bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy"><property name="poolConfig" ref="jedisPoolConfig"></property><property name="hostName" value="127.0.0.1"></property><property name="port" value="6379"></property><property name="password" value="0123456"></property><property name="timeout" value="15000"></property><property name="usePool" value="true"></property></bean><bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="jedisConnectionFactory"></property><property name="defaultSerializer"><bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/></property></bean><bean id="jedisQueueListener" class="com.sample.redis.sdr.QueueListener"/><bean id="jedisQueue" class="com.sample.redis.sdr.RedisQueue" destroy-method="destroy"><property name="redisTemplate" ref="jedisTemplate"></property><property name="key" value="user:queue"></property><property name="listener" ref="jedisQueueListener"></property></bean></beans>

二.程式執行個體:

1) QueueListener:當隊列中有資料時,可以執行類似於JMS的回調操作。

public interface RedisQueueListener<T> {public void onMessage(T value);}
public class QueueListener<String> implements RedisQueueListener<String> {@Overridepublic void onMessage(String value) {System.out.println(value);}}

2) RedisQueue:隊列操作,內部封裝redisTemplate執行個體;如果配置了“listener”,那麼queue將採用“訊息回調”的方式執行,listenerThread是一個後台線程,用來自動處理“隊列資訊”。如果不配置“listener”,那麼你可以將redisQueue注入到其他spring bean中,手動去“take”資料即可。

public class RedisQueue<T> implements InitializingBean,DisposableBean{private RedisTemplate redisTemplate;private String key;private int cap = Short.MAX_VALUE;//最大阻塞的容量,超過容量將會導致清空舊資料private byte[] rawKey;private RedisConnectionFactory factory;private RedisConnection connection;//for blockingprivate BoundListOperations<String, T> listOperations;//noblockingprivate Lock lock = new ReentrantLock();//基於底層IO阻塞考慮private RedisQueueListener listener;//非同步回調private Thread listenerThread;private boolean isClosed;public void setRedisTemplate(RedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}public void setListener(RedisQueueListener listener) {this.listener = listener;}public void setKey(String key) {this.key = key;}@Overridepublic void afterPropertiesSet() throws Exception {factory = redisTemplate.getConnectionFactory();connection = RedisConnectionUtils.getConnection(factory);rawKey = redisTemplate.getKeySerializer().serialize(key);listOperations = redisTemplate.boundListOps(key);if(listener != null){listenerThread = new ListenerThread();listenerThread.setDaemon(true);listenerThread.start();}}/** * blocking * remove and get last item from queue:BRPOP * @return */public T takeFromTail(int timeout) throws InterruptedException{ lock.lockInterruptibly();try{List<byte[]> results = connection.bRPop(timeout, rawKey);if(CollectionUtils.isEmpty(results)){return null;}return (T)redisTemplate.getValueSerializer().deserialize(results.get(1));}finally{lock.unlock();}}public T takeFromTail() throws InterruptedException{return takeFromHead(0);}/** * 從隊列的頭,插入 */public void pushFromHead(T value){listOperations.leftPush(value);}public void pushFromTail(T value){listOperations.rightPush(value);}/** * noblocking * @return null if no item in queue */public T removeFromHead(){return listOperations.leftPop();}public T removeFromTail(){return listOperations.rightPop();}/** * blocking * remove and get first item from queue:BLPOP * @return */public T takeFromHead(int timeout) throws InterruptedException{lock.lockInterruptibly();try{List<byte[]> results = connection.bLPop(timeout, rawKey);if(CollectionUtils.isEmpty(results)){return null;}return (T)redisTemplate.getValueSerializer().deserialize(results.get(1));}finally{lock.unlock();}}public T takeFromHead() throws InterruptedException{return takeFromHead(0);}@Overridepublic void destroy() throws Exception {if(isClosed){return;}shutdown();RedisConnectionUtils.releaseConnection(connection, factory);}private void shutdown(){try{listenerThread.interrupt();}catch(Exception e){//}}class ListenerThread extends Thread {@Overridepublic void run(){try{while(true){T value = takeFromHead();//cast exceptionyou should check.//逐個執行if(value != null){try{listener.onMessage(value);}catch(Exception e){//}}}}catch(InterruptedException e){//}}}}

3) 使用與測試:

public static void main(String[] args) throws Exception{ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-redis-beans.xml");RedisQueue<String> redisQueue = (RedisQueue)context.getBean("jedisQueue");redisQueue.pushFromHead("test:app");Thread.sleep(15000);redisQueue.pushFromHead("test:app");Thread.sleep(15000);redisQueue.destroy();}

在程式運行期間,你可以通過redis-cli(用戶端視窗)執行“lpush”,你會發現程式的控制台仍然能夠正常列印佇列資訊。




更多文章: 武漢企業目錄 JMeter壓力測試工具——環境搭建 工作的用的小指令碼(原創) 【修鍊十二】當蘿蔔+大棒失效時,我們如何更有效激勵員工。 SWTableView(CCTableView)移動清單項目到指定索引對應的cell stl string的記憶體增長策略 線上學習編程網站收集 關於使用TexturePacker打包圖片後,運行時精靈圖片會變紅,並且有異樣文字 一步步實現自己的架構系列(三):用戶端服務端通訊的實現 注入架構RoboGuice

<iframe id="iframeu1254640_0" src="http://pos.baidu.com/acom?rdid=1254640&amp;dc=2&amp;di=u1254640&amp;dri=0&amp;dis=0&amp;dai=1&amp;ps=5913x8&amp;dcb=BAIDU_EXP_UNION_define&amp;dtm=BAIDU_DUP_SETJSONADSLOT&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=88&amp;tpr=1452072691177&amp;ti=Spring-data-redis%3A%20%E5%88%86%E5%B8%83%E5%BC%8F%E9%98%9F%E5%88%97%20-%20%E8%84%9A%E6%9C%AC%E7%99%BE%E4%BA%8B%E9%80%9A&amp;ari=1&amp;dbv=2&amp;drs=1&amp;pcs=1337x719&amp;pss=1337x5922&amp;cfv=0&amp;cpl=4&amp;chi=1&amp;cce=true&amp;cec=GBK&amp;tlm=1425257122&amp;ltu=http%3A%2F%2Fwww.csdn123.com%2Fhtml%2Fblogs%2F20130616%2F22846.htm&amp;ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DeaAHmNKcNRPDMi0Z7iVAuHgU2Tw729bGOsLF1u7KwtRFNERJg8tHxfIBAHgGxgSzECcQNsDOm4eTFqrWAEFqNa%26wd%3D%26eqid%3Db6daff4d0001185700000003568cdeef&amp;ecd=1&amp;psr=1600x900&amp;par=1538x900&amp;pis=-1x-1&amp;ccd=24&amp;cja=true&amp;cmi=6&amp;col=zh-CN&amp;cdo=-1&amp;tcn=1452072691&amp;exps=110211&amp;qn=06472862a48c85e3&amp;tt=1452072691088.92.113.115&amp;feid=110211" width="960" height="90" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; border-style: initial; vertical-align: bottom; margin: 0px;"></iframe>

百度統計 <iframe scrolling="no" frameborder="0" allowtransparency="true" align="center,center" src="http://pos.baidu.com/ecom?adn=32&amp;at=231&amp;aurl=&amp;cad=1&amp;ccd=24&amp;cec=GBK&amp;cfv=19&amp;ch=0&amp;col=zh-CN&amp;conBW=0&amp;conOP=1&amp;cpa=1&amp;dai=1&amp;dis=0&amp;hn=4&amp;ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DeaAHmNKcNRPDMi0Z7iVAuHgU2Tw729bGOsLF1u7KwtRFNERJg8tHxfIBAHgGxgSzECcQNsDOm4eTFqrWAEFqNa%26wd%3D%26eqid%3Db6daff4d0001185700000003568cdeef&amp;ltu=http%3A%2F%2Fwww.csdn123.com%2Fhtml%2Fblogs%2F20130616%2F22846.htm&amp;lunum=6&amp;n=94007089_cpr&amp;pcs=1337x719&amp;pis=10000x10000&amp;ps=6053x8&amp;psr=1600x900&amp;pss=1337x6054&amp;qn=ac064af064d6cb58&amp;rad=&amp;rsi0=960&amp;rsi1=75&amp;rsi5=4&amp;rss0=%23FFFFFF&amp;rss1=%23FFFFFF&amp;rss2=%230000ff&amp;rss3=&amp;rss4=&amp;rss5=&amp;rss6=%23e10900&amp;rss7=&amp;scale=&amp;skin=&amp;slideLU_abs_pos=bottom&amp;slideLU_in_per=1.0&amp;slideLU_out_per=0.0&amp;slideLU_rel_pos=left&amp;stid=14&amp;td_id=1656710&amp;titFF=%E5%AE%8B%E4%BD%93&amp;titFS=12&amp;titTA=left&amp;tn=baiduTlinkInlay&amp;tpr=1452072691177&amp;ts=1&amp;wn=9&amp;xuanting=0&amp;cpro_id=u1656710_0&amp;dtm=BAIDU_DUP2_SETJSONADSLOT&amp;dc=2&amp;di=u1656710&amp;ti=Spring-data-redis%3A%20%E5%88%86%E5%B8%83%E5%BC%8F%E9%98%9F%E5%88%97%20-%20%E8%84%9A%E6%9C%AC%E7%99%BE%E4%BA%8B%E9%80%9A&amp;tt=1452072691265.11.29.62" style="width: 960px; height: 75px;"></iframe> 為您推薦

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.