Java处理延时任务的常用几种解决方案
前言
项目中经常会遇到如下的需求:
- 创建订单30分钟未支付,订单自动取消。
- 订单支付成功后,1分钟后给用户发送短信,提醒用户评价。
- …
针对延时任务需求,我们可以采用如下的解决方案:
数据库轮询
原理
通过一个线程定时的扫描数据库当天创建的订单,根据订单的创建时间来判断订单是否超时,针对超时订单进行相关的更新操作。
实现技术
采用Spring Boot结合quartz来实现,具体的实现可以参考之前的文章。
优缺点
优点:
此方案比较简单,且quartz也支持集群操作。
缺点:
- 系统订单数据量比较大,每个几分钟轮询数据库,对服务器和数据库的内存消耗比较大。
- 存在延迟,即使1分钟扫描一次数据库,也会存在1分钟的延迟。
Java延迟队列
原理
采用JDK自带的DelayQueue来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入DelayQueue中的对象。
实现技术
使用JDK的DelayQueue队列进行相关操作即可。
优缺点
优点:
此方案是基于内存操作所以效率高,任务触发时间延迟低.
缺点:
- 消息队列的信息都存放在内存中,一旦服务器重启,则数据全部消失
- 无法进行集群用扩展
- 由于本机内存有限,一旦订单数据量过大,很容易出现OOM异常。
Reids监听失效key
原理
该方案使用Redis的Keyspace Notifications,利用key失效的提供的回调机制,处理相关的业务实现
实现技术
基于reids的方案,实现MessageListener接口。
实现步骤
修改Redis配置文件
打开redis.conf 文件,搜索 “notify-keyspace-events”找到原本的notify-keyspace-events " ",修改为 “notify-keyspace-events Ex”,至此Redis 就支持Key过期事件的监听。
创建监听类,实现MessageListener接口
@Component public class RedisKeyExpirationListener implements MessageListener { private static final Logger logger = LoggerFactory.getLogger(RedisKeyExpirationListener.class); public static final String KEY_PREX = "test::order:queue"; @Override public void onMessage(Message message, byte[] pattern) { try { String expiredKey = message.toString(); // 通过key来判断 if(!expiredKey.contains(KEY_PREX)) { return; } //满足条件处理具体的业务逻辑 } catch (Exception e) { logger.error("失效事件失败",e); } } }
优缺点
优点:
基于Redis实现简单
缺点:
- 客户端断开后重连会导致所有事件丢失。
- 高并发场景下,存在大量的失效key场景会导出失效时间存在延迟。
- 此方案针对业务量较少且可靠性要求不高的场景使用。
RocketMq延迟消息
实现原理
基于RocketMQ设置消息的等级,发送延迟消息,RocketMQ延时消息会暂存在名为SCHEDULE_TOPIC_XXXX的Topic中,并根据delayTimeLevel存入特定的queue,queueId = delayTimeLevel – 1,即一个queue只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。broker会调度地消费SCHEDULE_TOPIC_XXXX,将消息写入真实的topic。
其具体步骤如下:
- 修改消息Topic名称和队列信息
- 转发消息到延迟主题SCHEDULE_TOPIC_XXXX的CosumeQueue中
- 延迟服务消费SCHEDULE_TOPIC_XXXX消息
- 将信息重新存储到CommitLog中
- 将消息投递到目标Topic中
- 消费者消费目标topic中的数据。
/** * 发送延迟消息 * @param topic * @param msg */ public void sendDelayMessage(String topic,Object msg) { Message msgMessage =new Message(); //设置消息等级 msgMessage.setDelayTimeLevel(2); rocketMQTemplate.convertAndSend(topic, msg); }
注意:RocketMQ延时消息的延迟时长不支持随意时长的延迟,是通过特定的延迟等级来指定的。默认支持18个等级的延迟消息,延时等级定义在RocketMQ服务端的MessageStoreConfig类中的如下变量中:
例如指定的延时等级为2,则表示延迟时长为5s,即延迟等级是从1开始计数的。
优缺点
优点:
支持高并发场景消息处理.
缺点:
- 引入额外的消息队列,增加项目的维护和复杂度。
- 支持固定时长的消息延迟,针对任意时长的消息延迟需要进行扩展。
总结
本文讲解了针对延时任务的处理的几种方案和相关的优缺点,针对不同的业务场景,选择合适的解决方案。更多相关Java 延时任务内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://blog.csdn.net/Monsterof/article/details/125065486
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
- 这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解
这篇文章主要介绍了Java 8 Stream Collectors 功能与操作方法,结合实例形式详细分析了Java 8 Stream Collectors 功能、操作方法及相关注意事项,需要的朋友可以参考下...2020-05-20Java中lombok的@Builder注解的解析与简单使用详解
这篇文章主要介绍了Java中lombok的@Builder注解的解析与简单使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-06- 下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28
- 这篇文章主要介绍了Java连接数据库oracle中文乱码解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-05-16
- 这篇文章主要介绍了Java线程池中的各个参数如何合理设置操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-19