延时任务的解决方案

这篇具有很好参考价值的文章主要介绍了延时任务的解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.数据库轮询

该方案通常是在小型项目中使用,即通过一个线程定时的去扫描数据库,通过订单时间来判断是否有超时的订单,然后进行update或delete等操作

代码示例:

select * from '表名' where '时间字段' < '数据库存储的时间戳' and status = '未执行'
while(true){
	sql;
	Thread.sleep(1000);
}

1.优点:简单易行,支持集群操作

2.缺点:

  • 对服务器内存消耗大
  • 存在延迟,比如你每隔3分钟扫描一次,那最坏的延迟时间就是3分钟
  • 假设你的订单有几千万条,每隔几分钟这样扫描一次,数据库损耗极大

2. JDK的延迟队列

该方案是利用JDK自带的DelayQueue来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入DelayQueue中的对象,是必须实现Delayed接口的

延时任务完成不释放,解决方案,java,开发语言
代码示例:

public class JdkDelayQueue {

    public static void main(String[] args) throws Exception{
        DelayQueue<MyDelayed> delayQueue = new DelayQueue();
        delayQueue.add(new MyDelayed("Andy",5, TimeUnit.SECONDS));
        delayQueue.add(new MyDelayed("Andy_1",10, TimeUnit.SECONDS));

        for (;;){
            // 没有队列就就会阻塞
            MyDelayed take = delayQueue.take();
            take.excutue();
        }

    }

    static class MyDelayed implements Delayed {

        private String name;

        private long startTime;
        public MyDelayed(String name, long delayTime, TimeUnit unit) {
            this.name = name;
            // 当前时间毫秒值
            long currentTime = System.currentTimeMillis();
            // 时间转换为毫秒值
            long convert = TimeUnit.MILLISECONDS.convert(delayTime, unit);
            // 任务真正的执行时间
            this.startTime = currentTime + convert;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            long currentTime = System.currentTimeMillis();
            if(startTime <= currentTime){
                return 0;
            }
            long nextTime = startTime - currentTime;
            return unit.convert(nextTime, TimeUnit.MICROSECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
            MyDelayed prx = (MyDelayed) o;
            MyDelayed next = this;
            if (prx.startTime < next.startTime) {
                return 1;
            } else if (prx.startTime > next.startTime){
                return -1;
            }
            return 0;
        }
        public void excutue(){
            System.out.println(name + "任务执行");
        }

    }
}

1.优点:效率高,任务触发时间延迟低

2.缺点:

  • 服务器重启后,数据全部消失,怕宕机
  • 集群扩展相当麻烦
  • 因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现OOM异常
  • 代码复杂度较高

3.netty时间轮算法

时间轮算法可以类比于时钟,如上图箭头(指针)按某一个方向按固定频率轮动,每一次跳动称为一个 tick

延时任务完成不释放,解决方案,java,开发语言
这样可以看出定时轮由个3个重要的属性参数,ticksPerWheel(一轮的tick数),tickDuration(一个tick的持续时间)以及 timeUnit(时间单位),例如当ticksPerWheel=60,tickDuration=1,timeUnit=秒,这就和现实中的始终的秒针走动完全类似了。

如果当前指针指在1上面,我有一个任务需要4秒以后执行,那么这个执行的线程回调或者消息将会被放在5上。那如果需要在20秒之后执行怎么办,由于这个环形结构槽数只到8,如果要20秒,指针需要多转2圈,位置是在2圈之后的5上面(20 % 8 + 1)

1.优点:效率高,任务触发时间延迟时间比delayQueue低,代码复杂度比delayQueue低

2.确定

  • 服务器重启后,数据全部消失,怕宕机
  • 集群扩展相当麻烦
  • 因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现OOM异常

4.使用消息队列

延时任务完成不释放,解决方案,java,开发语言

我们可以采用RabbitMQ的延时队列,RabbitMQ具有以下两个特性,可以实现延迟队列

  • RabbitMQ可以针对Queue和Message设置 x-message-ttl,来控制消息的生存时间,如果超时,则消息变为dead letter
  • RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,用来控制队列内出现了dead letter,则按照这两个参数重新路由

1.优点:高效,可以利用rabbitmq的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性。

2.缺点:本身的易用度要依赖于RabbitMq的运维,因为要引用RabbitMq,所以复杂度和成本变高文章来源地址https://www.toymoban.com/news/detail-821155.html

到了这里,关于延时任务的解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 定时任务报警通知解决方案详解

