2021-04-02

延迟队列的常用的实现方式

延迟队列的使用场景还比较多,例如:

1、超时未收到支付回调,主动查询支付状态;

2、规定时间内,订单未支付,自动取消;

。。。

总之,但凡需要在未来的某个确定的时间点执行检查的场景中都可以用延迟队列。

常见的手段主要有:定时任务扫描、RocketMQ延迟队列、Java自动的延迟队列、监听Redis Key过期等等

1.  DelayQueue

首先,定义一个延迟任务

package com.cjs.example;import lombok.Data;import java.util.concurrent.Delayed;import java.util.concurrent.TimeUnit;/** * @author ChengJianSheng * @since 2021/3/18 */@Datapublic class DelayTask implements Delayed { private Long orderId; private long expireTime; public DelayTask(Long orderId, long expireTime) {  this.orderId = orderId;  this.expireTime = expireTime; } @Override public long getDelay(TimeUnit unit) {  return expireTime - System.currentTimeMillis(); } @Override public int compareTo(Delayed o) {  return (int) (getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS)); }}

然后,定义一个管理类

package com.cjs.example;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;import java.util.concurrent.DelayQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * @author ChengJianSheng * @since 2021/3/19 */@Slf4j@Componentpublic class DelayQueueManager implements CommandLineRunner { private DelayQueue<DelayTask> queue = new DelayQueue<>(); @Autowired private ParkOrderQueryHandler handler; @Override public void run(String... strings) throws Exception {  ExecutorService executorService = Executors.newSingleThreadExecutor();  executorService.execute(new Runnable() {   @Override   public void run() {    while (true) {     try {      DelayTask task = queue.take();      handler.handle(task);     } catch (InterruptedException e) {      e.printStackTrace();     }    }   }  }); } public void put(DelayTask task) {  queue.put(task); }}

插入任务

@Slf4j@Servicepublic class PayServiceImpl implements PayService { @Autowired private DelayQueueManager delayQueueManager; @Override public void pay() {    delayQueueManager.put(new DelayTask(1, 15));  delayQueueManager.put(new DelayTask(2, 30));  delayQueueManager.put(new DelayTask(3, 60)); }}

2.  Redis Key过期回调

修改redis.conf文件

# bind 127.0.0.1 -::1protected-mode nonotify-keyspace-events Ex

[root@localhost redis-6.2.1]$ src/redis-server redis.conf 

<?<project     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-parent</artifactId>  <version>2.4.4</version>  <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo0401</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo0401</name> <description>Demo project for Spring Boot</description> <properties>  <java.version>1.8</java.version> </properties> <dependencies>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-data-redis</artifactId>  </dependency> </dependencies> <build>  <plugins>   <plugin>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-maven-plugin</artifactId>   </plugin>  </plugins> </build></project>

RedisConfig.java

package com.example.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.listener.RedisMessageListenerContainer;/** * @author ChengJianSheng * @since 2021/4/2 */@Configurationpublic class RedisConfig { @Bean public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {  RedisMessageListenerContainer container = new RedisMessageListenerContainer();  container.setConnectionFactory(connectionFactory);  return container; }}

创建一个监听类

package com.example.listener;import org.springframework.data.redis.connection.Message;import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;import org.springframework.data.redis.listener.RedisMessageListenerContainer;import org.springframework.stereotype.Component;/** * @author ChengJianSheng * @since 2021/4/2 */@Componentpublic class MyRedisKeyExpirationListener extends KeyExpirationEventMessageListener { public MyRedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {  super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) {  String expiredKey = message.toString();  System.out.println("监听到Key: " + expiredKey + " 已过期"); }}

3.  RocketMQ

 

https://help.aliyun.com/document_detail/29549.htm 

 









原文转载:http://www.shaoqun.com/a/661720.html

跨境电商:https://www.ikjzd.com/

inkfrog:https://www.ikjzd.com/w/668

海带宝:https://www.ikjzd.com/w/1548


延迟队列的使用场景还比较多,例如:1、超时未收到支付回调,主动查询支付状态;2、规定时间内,订单未支付,自动取消;。。。总之,但凡需要在未来的某个确定的时间点执行检查的场景中都可以用延迟队列。常见的手段主要有:定时任务扫描、RocketMQ延迟队列、Java自动的延迟队列、监听RedisKey过期等等1.DelayQueue首先,定义一个延迟任务packagecom.cjs.example;imp
upc:https://www.ikjzd.com/w/111
e邮宝:https://www.ikjzd.com/w/594.html?source=tagwish
好东东网:https://www.ikjzd.com/w/1238
如何通过亚马逊SEO提升曝光搜索排名?:https://www.ikjzd.com/home/143658
跨境电商亚马逊欧美商标、外观专利查询:https://www.ikjzd.com/tl/91132
亚马逊日本站选品技巧线下活动所得:https://www.ikjzd.com/tl/108358

No comments:

Post a Comment