国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫(kù)技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫(kù) - Redis - 使用Redisson優(yōu)雅關(guān)閉訂單

使用Redisson優(yōu)雅關(guān)閉訂單

2021-04-21 01:48碼農(nóng)參上Dr Hydra Redis

針對(duì)于定時(shí)任務(wù)的這種缺陷,關(guān)閉訂單的這個(gè)需求大多依賴于延時(shí)任務(wù)來實(shí)現(xiàn),這里說明一下延時(shí)任務(wù)與定時(shí)任務(wù)的最大不同,定時(shí)任務(wù)有執(zhí)行周期的,而延時(shí)任務(wù)在某事件觸發(fā)后一段時(shí)間內(nèi)執(zhí)行,并沒有執(zhí)行周期。

使用Redisson優(yōu)雅關(guān)閉訂單

在支付系統(tǒng)中,訂單通常是具有時(shí)效性的,例如在下單30分鐘后如果還沒有完成支付,那么就要取消訂單,不能再執(zhí)行后續(xù)流程。說到這,可能大家的第一反應(yīng)是啟動(dòng)一個(gè)定時(shí)任務(wù),來輪詢訂單的狀態(tài)是否完成了支付,如果超時(shí)還沒有完成,那么就去修改訂單的關(guān)閉字段。當(dāng)然,在數(shù)據(jù)量小的時(shí)候這么干沒什么問題,但是如果訂單的數(shù)量上來了,那么就會(huì)出現(xiàn)讀取數(shù)據(jù)的瓶頸,畢竟來一次全表掃描還是挺費(fèi)時(shí)的。

針對(duì)于定時(shí)任務(wù)的這種缺陷,關(guān)閉訂單的這個(gè)需求大多依賴于延時(shí)任務(wù)來實(shí)現(xiàn),這里說明一下延時(shí)任務(wù)與定時(shí)任務(wù)的最大不同,定時(shí)任務(wù)有執(zhí)行周期的,而延時(shí)任務(wù)在某事件觸發(fā)后一段時(shí)間內(nèi)執(zhí)行,并沒有執(zhí)行周期。

對(duì)于延時(shí)任務(wù),可能大家對(duì)于RabbitMQ的延時(shí)隊(duì)列會(huì)比較熟悉,用起來也是得心應(yīng)手,但是你是否知道使用Redis也能實(shí)現(xiàn)延時(shí)任務(wù)的功能呢,今天我們就來看看具體應(yīng)該如何實(shí)現(xiàn)。

使用Redis實(shí)現(xiàn)的延時(shí)隊(duì)列,需要借助Redisson的依賴:

  1. <dependency> 
  2.     <groupId>org.redisson</groupId> 
  3.     <artifactId>redisson-spring-boot-starter</artifactId> 
  4.     <version>3.10.7</version> 
  5. </dependency> 

首先實(shí)現(xiàn)往延時(shí)隊(duì)列中添加任務(wù)的方法,為了測(cè)試時(shí)方便,我們把延遲時(shí)間設(shè)為30秒。

  1. @Component 
  2. public class UnpaidOrderQueue { 
  3.     @Autowired 
  4.     RedissonClient redissonClient; 
  5.  
  6.     public void addUnpaid(String orderId){ 
  7.         RBlockingQueue<String> blockingFairQueue = redissonClient.getBlockingQueue("orderQueue"); 
  8.         RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue); 
  9.  
  10.         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 添加任務(wù)到延時(shí)隊(duì)列"); 
  11.         delayedQueue.offer(orderId,30, TimeUnit.SECONDS); 
  12.     } 

