免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

如何使用Redisson關(guān)閉訂單

本篇內(nèi)容介紹了“如何使用redisson關(guān)閉訂單”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供師宗網(wǎng)站建設(shè)、師宗做網(wǎng)站、師宗網(wǎng)站設(shè)計(jì)、師宗網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、師宗企業(yè)網(wǎng)站模板建站服務(wù),10多年師宗做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

在支付系統(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的依賴:

<dependency>     <groupId>org.redisson</groupId>     <artifactId>redisson-spring-boot-starter</artifactId>     <version>3.10.7</version> </dependency>

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

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

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

@Component public class QueueRunner implements CommandLineRunner {     @Autowired     private RedissonClient redissonClient;      @Autowired     private OrderService orderService;      @Override     public void run(String... args) throws Exception {         new Thread(()->{             RBlockingQueue<String> blockingFairQueue = redissonClient.getBlockingQueue("orderQueue");             RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);             delayedQueue.offer(null, 1, TimeUnit.SECONDS);             while (true){                 String orderId = null;                 try {                     orderId = blockingFairQueue.take();                 } catch (Exception e) {                     continue;                 }                 if (orderId==null) {                     continue;                 }                 System.out.println(String.format(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 延時(shí)隊(duì)列收到:"+orderId));                 System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 檢測(cè)訂單是否完成支付");                 if (orderService.isTimeOut(orderId)) {                     orderService.closeOrder(orderId);                 }             }         }).start();     } }

在方法中,單獨(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)閉訂單方法:

@Service public class OrderService {      @Autowired     UnpaidOrderQueue unpaidOrderQueue;      public void createOrder(String order){         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 創(chuàng)建訂單:"+order);         unpaidOrderQueue.addUnpaid(order);     }      public boolean isTimeOut(String orderId){         return true;     }      public void closeOrder(String orderId){         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+ " 關(guān)閉訂單");     } }

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

如何使用Redisson關(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方法:

@Component public class RedisExpiredListener extends KeyExpirationEventMessageListener {     public static final String UNPAID_PREFIX="unpaidOrder:";      @Autowired     OrderService orderService;      public RedisExpiredListener(RedisMessageListenerContainer listenerContainer) {         super(listenerContainer);     }      @Override     public void onMessage(Message message, byte[] pattern) {         String expiredKey = message.toString();         if (expiredKey.startsWith(UNPAID_PREFIX)){             System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" " +expiredKey+"已過期");             orderService.closeOrder(expiredKey);         }     } }

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

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

@RestController @RequestMapping("order") public class TestController {     @Autowired     RedisTemplate redisTemplate;      @GetMapping("create")     public String setTemp(String id){         String orderId= RedisExpiredListener.UNPAID_PREFIX+id;         System.out.println(DateTime.now().toString(JodaUtil.HH_MM_SS)+" 創(chuàng)建訂單:"+orderId);         redisTemplate.opsForValue().set(orderId,orderId,30, TimeUnit.SECONDS);         return id;     }      @GetMapping("fallback")     public void successFallback(String id){         String orderId= RedisExpiredListener.UNPAID_PREFIX+id;         redisTemplate.delete(orderId);     } }

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

如何使用Redisson關(guān)閉訂單

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

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

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

“如何使用Redisson關(guān)閉訂單”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

分享標(biāo)題:如何使用Redisson關(guān)閉訂單
文章URL:http://m.newbst.com/article36/ihpdpg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)電子商務(wù)域名注冊(cè)企業(yè)建站小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站