定时器超时 java_java中定时器的设置

在java后台开发中,我们常常会碰到一种需求:定时任务,比如超时取消未支付订单、定时推送通知(发送短信)、定时清理日志等等。这些需求在我们的开发中是随处可见的,但是往往对于一些特殊的需求不知道如何做,或者不知道如何设计。

在这里我将它们分为三种:第一种是从时间点开始(已知起始时间点),到一定时长后触发(到达结束时间点)的任务,如超时自动取消;第二种是提前n时长的通知任务(定时任务);第三种是固定周期的任务,如每天的凌晨4点清理日志或数据等。

下面我们针对这三种作具体分析。

一、n分钟后触发(订单超时自动取消)

需求:订单下单后,30分钟内未付款的订单将自动取消

分析:起始时间点已知,时长设置已知,推算出来触发时间点

解决方案:通过rabbitmq的延迟队列实现,其原理主要是通过TTL和Dead Letter Exchange实现的。具体可查看https://www.cnblogs.com/haoxinyue/p/6613706.html,在这里不再赘述。要注意的是,一个TTL队列,其中的时长必须是一致的,原因是因为消息队列的先进先出机制,即使队列top节点剩余时长是最长的,但也是它先出后,后面的才回被推出,别忽略了消息队列的本质。

缺点:TTL时长必须一致,这样不同的时长就需要创建不同的队列

二、提前n分钟的触发任务(定时推送)

需求:订单约定时间点为14:00,提前10分钟通知用户

分析:因为这里每个用户的约定时间点不一致,那么从任务开始后,任务的触发时长也不一致,没法采用方案一的解决方式。

解决方案:采用redis的失效key监听触发。redis可以通过订阅的方式来监听失效key,以此来达到定时推送功能。通过计算可知触发时间点,再利用当前时间点和触发时间点的时间长获得失效时长times,通过redis设置任务key的失效时间(有效剩余时长)。

缺点:不能像消息队列一样有未确认(not ack)机制,失败后可以这个任务就消失了。

三、固定周期的触发任务(定时清理日志)

这个就是我们经常用的cron表达式,这也是最简单的一种。网络上资料很多,就不赘述了。

总结:至于为什么前两种场景为什么不用cron表达式通过轮询数据库的方案来解决,一是因为我们schedule定时任务的创建相比较通过redis和rabbitmq来说,内存消耗代价更大,二是因为有效场景不适合利用轮询数据库的方式,占用数据库的连接不说,订单数据一多,查询压力更大,而且做不到精确触发任务。

第一次写文章,有不足或指教的地方请留言

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值