添加一個(gè)對(duì)隊(duì)列的監(jiān)聽方法,通過實(shí)現(xiàn)CommandLineRunner接口,使它在springboot啟動(dòng)時(shí)就開始執(zhí)行:

  1. @Component 
  2. public class QueueRunner implements CommandLineRunner { 
  3.     @Autowired 
  4.     private RedissonClient redissonClient; 
  5.  
  6.     @Autowired 
  7.     private OrderService orderService; 
  8.  
  9.     @Override 
  10.     public void run(String... args) throws Exception { 
  11.         new Thread(()->{ 
  12.             RBlockingQueue<String> blockingFairQueue = redissonClient.getBlockingQueue("orderQueue"); 
  13.             RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue); 
  14.             delayedQueue.offer(null, 1, TimeUnit.SECONDS); 
  15.             while (true){ 
  16.                 String orderId = null
  17.                 try { 
  18.                     orderId = blockingFairQueue.take(); 
  19.                 } catch (Exception e) { 
  20.                     continue
  21.                 } 
  22.                 if (orderId==null) { 
  23.                     continue
  24.                 } 
  25.                 System.out.println(String.format(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 延時(shí)隊(duì)列收到:"+orderId)); 
  26.                 System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 檢測(cè)訂單是否完成支付"); 
  27.                 if (orderService.isTimeOut(orderId)) { 
  28.                     orderService.closeOrder(orderId); 
  29.                 } 
  30.             } 
  31.         }).start(); 
  32.     } 

在方法中,單獨(dú)啟動(dòng)了一個(gè)線程來進(jìn)行監(jiān)聽,如果有任務(wù)進(jìn)入延時(shí)隊(duì)列,那么取到訂單號(hào)后,調(diào)用我們OrderService提供的檢測(cè)是否訂單過期的服務(wù),如果過期,那么執(zhí)行關(guān)閉訂單的操作。

創(chuàng)建簡(jiǎn)單的OrderService用于測(cè)試,提供創(chuàng)建訂單,檢測(cè)超時(shí),關(guān)閉訂單方法:

  1. @Service 
  2. public class OrderService { 
  3.  
  4.     @Autowired 
  5.     UnpaidOrderQueue unpaidOrderQueue; 
  6.  
  7.     public void createOrder(String order){ 
  8.         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 創(chuàng)建訂單:"+order); 
  9.         unpaidOrderQueue.addUnpaid(order); 
  10.     } 
  11.  
  12.     public boolean isTimeOut(String orderId){ 
  13.         return true
  14.     } 
  15.  
  16.     public void closeOrder(String orderId){ 
  17.         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+ " 關(guān)閉訂單"); 
  18.     } 

執(zhí)行請(qǐng)求,看一下結(jié)果:

使用Redisson優(yōu)雅關(guān)閉訂單

在訂單創(chuàng)建30秒后,檢測(cè)到延時(shí)隊(duì)列中有任務(wù)任務(wù),調(diào)用檢測(cè)超時(shí)方法檢測(cè)到訂單沒有完成后,自動(dòng)關(guān)閉訂單。

除了上面這種延時(shí)隊(duì)列的方式外,Redisson還提供了另一種方式,也能優(yōu)雅的關(guān)閉訂單,方法很簡(jiǎn)單,就是通過對(duì)將要過期的key值的監(jiān)聽。

創(chuàng)建一個(gè)類繼承KeyExpirationEventMessageListener,重寫其中的onMessage方法,就能實(shí)現(xiàn)對(duì)過期key的監(jiān)聽,一旦有緩存過期,就會(huì)調(diào)用其中的onMessage方法:

  1. @Component 
  2. public class RedisExpiredListener extends KeyExpirationEventMessageListener { 
  3.     public static final String UNPAID_PREFIX="unpaidOrder:"
  4.  
  5.     @Autowired 
  6.     OrderService orderService; 
  7.  
  8.     public RedisExpiredListener(RedisMessageListenerContainer listenerContainer) { 
  9.         super(listenerContainer); 
  10.     } 
  11.  
  12.     @Override 
  13.     public void onMessage(Message message, byte[] pattern) { 
  14.         String expiredKey = message.toString(); 
  15.         if (expiredKey.startsWith(UNPAID_PREFIX)){ 
  16.             System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" " +expiredKey+"已過期"); 
  17.             orderService.closeOrder(expiredKey); 
  18.         } 
  19.     } 

因?yàn)榭赡軙?huì)有很多key的過期事件,因此需要對(duì)訂單過期的key加上一個(gè)前綴,用來判斷過期的key是不是屬于訂單事件,如果是的話那么進(jìn)行關(guān)閉訂單操作。

