首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

延时任务怎么搞

前言

开发过程中,往往有一些延迟任务的需求,比如:

订单15分钟未支付,自动取消订单。

用户支付成功后,给用户发短信。

这种情况我们一般采用延迟任务来实现。

延迟任务和定时任务什么区别呢?

定时任务是在一个指定时间执行,延迟任务一般是在上一次任务执行完成后在同一个延迟间隔执行。

方案

数据库轮询

可以通过一个线程定时扫描数据库,根据时间执行update或insert操作。 可以采用quartz实现:

Demo:

这样程序会每隔3秒,输出:要去数据库扫描啦。。。

优点:

简单,支持集群操作。

缺点:

消耗内存。

如果数据量大,每扫描一次db性能存在损失。

JDK延迟队列

采用JDK自带的DelayQueue实现,是一个无界阻塞队列,只有在延迟时间满足时才在队列获取元素,流程如下:

producer->生产一个任务->放入delayedQueue->通过poll()/take()方法获取一个任务->交给消费者

poll:获取并移除队列的超时元素,没有则返回空;

take:获取并移除队列的超时元素,如果没有,线程阻塞,直到满足条件返回结果;

Demo:

输出:

优缺点:

效率高,低延迟

服务器重启,数据丢失,集群扩展受限于单机/内存,易出现OOM异常,代码复杂度高

时间片轮训

原理:

类似于时钟顺时针执行,每一次移动算一个tick。时间片主要有三个属性:

ticksPerWheel:一圈的tick数

tickDuration:一个tick持续的时间

timeUnit:时间单位

比如现实中的时钟就是:ticksPerWheel = 60,tickDurateion = 1,timeUnit = s。

如果当前时针在1上,下一个任务要4秒后执行,这这个任务的线程回调放在5上。 如果要在20秒后执行,由于一圈有8个位置,如果20秒,指针需要转两圈的5上面。

实现: 利用Netty的HashedWheelTimer:

Demo:

输出:

优缺点:

效率高,延迟低,代码复杂度比delayQueue低。

受限于单机内存,易出现OOM,机器重启数据丢失,集群难扩展。

消息队列

可以采用消息队列简单的实现延迟队列,比如:

RabbitMQ对Queue和Message设置x-message-tt来控制消息的生存时间,如果超时消息变为dead leter。

RabbitMQ的Queue设置x-dead-leter-exchange和x-dead-letter-routing-key用来控制队列内出现dead letter后进行重新路由。

优缺点:

高效的利用MQ本身的分布式特点,增加了扩展性和可靠性。

但是强依赖于MQ的运维,复杂度有一定的增高。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181226G0S6V300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券