    定时任务是每个业务常见的需求,比如每分钟扫描超时支付的订单,每小时清理一次数据库历史数据,每天统计前一天的数据并生成报表等等。 随着微服务和云计算的兴起,定时任务技术也是发展迅速,不仅能做单机的定时任务,而且在分布式系统下应用也很广泛,成为了业

    2024年02月02日
    浏览(34)
  • Go异步任务解决方案 Asynq

    今天为大家介绍一个Go处理异步任务的解决方案:Asynq,是一个 Go 库,用于排队任务并与 worker 异步处理它们。它由Redis提供支持,旨在实现可扩展且易于上手。 Asynq 是一个 Go 库,用于对任务进行排队并与工作人员异步处理它们。 Asynq 工作原理的高级概述: 客户端将任务放入

    2024年01月17日
    浏览(38)
  • freeswitch的任务引擎问题与解决方案

      freeswitch核心框架中有一个定时任务系统task,在开发过程中用来做一些延时操作和异步操作很方便。 我们在VOIP的呼叫流程中,经常会有一些对实时性要求没那么高的操作,或者会有阻塞流程的操作,我们都可以开启一个定时任务子流程,来达到延时和异步的目标。 但是在

    2023年04月27日
    浏览(26)
  • 【go】异步任务解决方案Asynq实战

    Asynq 是一个 Go 库,一个高效的分布式任务队列。 Asynq 工作原理: 客户端(生产者)将任务放入队列 服务器(消费者)从队列中拉出任务并为每个任务启动一个工作 goroutine 多个工作人员同时处理任务 git库:https://github.com/hibiken/asynq Asynq 使用 Redis 作为消息代理。client 和 se

    2024年02月10日
    浏览(39)
  • 「Bug」“OSError [WinError 1455] 页面文件太小,无法完成操作” 解决方案

    训练YOLOv5模型时出现错误 修改train.py中配置项workers的默认值,从初始值8修改为0(也可以试试1或2等较小的数)。 workers_per_gpu=2, # 每个gpu分配的线程数,给每一个GPU喂数据的进程,GPU性能越强,取值越大,这样才能充分利用GPU的算力。如果用自己的电脑训练,这个值需要取小一

    2024年02月11日
    浏览(47)
  • 任务管理器显示不全的解决方案

      大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作

    2024年02月08日
    浏览(36)
  • MSB4018 “ResolvePackageAssets”任务意外失败 解决方案

    使用Vs2019,发现新创建的代码,也无法正常编译, 尝试过用visual自带的修复功能;去官网升级Nuget;甚至卸载Nuget;也无法解决. 详细报错内容如下 查询若干方法后,发现 解决方案 就藏在第二排提示中 Unable to find fallback package folder ‘D:MicrosoftXamarinNuGet’. ** 新建一个空目录 folder ‘

    2024年02月12日
    浏览(53)
  • 轻量级报表解决方案Telerik Reporting,轻松完成嵌入式报表交互!

    开发者可以通过多种方式与集成在应用程序中的Telerik报表进行交互,从“只是阅读它”到更改报表中包含的数据。 但是要注意:开发者所能做的一些事情将取决于报表是如何创建的,以及它是如何嵌入到应用程序UI中的。因此(和任何应用程序一样),为了从Telerik报表中获得想

    2024年02月08日
    浏览(61)
  • Haydn解决方案数字化平台助力架构师1小时完成架构设计(实操篇)

    如何基于Haydn快速完成几种常用集成架构的设计? 如何基于Haydn快速完成几种常用部署架构的设计? 如何基于Haydn高效分享架构设计? 设计器的使用有哪些小Tips? 1. Haydn解决方案数字化平台介绍 2. Haydn设计中心几种风格图元库的切换使用 3. 如何基于Haydn设计中心快速完成几种

    2024年02月03日
    浏览(53)
  • Ajax_4(进阶)同步异步+ 宏任务微任务 + Promise链 + async终极解决方案 +事件循环原理 + 综合案例

    01-同步代码和异步代码 什么是同步代码? 同步代码:逐行执行,需要原地等待结果后,才继续向下执行。 什么是异步代码? 调用后耗时,不阻塞代码继续执行,(不必原地等待),在将来完成后 触发一个 回调函数 。 代码阅读 目标:阅读并回答代码执行和打印的顺序 打印

    2024年02月13日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包