再在寫一個(gè)測(cè)試接口,用于創(chuàng)建訂單和接收支付成功的回調(diào)結(jié)果:

  1. @RestController 
  2. @RequestMapping("order"
  3. public class TestController { 
  4.     @Autowired 
  5.     RedisTemplate redisTemplate; 
  6.  
  7.     @GetMapping("create"
  8.     public String setTemp(String id){ 
  9.         String orderId= RedisExpiredListener.UNPAID_PREFIX+id; 
  10.         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 創(chuàng)建訂單:"+orderId); 
  11.         redisTemplate.opsForValue().set(orderId,orderId,30, TimeUnit.SECONDS); 
  12.         return id; 
  13.     } 
  14.  
  15.     @GetMapping("fallback"
  16.     public void successFallback(String id){ 
  17.         String orderId= RedisExpiredListener.UNPAID_PREFIX+id; 
  18.         redisTemplate.delete(orderId); 
  19.     } 

在訂單支付成功后,一般我們會(huì)收到第三方的一個(gè)支付成功的異步回調(diào)通知。如果支付完成后收到了這個(gè)回調(diào),那么我們主動(dòng)刪除緩存的未支付訂單,那么也就不會(huì)監(jiān)聽到這個(gè)訂單的orderId的過期失效事件。

使用Redisson優(yōu)雅關(guān)閉訂單

但是這種方式有一個(gè)弊端,就是只能監(jiān)聽到過期緩存的key,不能獲取到對(duì)應(yīng)的value。而通過延時(shí)隊(duì)列的方式,可以通過為RBlockingQueue添加泛型的方式,保存更多訂單的信息,例如直接將對(duì)象存進(jìn)隊(duì)列中:

  1. RBlockingQueue<OrderDTO> blockingFairQueue = redissonClient.getBlockingQueue("orderQueue"); 
  2. RDelayedQueue<OrderDTO> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue); 

這樣的話我們?cè)購(gòu)难訒r(shí)隊(duì)列中獲取的時(shí)候,能夠拿到更多我們需要的屬性。綜合以上兩種方式,監(jiān)聽過期更為簡(jiǎn)單,但存在的一定的局限性,如果我們只需要對(duì)訂單進(jìn)行判斷的話那么功能也能夠滿足我們的需求,如果需要在過期時(shí)獲取更多的訂單屬性,那么使用延時(shí)隊(duì)列的方式則更為合適。究竟選擇哪種,就要看大家的業(yè)務(wù)場(chǎng)景了。

原文地址:https://mp.weixin.qq.com/s/AMTEuBId3L1LOnpwkQZ5HA

延伸 · 閱讀

精彩推薦
  • Redisredis實(shí)現(xiàn)排行榜功能

    redis實(shí)現(xiàn)排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用來實(shí)現(xiàn)排行榜功能,本文就來簡(jiǎn)單的介紹一下如何使用,具有一定的參考價(jià)值,感興趣的小伙伴們...

    乘月歸5022021-08-05
  • RedisRedis的配置、啟動(dòng)、操作和關(guān)閉方法

    Redis的配置、啟動(dòng)、操作和關(guān)閉方法

    今天小編就為大家分享一篇Redis的配置、啟動(dòng)、操作和關(guān)閉方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧 ...

    大道化簡(jiǎn)5312019-11-14
  • RedisRedis如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)讀寫分離詳解

    Redis如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)讀寫分離詳解

    Redis的主從架構(gòu),能幫助我們實(shí)現(xiàn)讀多,寫少的情況,下面這篇文章主要給大家介紹了關(guān)于Redis如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)讀寫分離的相關(guān)資料,文中通過示例代碼介紹...

    羅兵漂流記6092019-11-11
  • Redis詳解Redis復(fù)制原理

    詳解Redis復(fù)制原理

    與大多數(shù)db一樣,Redis也提供了復(fù)制機(jī)制,以滿足故障恢復(fù)和負(fù)載均衡等需求。復(fù)制也是Redis高可用的基礎(chǔ),哨兵和集群都是建立在復(fù)制基礎(chǔ)上實(shí)現(xiàn)高可用的...

    李留廣10222021-08-09
  • Redisredis中如何使用lua腳本讓你的靈活性提高5個(gè)逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個(gè)逼格詳解

    這篇文章主要給大家介紹了關(guān)于redis中如何使用lua腳本讓你的靈活性提高5個(gè)逼格的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具...

    一線碼農(nóng)5812019-11-18
  • RedisRedis 事務(wù)知識(shí)點(diǎn)相關(guān)總結(jié)

    Redis 事務(wù)知識(shí)點(diǎn)相關(guān)總結(jié)

    這篇文章主要介紹了Redis 事務(wù)相關(guān)總結(jié),幫助大家更好的理解和學(xué)習(xí)使用Redis,感興趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • Redisredis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友...

    xiaojin21cen10152021-07-27
  • RedisRedis全量復(fù)制與部分復(fù)制示例詳解

    Redis全量復(fù)制與部分復(fù)制示例詳解

    這篇文章主要給大家介紹了關(guān)于Redis全量復(fù)制與部分復(fù)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis爬蟲具有一定的參考學(xué)習(xí)...

    豆子先生5052019-11-27
主站蜘蛛池模板: 亚洲成av人片一区二区梦乃 | 在线91av | 一本大道久久a久久精二百 国产欧美视频一区二区 | 日韩成人免费中文字幕 | 成年人在线观看免费视频 | 精品国产一区二区三区日日嗨 | 久久久久久国产精品 | 高清国产一区二区三区四区五区 | 亚洲第一区在线 | a资源在线观看 | 久久成人综合 | 免费视频一区 | 亚洲第一成年人网站 | 日韩一片 | 久久蜜桃精品一区二区三区综合网 | 成人精品视频在线 | 国产大片在线观看 | 久久青青 | 成人福利视频 | 亚洲情视频 | 日韩精品视频在线播放 | 亚洲成av人片在线观看 | 色花av| 亚洲性网 | 久久人人爽人人爽人人片亚洲 | 自拍偷拍av | 97久久精品午夜一区二区 | 亚洲福利在线播放 | 日韩欧美视频 | 国产片在线免费观看 | 国产中文字幕一区 | 日韩精品一区在线视频 | 日本不卡一区二区三区在线观看 | 精品无码久久久久久国产 | 色综合天天综合网国产成人网 | 在线中文字幕av | 特级淫片日本高清视频免费 | 中文字幕在线观看一区二区三区 | 日韩欧美视频免费在线观看 | 精品久久久久一区二区国产 | 免费视频爱爱太爽了 |