版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Ⅰ基于时间轮的分布式定时任务调度系统设计与实现 摘要 随着企业信息化程度的加深,分布式系统中定时任务的需求日益凸显,特别是在大规模、高并发的环境下,传统定时任务调度方式通常难以满足现在的要求。为了解决传统方法在高并发和大规模任务场景下的性能瓶颈和扩展性问题,本文基于多维时间轮实现了一套定时任务调度机制,解决了单点故障问题,改进了传统一维时间轮扩展性差的问题。 本文深入分析了现有定时任务调度技术的缺点,并探讨了时间轮算法在定时任务调度中的适用性。然后,详细设计了基于时间轮的分布式定时任务调度系统的整体架构,包括任务管理、时间轮算法设计、任务派发与调度、容错与重试机制等核心模块。系统采用了分级管理策略,将任务按照分时和分桶进行归类,以便更高效地进行任务调度。在时间轮设计上,本文创新性地提出了一种动态可扩展的时间轮结构,以适应任务数量的动态变化。本文通过引入分布式锁机制以及分时分桶逻辑,有效解决了任务在不同节点间的均衡分配和任务执行的一致性等核心问题。同时,通过引入布隆过滤器,确保每个任务只能被执行一次,有效避免了任务重复执行带来的业务系统数据不一致问题。 项目在Centos7系统中多机部署并运行后,定时任务调度性能比升级前提升了45%,可靠性提升了80%,出错率降低了50%。实践证明,本文提出的基于时间轮的定时任务调度算法能够有效提升系统性能,降低出错率。关键词:定时任务、分布式系统、时间轮、任务分发、分布式锁ⅡDESIGNANDIMPLEMENTATIONOFADISTRIBUTEDTIMEDTASKSCHEDULINGSYSTEMBASEDONTIMEWHEELSABSTRACTAsenterprisedigitizationadvances,theneedforscheduledtasksindistributedsystemsisbecomingmorepronounced,particularlyinlarge-scaleandhighconcurrencysettingswhereconventionalschedulingmethodsmaystruggletofulfillthedemands.Therefore,thisarticleproposesatimedtaskschedulingmechanismbasedontimewheelstoaddresstheperformancebottlenecksandscalabilityissuesoftraditionalmethodsinhighconcurrencyandlarge-scaletaskscenarios.Thisarticlefirstanalyzestheshortcomingsofexistingscheduledtaskschedulingtechniquesandexplorestheapplicabilityoftimewheelalgorithmsinscheduledtaskscheduling.Subsequently,theoverallarchitectureofadistributedtimedtaskschedulingsystembasedontimewheelswasdesignedindetail,includingkeymodulessuchastaskmanagement,timewheeldesign,taskdistributionandexecution,faulttoleranceandretrymechanism.Intherealmoftaskmanagement,thesystememploysastructuredapproachofhierarchicalmanagement,organizingtasksbytimingandallocationwithindesignatedbucketsforenhancedefficiencyinscheduling.Thisarticlepresentsanovelideainthedesignoftimewheels,introducingadynamicallyadjustabletimewheelstructurecapableofaccommodatingfluctuatingnumbersoftasks,respondingdynamicallytochanges.Duringthesystemimplementationphase,thepaperspecificallyaddresseschallengesrelatedtoensuringtaskconsistencyanddistributingtheworkloadevenlyinadistributedenvironment.Byintroducingdistributedlocksandtime-divisionbucketlogic,balancedallocationandconsistencyassuranceoftasksbetweendifferentnodeshavebeenachieved.Simultaneously,thesystemincorporatesaBloomfiltertoguaranteethateachtaskisexecutedonlyonce.Thefindingspresentedinthisarticleofferaneffectiveanddependablesolutionforschedulingtasksindistributedsystemsattheenterpriselevel,whilealsoservingasvaluableresourcesandpointsofreferenceforfutureresearchinthisarea.KeyWords:Timingtask;Distributedsystem;Timewheel;Taskdistribution;DistributedlockPAGEPAGE9目录摘要 3ABSTRACT 4目录 1第1章 绪论 31.1背景与意义 31.1.1研究背景 31.1.2研究意义 31.2国内外研究现状 41.3研究内容 61.4论文结构 7第2章相关技术介绍 82.1开发框架 82.1.1Gin框架 82.1.2Vue.Js框架 82.2开发语言 92.2.1Golang 92.3开发工具 92.3.1MySQL 92.3.2Redis 92.3.3MongoDB 102.4本章小结 10第3章需求分析 113.1功能需求 113.1性能需求 12第4章系统设计 134.1总体设计 134.2流程设计 154.2.1创建任务 164.2.2执行计划生成 174.2.3任务调度 184.2.4执行任务 194.3数据库设计 20第5章详细设计与实现 225.1任务管理模块 225.1.1创建任务 225.1.2查询任务 245.2日志监控模块 265.2.1调度日志 265.2.2监控系统 275.3调度模块 295.3.1二维时间轮 295.3.2迁移器 325.3.2调度器 325.3.3布隆过滤器 34第6章总结与展望 366.1总结 376.2展望 37致谢 39参考文献 40软件使用说明书 42一、 运行环境 42二、 分布式定时任务调度系统 421.登录 422.创建任务 423.激活任务 454.查询调度日志 465.监控系统 48
绪论1.1背景与意义1.1.1研究背景随着互联网技术的日益普及,已经深入渗透到我们生活的方方面面,因此,每天都会有海量的业务数据在企业级应用中产生。海量的数据使得越来越多公司的业务逻辑变得更加复杂,企业的许多业务中出现了大量的需要在特点时间点进行某种特定操作的业务场景[1]。例如,每天定时或定期从Hive表中读取一批业务数据进行计算和分析;每小时收集一次应用程序写入公共日志的数据,并将其存储至相应的介质中;每五秒更新一次信息管理系统的元数据等。传统的方式可以采用人工手动触发或者是使用Linux系统中的Crontab服务,但是前者过于耗费人力而且时间上不精确,后者具有单体故障的风险而且Crontab不提供秒级的定时服务。现代企业往往数据量巨大、业务复杂度高,加上应用系统的分布式架构,使得传统的实现方式并不能同时满足任务统一配置管理,海量定时任务的精准、高可靠触发,大规模子任务的分布式、高性能、高可靠的工作负荷自动化调度[2]。现代企业需要的定时调度系统往往需要具备集群化、面对不断增加的海量任务,可以无限进行水平扩展、提供高可用机制应对单点故障的风险、采用并发调度机制充分利用机器资源等等。1.1.2研究意义在信息化、数字化的时代背景下,企业级应用系统的规模和复杂性日益增长,对任务调度的需求也日益迫切。在企业级应用中,定时任务调度扮演着至关重要的角色,它对于保障系统的稳定运行、提升业务处理效率以及优化资源利用等方面都起到了关键的作用。所以,本文希望设计并实现一种基于时间轮的企业级分布式定时任务调度系统,具有比较重要的研究意义。首先,传统的定时任务调度方式往往存在扩展性差、可靠性低以及调度精度不足等问题,难以满足现代企业级应用的需求。但是基于时间轮的分布式定时任务调度系统,通过结合时间轮算法的高效性和分布式架构的可扩展性,能够有效实现任务的低延迟调度与高效率执行,从而增强系统的稳定性和性能。其次,本研究对于提升企业级应用的性能和效率具有重要意义。通过实现自动化的定时任务调度,可以有效释放人工劳动力,降低人工干预的需求,进而提升业务处理的效率。同时,系统能够根据任务的实际需求合理分配系统资源,避免资源浪费和空闲,实现CPU资源、内存资源等等的最大化利用。这不仅能够降低企业的服务器成本、人力成本,还能够提升企业的竞争力和市场地位。除此之外,本文的研究还有利于推动定时任务调度领域的技术发展和创新。在本项研究中,时间轮这种高效的定时调度算法得到了深入的探讨和改进。通过本文的实践,可以进一步推动时间轮算法在定时任务系统领域中的应用和发展。同时,本文研究的项目也将为其他相关领域的研究和实践提供些许参考。1.2国内外研究现状当前,不同的软件系统或多或少都包含了需要定期或定时执行的任务。面对这类业务场景,如何对这些任务进行高效的管理、打破单机任务的容量瓶颈、在分布式系统中完成任务并在任务失败时提供重试机制等,都需要一套完美健全的解决方案。国内外在面对这类问题时,解决办法比较通用,最常使用的两个定时调度服务就是Linux的Crontab服务和Quartz服务。1、CrontabCrontab服务是Unix/Linux系统中一个常用的定时任务调度工具,它允许用户根据自定义的时间表来设定任务的执行,这些时间表可以覆盖从每分钟、每小时到每天、每周,乃至每月等不同时间间隔的需求。用户可以在Crontab中定义多个任务并指定其执行时间,实现灵活的任务调度计划。在Linux操作系统中,Crontab工具通过标准输入接收用户的指令,并将这些指令保存到Crontab文件中,以便后续可以方便地读取和执行。Crontab存储的用户指令会经由守护进程激活,之后Crond会在后台运行,每分钟轮询检查是否有待执行的作业。Crontab文件包含送交Crond守护进程的一系列任务和指令[3]。但它也存在一些缺点。其中包括难以管理复杂任务依赖关系、不具备任务监控和自愈能力、不易调试和排查问题、无法处理动态任务调度等等。更加关键的是,Crontab作为一个单机服务,并不支持任务的分布式调度,无法在集群层面实现任务调度的协同工作。因此,它具有较高的单点故障风险,一旦主机发生故障,所有的定时任务都将被迫中断,对系统的稳定性和可靠性构成威胁。2、QuartzQuartz是一个开源并且功能完备的任务调度框架,采用Java语言编写实现,为在Java应用程序中进行任务调度提供了简洁却强大的调度机制。它既可以集成到其他应用服务里面,还可以独立部署运行。通过配置好Job实现类并设定好调度时间表,它会自动在设定的时间调度作业执行。Quartz框架主要是由JobDetail、Job、Scheduler、Trigger这4个核心类构成。其中Trigger是用于设置任务的触发时机,Trigger通过TriggerBuilder来进行创建。主要有两种触发形式SimpleTrigger和CronTrigger,SimpleTrigger可以在规定时期内触发并执行任务[4]。其中Quartz的分布式调度功能是其一大亮点,使得Quartz能够在集群环境下进行高效、可靠的任务调度。在Quartz集群中,每台服务器节点都是独立的节点,所以每个服务器节点都可以独立的进行任务调度[5]。Quartz的分布式调度基于数据库实现,通过数据库锁来保障多节点任务执行时的唯一性,从而避免了多个节点同时执行同一个任务的情况。在Quartz的调度模型中,每个节点(或实例)都是一个单独的调度器(Scheduler),它们共同合作完成任务调度。所有节点都会连接到同一个数据库,从里面获取任务信息并执行。当一个节点获取到任务并开始执行时,它会通过数据库锁来确保其他节点不会同时执行同一个任务。但是它也有一些不足之处,对于初学者或不了解Quartz的人来说,设置和配置可能会有些复杂,因为涉及到一些专业的调度概念如Job、Trigger和Scheduler等。这或许导致在使用Quartz进行任务调度时,用户需要投入一定的时间和精力来理解和学习这些功能。在一些高级功能已经定制化场景方面,比如任务管理、节点动态灵活扩展和分布式调度执行等方面,Quartz的支持还不够充分。而且Quartz需要将任务信息保存到业务数据库,这样做会增加与业务系统的耦合度。还会导致业务和调度之间在资源利用上互相影响。综上所述,我们需要研发一款更简单、任务管理功能更加完备、性能更高、横向扩展能力更灵活的定时任务调度系统。1.3研究内容本篇文章研究的是基于多维时间轮实现的分布式定时任务调度系统。具体研究内容如下:设计一种基于时间轮算法的定时任务调度系统的整体模型。本系统将会使用分布式架构,通过多个节点之间的协同式工作来实现任务的调度和执行。然后,将设计出合理的模块间通信机制和定时任务数据存储方案,用来确保系统的稳定性和高性能。详细阐述任务调度与执行模块的设计与实现过程。包括如何依据任务的特性和需求,使用时间轮算法进行任务的分发和调度;如何设计高效的任务调度机制,能够确保任务按时、准确地执行;以及如何处理任务执行过程中的异常情况和错误。为了提高系统的容错功能和负载均衡能力,本文将设计相应的机制。包括设计节点间的故障检测和恢复机制,以确保在节点故障时能够自动切换到其他正常节点;设计负载均衡策略,根据节点的负载情况动态调整任务分配,以平衡系统负载。1.4论文结构本文主要分了六个章节来分析基于多维时间轮算法实现的分布式定时任务调度系统。其中具体的内容如下:第一章:绪论。介绍基于多维时间轮的定时任务系统如何设计以及实现这个项目的背景和相关领域的现状,还有此项研究的目标和意义等等。第二章:技术介绍。介绍自己设计的分布式定时任务调度系统的模块结构以及使用的开发框架、开发语言和开发工具等。第三章:需求分析。分析该课题的可行性,对该系统功能的描述以及对于其性能的分析研究等,并画出ER图。第四章:系统设计。描述该系统的架构、功能、数据库表设计以及用户管理界面的设计等。第五章:系统整体功能的实现,并对其进行测试,对于相关的问题进行修正完善。第六章:总结与展望。对该课题进行的总结,实现该课题时的感受,以及对该系统未来前景的想法。
第2章相关技术介绍2.1开发语言2.1.1Golang本项目目标是构建一个高性能、低延时、资源分配合理、扩展性高的分布式系统,系统中的定时任务调度功能需要使用并发编程,以达到对机器CPU资源的合理利用。Java、C++等语言在并发编程方面需要编写大量冗余、繁杂的代码,而且只能创建操作系统内核线程级别的最小调度单元,而且根据操作系统的不同,一个线程的堆栈大小为1MB~8MB左右,线程数量一旦到达百级别,很可能引起服务器内存资源耗尽。所以,考虑到上述原因,选用Go语言来编写本项目的后端模块。Go语言由Google团队开发和维护,其便捷、高效、高并发、丰富的类库获得了众多开发者的喜爱[8]。系统需具备并发调度的能力,Go语言非常适合并发编程,其在语言层面实现了协程,单个协程仅占2kb,系统开销远小于操作系统中的线程,而且多个并发组件,大大降低了并发编程的心智负担。除了传统语言中基于锁的同步方法,Go语言提供了一种CSP(communicatingsequentialprocesses)风格[9]的多个协程间通信机制,简化了并发环境中的数据交互。2.2开发框架2.2.1Gin框架本项目还将设计一个任务管理平台供用户使用,用户可以在管理平台中使用任务管理、查询调度日志、查看监控看板、查看任务手册等功能。客户端浏览器和后端模块采用HTTP协议进行通信,所以后端模块中需要使用Go语言构建一个HTTP服务器,目前业界比较流行的Web服务器框架有:Echo、Beego和Gin,前两个框架的发布时间比较早,但是存在诸多问题,比如日志功能混乱、路由匹配机制性能差、扩展性差等等,而Gin作为GolangWeb框架中的新势力,比较完美的解决了上述问题,所以本项目采用Gin作为Web框架。Gin是一个以Go语言开发的Web框架,它提供了martini-like形式的API,它具有运行速度快,能够进行路由分组,支持中间件和JSON验证等功能,并且有优雅错误处理机制,在当前的Web开发中非常流行[6]。它具有以下优点:高性能:Gin框架底层复用了HttpRouter库的路由模型,使用基数树构建路由树,可以快速匹配和处理大量的请求。简洁易用:Gin提供了简洁的API设计,开发者可以轻松地创建路由、中间件等,代码可读性强。中间件支持:Gin框架提供了灵活的middleware机制,可以对HTTP请求进行预处理、日志记录、权限控制等操作。JSON支持:Gin框架内置了对于JSON的支持,开发者可以便捷地处理JSON数据。2.2.2Vue.Js框架本项目的任务管理平台定位是一个小型的网站系统,为了更加便捷、快速的进行开发,需要选择一款上手简单、文档完整、社区活跃的前端框架,这里不选用学习成本较为高的Angular和React框架,而是选用易上手,而且支持组件化开发的Vue.js框架。Vue.js是一个轻量级的前端框架,是一个非常易于上手的框架,因为它的API设计非常直观和简单,官网文档介绍的也比较完整。Vue使用了虚拟DOM来实现高效的渲染,并提供了一些有用的指令和组件等,来协助开发者快速构建复杂的应用。Vue的性能非常好,因为它的体积小,加载速度快,同时也提供了一些优化工具,如异步组件、代码分割等。框架的优点包括:简单易学、双向数据绑定、组件化开发、虚拟DOM、社区活跃[7]。2.3开发工具2.3.1MySQL项目中有一些关系化模型,比如定时任务以及基于定时任务生成的执行计划,还有用户信息,所以需要一个关系型数据库来存储这些关系模型数据。基于服务器成本、学习成本考量,这里还是选用开源、轻量级、使用广泛的社区版MySQL数据库。MySQL是目前主流的关系型数据库[10],广泛应用于Web应用程序中。它采用SQL语言进行数据管理,支持事务处理,并具有高性能、稳定可靠、跨平台等特点。MySQL提供了多种安全功能,包括用户权限管理、数据加密等,适用于各种规模的应用场景。2.3.2Redis由于后端模块访问MySQL的QPS会比较高,项目需要构建一个缓存系统来减少数据库的请求压力,而且由于后端模块是分布式部署的,时间轮的实现也需要放在一个第三方组件中,而不是在应用系统的内存中,此外为了实现分布式系统中事务的ExactlyOnce特性,也即保证任务不会被重复执行,需要引入比如布隆过滤器这种数据结构。这里同样选用具备开源、轻量级、使用广泛特性的Redis数据库。Redis是一种基于内存的开源KV存储系统,常用于数据库缓存、在线数据存储、会话管理、消息队列等场景。另外Redis支持丰富的数据类型[11](如字符串、哈希、列表、集合、有序集合等),具有快速的读写操作速度和高并发性能。Redis还提供了持久化机制RDB、AOF,以及节点间的数据复制功能,可以确保数据的安全性和可扩展性。因为其高效的数据存储和读取能力,Redis被广泛应用于大规模网络系统、实时数据处理等场景。2.3.3MongoDB每个定时任务在执行完成之后,后端模块会将执行结果构造成一条调度日志,然后存入一个日志存储组件中,供业务方进行查询。日志是一种半结构化数据,而关系型数据库需要事先定义表结构,适合存储结构化数据,所以并不适合直接存储日志数据,需要进行一步序列化。所以这里选用扩展性高、开源的文档型数据库MongoDB。MongoDB是2009年发布的一种NoSQL的文档数据库系统,它采用C++语言开发实现[12]。它采用文档型存储方式,通常用于分布式海量数据存储、处理和运算。MongoDB以其灵活的数据模型和高性能著称,支持复杂的数据查询和分析,适用于需要处理半结构化和非结构化数据的场景。MongoDB具有强大的水平扩展能力,可以轻松应对高并发和海量数据量的场景。它还提供了丰富的查询语言和索引功能,便于开发人员进行数据操作和分析。MongoDB的特点包括高可用性、自动故障恢复、数据冗余备份等,使其成为许多企业和开发团队首选的数据库解决方案。2.4本章小结本章对项目中要用到的开发框架、开发语言和开发工具做了大致的介绍,阐述了每种框架和工具的基本情况、使用场景以及优势特点。
第3章需求分析3.1功能需求首先本系统有一个定时任务管理平台,供用户使用,为用户提供任务接入、查用户手册、日志查询、监控看板等服务。以下是该管理平台的具体功能需求:任务管理:系统支持任务的创建、编辑、删除、查询等基本操作,同时支持任务的启动、暂停、恢复等功能。定时策略:该系统提供了灵活的定时策略配置功能,通过Cron时间表达式来设定定时任务的启动时间和执行间隔,从而满足用户多样化的需求。调度日志:系统为用户提供了查询MongoDB调度日志的入口,用户可以通过查询日志来排查任务调度失败的原因。监控系统:系统基于Grafana与Prometheus搭建了一套日志系统,用户可以查询基础监控与业务监控,便于查看系统的性能瓶颈以及感知系统的运行风险。文档沉淀:任何系统在设计之初都应该具有前瞻性,考虑到系统的后续迭代升级,设计了文档沉淀模块,用户可以在该模块进行问题记录、改进意见、技术分析等等,此外新用户还可以在这里看到系统的使用手册。定时任务管理平台的设计理念是大道至简,聚焦于让用户做最少的操作完成功能。首先对定时任务管理平台的功能模块做了拆分,分为四个子模块:登录模块、文档模块、定时器模块和监控模块,然后将系统功能依次划分到上述四个子模块中,详细的功能模块图如图3-1所示。图3-1定时任务管理平台功能模块图3.1性能需求除功能需求之外,系统的性能需求也是需要重点考虑的。传统的单体架构往往难以扩展,这可能导致性能瓶颈和难以应对高负载的挑战[13]。我们的设计目标是构建一个高性能、低延时的分布式系统,而且系统在面对流量高峰出现性能瓶颈时,需要具备横向扩展的能力。具体的性能需求如下:分布式调度:系统应该支持分布式环境下的任务调度,能够自动将任务分发给各个节点执行,实现负载均衡和容错处理。高并发:系统应该能够支持高并发场景下的任务调度调度和执行,确保系统的稳定性和可靠性。低延迟:为了优化系统性能,我们应该努力减少任务调度过程中的延迟时间,以提升任务执行的效率。可扩展性:系统应该拥有较为灵活的扩展性,可以基于业务需求的变动以及业务量级的增加,轻松方便的实现节点的扩展和性能的提升。容错处理:系统应该具备容错处理能力,能够在部分节点出现故障时自动切换到其它正常节点执行任务。
第4章系统设计4.1总体设计基于时间轮的分布式定时任务调度系统总体设计为分层设计,将系统模块和系统功能进行清晰的分离,使得系统的架构更加直观。降低理解成本,系统架构图如图4-1所示。系统架构总体分为四层:用户服务层、业务逻辑层、任务调度层和数据存储层。每层的功能如下所示:用户服务层:该层充当整个系统的前端界面与交互枢纽,负责接收用户的操作指令。该层提供友好的用户界面,使用户能够方便地创建、编辑、查询和删除定时任务,同时用户服务层还向用户提供了查询MongoDB调度日志的入口,此外能够监控任务的执行状态和结果,方便用户及时了解任务执行情况和处理异常情况。业务服务层:业务服务层是系统的核心逻辑处理层,主要负责处理与定时任务相关的业务逻辑,提供用户登录、文档查询、监控查询、任务管理等功能。除此之外,业务服务层还提供了一系列的API接口,供其他系统或者模块与定时任务调度系统进行相互调用。调度层:调度层是整个系统的核心部分,主要职责是实现基于时间轮的定时任务调度算法。调度层会根据策略以及多维时间轮算法,计算生成任务的执行时间,并将任务分配相应的机器节点去执行。同时,调度层还负责监控任务的执行状态,当任务出现异常或失败的时候,能够进行容错处理。此外调度层还具备负载均衡能力,能够根据节点的负载情况动态调整任务的分配,确保系统的稳定运行。数据存储层是系统的数据存储和管理层,主要负责存储和管理与定时任务相关的数据。该层采用高效稳定的存储方案,比如关系型数据库MySQL、文档型数据库MongoDB以及NoSQL数据库Redis等等,确保数据的安全性和可靠性。数据存储层存储的任务数据包括定时任务的元信息、执行计划、调度日志、监控数据等等。通过提供高效的数据访问接口,数据存储层为上层服务提供数据支持,确保系统的正常运行和决策分析。图4-1系统架构图此外由于系统的功能模块较为复杂,根据软件架构设计准则,将系统的后端模块拆分为两个子系统:Api模块和Exec模块,两个子系统各司其职,降低了总体的耦合度,提高了系统的可维护性、灵活性和扩展性。拆分之后,系统的总体功能流程图如图4-2所示。其中两个子模块各自的功能和作用如下所示:Api模块:负责处理用户对定时任务的增删改查,内嵌迁移器,每隔一小时生成下一小时的执行计划。内含两个子模块:WebServer和Migrator。Exec模块:负责从存储模块中获取定时任务的执行计划来调度执行。任务执行完毕后,会将任务的执行结果和输出信息存储到MongoDB的调度日志中,并同步报告给监控系统。图4-2整体功能流程图4.2流程设计本小节重点介绍系统中几个核心模块的流程设计。包括定时任务管理、如何生成执行计划、任务如何调度、任务如何执行。4.2.1创建任务任务创建是提供给用户最基本的功能,用户需要填写创建定时任务的表单,需要填写任务名称、Cron表达式、HTTP方法、回调函数的URL、回调函数的参数这些信息,前端会使用POST方法去请求Api模块的相应接口。接着Api模块中的接口会进行参数校验,接着基于雪花算法为任务生成一个8字节长的唯一ID,然后将任务信息插入数据库的Timer表中,其中Timer表中的任务名称字段有一个唯一索引,意味着任务名称不能重复,如果重复了则插入失败,Api模块会向前端返回错误。图4-3创建任务流程图4.2.2执行计划生成执行计划是对每个定时任务执行时间点的抽象,可以理解为每个定时任务的触发事件,执行计划的组成部分包括定时任务ID和执行时间的秒级时间戳。假如一个定时任务的ID是00000001,该定时任务的执行间隔为30秒,那么一分钟内该定时任务就会生成两个执行计划,分别是00000001_0秒时的时间戳和00000001_1秒时的时间戳。生成的执行计划会被存入MySQL和Redis中,执行模块会优先拉取Redis中的执行计划来触发相应的定时任务。执行计划的生成由Api模块中的迁移器实现,迁移器会每隔1分钟轮询一次数据库的定时任务表,生成下一个小时的所有执行计划。具体的实现逻辑如下:迁移器在每个小时的第1分钟抢占1小时粒度的Redis分布式锁,抢锁成功则轮询数据库中的Timer表,生成下一个小时的所有执行计划。后续的第2到59分钟,迁移器都会先轮询一遍数据库中的Timer表,查看是否有新创建的定时任务,如果有,就生成该定时任务当前小时和下一个小时的所有执行计划。然后再次获取分布式锁,为第1分钟生成执行计划失败的情况做兜底。每次生成的执行计划会插入到MySQL的执行计划表中,再插入到Redis的ZSET对象中,其中Redis作为数据库的缓存。图4-4创建任务流程4.2.3任务调度 任务调度由调度模块Exec来实现,Exec模块通常是多机部署的,如果定时任务的数量较少,建议Exec集群中至少有3台容器或者物理机。调度模块会每隔60s的时间间隔从数据存储模块中读取一批执行计划来运行。由于是多机环境,所以还存在并发冲突的场景,这里引入了Redis的分布式锁来解决,多台机器通过竞争分布式锁的方式获取一分钟粒度执行计划的调度权。具体逻辑如下:每台调度机器去竞争当前分钟的Redis分布式锁,锁的key为:redis-lock_当前分钟时间戳,锁的value为当前机器hostname+进程id+协程id。抢锁成功则进入一个调度循环,每隔1秒创建一个协程,该协程会去Redis的ZSET对象中获取当前秒的所有执行计划。当前机器经过60秒的调度循环,将当前分钟粒度内的所有执行计划运行完毕。图4-5任务调度流程4.2.4执行任务上一小节介绍了每台机器在抢占Redis分布式锁成功的情况下,对当前分钟区间内所有执行计划的调度方式。到最后,这台机器上运行的每个协程都将执行当前秒内的所有计划任务,其执行逻辑如下所示:负责调度的协程会把获取到的执行计划交给协程池,由协程池执行具体的定时任务。这里使用协程池的目的是为了更好的资源管理优化和并发控制,项目中引入的是腾讯开源的ants协程池框架。协程池中的worker首先会去数据库获取该执行计划对应的定时任务的元信息,比如回调函数URL、HTTP方法、回调函数参数等等。接着构造一个HTTP请求,通过HTTP请求来调用业务模块中的回调函数,以这种方式来执行业务逻辑。最后将执行结果比如执行输出、错误日志等信息存入MongoDB的调度日志中,并上报到监控系统。图4-6执行任务流程4.3数据库设计本系统的重点在于任务调度,关系模型设计的尽可能简单化,所以只有三张数据表,分别为定时任务表、执行计划表和用户表。系统的E-R图如图4-7所示。图4-7定时任务调度系统E-R图本系统的关系型数据库选型为MySQL,用来存储定时任务的元信息、执行计划和用户信息。数据库里面包含了3张数据表,分别是用户表、定时任务表和执行计划表,每张表的字段设计和索引情况如下所示:用户表:本张表用于记录用户信息,包含三个字段:id、用户名和用户密码。其中id是表的主键,为了用户的名称重复导致登录失败,我们在username这个字段中添加了唯一索引。表4-1用户表字段名数据类型是否非空描述备注idbigint(20)是id主键usernamevarchar(100)是用户名passwordvarchar(100)是密码定时任务表:本表用来存储定时任务元信息,用户新接入的定时任务会插入到这张表中,表中包含任务id、任务名称、cron表达式、回调函数url、回调函数参数等字段,其中任务id是主键,任务名称添加了唯一索引。表4-2定时任务表字段名数据类型是否非空描述备注idbigint(20)是id主键namevarchar(100)是定时任务名statuscronmethodurlheaderbodycreated_atupdated_atdeleted_attinyint(1)varchar(100)varchar(100)varchar(100)varchar(100)varchar(100)datetimedatetimedatetime是是是是是是否否否状态cron表达式http方法urlheader请求体创建时间修改时间删除时间执行计划表:本张表用来存储每个定时任务生成的执行计划,它与定时任务表的关系是1对n,表里面包含id、定时任务id、执行输出、运行时间等字段。其中id是主键,为timer_id和run_timer添加了唯一索引,由于服务端会频繁的通过运行时间字段来查询相应的执行计划,所以为运行时间字段run_timer也添加了普通索引,提高查询该表记录的性能。表4-3执行计划表字段名数据类型是否非空描述备注idbigint(20)是id主键timer_idbigint(20)是定时任务idoutputrun_timercost_timestatuscreated_atupdated_atdeleted_atvarchar(100)datatimeint(10)tinyint(1)datetimedatetimedatetime是是是是否否否输出结果执行时间执行耗时当前状态创建时间修改时间删除时间
第5章详细设计与实现5.1任务管理模块5.1.1创建任务用户登录之后会直接进入系统的主页,然后点击定时器侧边栏就会进入任务管理模块,这是本系统向用户提供的最核心的功能。用户可以在这个界面操作定时任务,对定时任务进行增删改查,后端逻辑较为简单,本质上还是用sql语句操作定时任务表的数据。创建定时任务的用户请求会执行handler.CreateTimer函数的逻辑,handler层的CreateTimer函数负责进行参数校验如图5-1所示,其内部调用了service层的CreateTimer函数,该函数内部执行真正的业务逻辑,首先调用雪花算法包生成一个定时任务id,构建一个数据库Model结构体,然后调用DAO层的CreateTimer函数将新的定时任务插入数据库的定时任务表中。其中name字段添加了唯一索引,数据库会自动判断该字段是否重复。图5-1参数解析图5-2创建任务逻辑以创建任务功能为例,点击图5-3中子页面的新建任务按钮,管理平台会弹出一个对话框如图5-4,用户可以在对话框中填写需要接入的定时任务信息,然后点击提交,后端校验参数,如果无误就可以创建成功。图5-3任务管理页面图5-4新建任务页面5.1.2查询任务在进入任务管理平台的主页面时,所有定时任务将以表格形式呈现给用户。该表格支持分页功能,默认显示最新添加的5条定时任务,用户可以根据需求翻页查看更多。其中分页逻辑是在后端模块中实现的,查询请求中会携带本次需要查询的页号,默认是0号页面,然后使用sql语句:select*fromtimersorderbycreated_atdesclimit5offset0;进行查询,首先根据定时任务的创建时间对所有记录进行倒序排序,使用offset关键字指定查询的是第一页的数据,使用limit关键字指定返回5条记录,相关的查询逻辑代码如图5-5所示。图5-5分页查询逻辑点击项目的定时器模块之后,如图5-6所示,就可以看到最新的5条任务会以表格的方式对用户进行呈现。图5-6分页展示5.2日志监控模块5.2.1调度日志任务管理模块向用户提供了查询调度日志的入口,通过点击表格操作栏中最右侧的日志按钮,就可以从MongoDB中查询该定时任务最近的5条调度日志,当然用于展示调度日志的表格也做了分页展示。调度日志的插入逻辑如图5-7和图5-8代码所示,每次定时任务成功执行后,程序都会异步调用reportLog函数,将这次的调度结果制作成一条调度日志,并随后将其保存到MongoDB数据库中。 图5-7异步添加日志图5-8调度日志插入MongoDB调度日志界面如图5-9所示,如果日志中某项任务的执行状态标记为Fail,意味着该任务在这次执行中未能成功,用户可以通过查看错误日志来诊断问题。通常,定时任务的执行状态会显示为Success,表明任务已成功执行,此时用户可以查阅执行结果。图5-9调度日志5.2.2监控系统在管理平台中,用户可以在监控看板侧边栏中查看系统的业务监控和基础监控。这些监控指标会在程序中打点采集数据,然后暂存在应用服务器中,然后我在应用程序中创建了一个http接口,Prometheus服务端会每隔15s访问一次该http接口,然后将采集的数据存入内部的时序数据库中。Grafana服务端也会定期从Prometheus的时序数据库中采集最新的监控数据,然后根据我们配置的策略渲染到面板中,供用户进行查看。其中应用模块采集指标数据并同步到监控系统的逻辑如图5-10所示。图5-10监控采集其中业务监控中有:当前处于激活态定时任务的数量、未执行的执行计划数量、生成的执行计划的总数、执行耗时这四个指标,用户可以通过观察这些监控指标来感知系统的运行状态,规避风险。基础监控是对Go程序的一些指标监控,主要有:正在运行的协程数量、GC耗时、堆内存的大小、栈内存的大小等指标,用户可以通过观察这些指标来排查出系统的性能瓶颈。用户端的监控界面如图5-11和图5-12所示。图5-11业务监控图5-12基础监控5.3调度模块5.3.1二维时间轮时间轮是一种实现延迟功能的算法,用于计算机系统中的定时器数据结构,时间轮以环形的队列作为时间格(TimingWheel),每个时间格上挂载着以双向链表数据结构存储的任务列表,双向链表中的每一个元素表示需要执行的任务项,这些任务项的执行时间一致,省去了任务调度器逐个判断任务执行时间的开销。通过表盘指针指向当前时间所在的位置,当指针指向到某一个时间格时,则任务调度器就将该链表上的所有任务取出执行[14]。首先,实现定时任务最简单粗暴的方式就是轮询+触发。为了去轮询定时任务,我们需要先构建一个时间轮,时间轮可以看成是一个时钟如图5-13,由一个个小格子组成,每个定时任务都会根据调度时间生成一批执行计划,执行计划可以看成一个时间节点,用来记录任务的执行时间。随着时间的流逝,我们会不断实时地查询时间轮里的任务计划,并触发那些被轮询到的任务计划以执行它们。比如一个定时任务规定30秒执行一次,假如当前时间是15:20,那么在这一分钟里面,这个定时任务会生成15:20:00和15:20:30这两个时间点的执行计划。图5-13时间轮模型然而,我们的目标是构建一个集群模式的分布式调度系统,这意味着集群中的所有节点都应该共同承担定时任务的执行。因此,我们首先实现了时间的纵向切片,以分钟为单位,将当前分钟内所有任务的执行计划集中存储,如图5-14所示。比如存在一个链表中,那么一小时就会生成60个一分钟粒度的执行计划链表。每当时间轮轮询到新的一分钟,集群中的所有机器就去获取执行计划链表,当前的实现方式是所有机器去获取分钟粒度的分布式锁,抢锁成功的机器即可获得当前分钟链表的执行权。图5-14一维时间轮由于golang非常适合用于并发编程,为了充分利用每台机器的CPU资源,我们会在每台机器中创建一个大小为1000的协程池。而为了能够将所有执行计划分摊给每个协程,避免池中多数协程处于忙等待状态,我们需要将执行计划的分组拆分为更细的粒度。假如一分钟有800个执行计划,那一个协程就需要调度800个执行计划,我们完全可以让8个协程分别去调度100个任务,充分利用并发能力。基于以上诉求,我们决定将一分钟粒度的所有执行计划拆分为8个桶,相当于一分钟有8个执行计划链表。也就是在横向上再添加一个分桶的维度,从而保证每个时间范围里面都能有对应于分桶数量的协程并发参加工作。最终我们得到了一个二维时间轮的结构如图5-15所示,一维用于分时,二维用于分桶。假如一个任务30秒触发一次,生成和运行执行计划的过程如下:首先找到该任务对应的一分钟粒度时间分片,也就是一维分片。然后将任务id对最大桶数8进行取模操作,得到应该被划分的桶号,最后在相应桶号的链表中生成这条执行计划。随着时间轮的运转,每台机器中的每个协程会去获取当前分钟+当前桶的二维分布式锁,抢锁成功,即可获得当前分钟+当前桶执行计划的调度权。图5-15二维时间轮5.3.2迁移器迁移器的作用是生成下个小时的所有执行计划,位于API模块中,每小时进行一次迁移,生成下个小时的所有执行计划,然后将生成的记录分别存入Redis以及MySQL中。具体实现是在一个forselect循环里面每隔60秒轮询一次数据库的Timer表,如果抢占分布式锁成功,就生成下一小时的执行计划;期间也会检查是否有新定时任务接入,如果有,则为这个新的定时任务生成当前小时和下一个小时的所有执行计划。具体代码逻辑如图5-16所示。图5-16迁移器实现逻辑5.3.2调度器调度器的作用是获取时间轮中的二维分片,然后去Redis中获取该分片的所有执行计划,最后交给协程池去执行。由于整体逻辑较为复杂,所以分成了三步:拼接出当前分钟的时间+桶号表达式,然后获取Redis的分布式锁,抢锁成功之后,即可获取到时间轮中的二维分片。调度器的执行逻辑如下:基于timeticker每隔1s进行轮询,基于当前时间推算出对应的分钟级别时间范围的表达式;读取配置文件获取最大桶数的信息,基于时间范围来拼接桶号,获得当前需要关心的二维分片的key;尝试抢占对应于每一个二维分片的分布式锁;抢锁成功,则从协程池中取出一个协程调度执行该分片中的所有执行计划。当获取到对应的时间分片之后,进入一个调度循环,每秒开启一个协程,然后去Redis中获取当前秒的所有执行计划异步执行,如此循环60次。这部分的代码逻辑如图5-17所示。最后每个协程会去执行当前秒的定时任务,执行逻辑是这样的:首先对定时任务进行幂等去重,具体在下一节中展开,执行定时任务,调用HTTP回调函数,然后上报执行监控和执行日志,最后更新MySQL定时任务执行记录的状态为已执行。图5-17调度循环5.3.3布隆过滤器分布式环境中,可能存在同一个二维分片的执行计划,被两个协程重复执行的情况。比如协程A成功拿到了一个二维分片的执行权,由于GC或者是容器竞争导致分布式锁过期之后,执行计划还是没有被执行,这时候协程B拿到了同一个二维分片的执行权然后执行。协程A恢复正常之后,又将执行计划执行了一遍,造成重复执行。解决这个问题看似非常简单,在执行任务之前,先去数据库执行计划表中查询一次,是否被执行即可。但是假如1秒钟有几千上万个执行计划,我们就会对数据库造成几千上万的qps压力,执行计划数量一多很可能会将数据库打挂。所以打算引入布隆过滤器如图5-18所示,这是一种常用的用于过滤请求的数据结构,能防止大量的无效请求穿透数据库。原理是将数据库中已有的记录经过k个哈希函数的哈希计算,再将计算得到的哈希值投射到二维矩阵中的k个点上。当一个请求到来时,先对请求中的记录做k次哈希计算,再将计算得到的哈希值与二维矩阵中的点做对比,如何有一个点对应不上,则证明数据库中没有这条记录,予以过滤;否则,鉴于哈希函数可能存在碰撞的特性,这条记录有可能已经存在于数据库中,所以布隆过滤器具有一定的假阳性。图5-18布隆过滤器由于标准布隆过滤器使用布尔数组存储元素,当有多个元素同时映射到相同位置时,布隆过滤器仅会被设置一次。加之标准布隆过滤器不存储每个位置由哪些元素设置,因此当多个元素由于哈希冲突同时映射到相同位置时便会产生假阳性。更重要的是,由于可能有多个元素同时共享一个比特位,删除某一个元素时会影响到同样映射到该位置的其他元素,因此标准布隆过滤器无法支持删除操作[15]。项目采用分布式架构,为了确保所有机器使用同一个布隆过滤器,布隆过滤器得在一个第三方组件中实现。由于前面引入了Redis,所以决定采用Redis的Bitmap对象来实现。首先,我们对某个执行计划的时间戳、桶号和任务ID进行k次哈希运算,然后将得到的哈希值映射到RedisBitmap中的k个位点上。执行器在执行之前,将当前任务的:时间戳+桶号+任务id也做k次哈希,然后去Redis的Bitmap上校验这k个点,用此方法来去重。其中往布隆过滤器中设置值以及判断某个key是否存在的逻辑如图5-19所示。图5-19布隆过滤器实现
第6章总结与展望6.1总结本论文致力于满足企业级分布式系统中定时任务调度的需求,设计并实现了一个基于多维时间轮的定时任务调度系统。该系统采用时间轮算法,有效地突破了传统定时任务调度方法在高并发、大规模任务场景下的性能局限,同时确保了分布式环境下任务的稳定执行和负载均衡机制的实现。在系统设计方面,本篇论文首先探讨了定时任务调度的核心需求和面临的挑战,随后深入解释了时间轮算法的工作原理以及它在定时任务调度中的实际应用。基于多维时间轮算法,我们设计了一个分布式定时任务调度框架,包括任务注册、任务触发、任务执行等核心模块。同时,为了确保系统的可靠性与稳定性,我们还设计了一套任务容错和负载均衡的机制。在实现过程中,采用了分布式系统的相关技术,如分布式锁等,实现了任务的分布式注册和触发。此外,还对时间轮算法进行了优化,通过调整时间轮的时间粒度和横向扩展,以适应不同规模和负载的任务场景。通过一系列的实验和测试,验证了基于时间轮的分布式定时任务调度系统的有效性和性能优势。实验结果表明,该系统在高并发、大规模任务场景下能够保持良好的性能和稳定性,同时能够显著降低系统的资源消耗和运维成本。6.2展望尽管基于时间轮的分布式定时任务调度系统已经取得了一定的成果,但在以后的工作中,已然有着很多可以进一步探索和改进的地方。首先,随着企业业务的不断发展和复杂化,定时任务的类型和需求也在不断变化。所以,需要进一步优化和完善任务调度算法,以适应更加复杂和定制化的任务调度场景。例如,我们可以考虑引入更为智能的任务调度策略,诸如基于机器学习的预测调度或是动态优先级调度等。其次,随着云计算和大数据技术的快速发展,分布式系统的规模和复杂性也在不断增加。因此,需要进一步提高系统的可扩展性和容错性,以应对更加严峻的挑战。比如,可以考虑接入更加高性能的分布式通信机制比如RPC,以及更加完善的容错还有恢复策略等。此外,我们还可以考虑将本系统与其他企业级系统进行集成和融合,如与企业级服务总线、分布式配置中心等进行集成,以提供更加全面和高效的企业级服务。总之,定时任务系统是一个具有广阔应用前景和研究价值的课题。我将继续对该系统进行深入的研究和优化,旨在为企业级分布式系统的定时任务调度提供更高效、可靠和智能化的解决方案。
参考文献彭浩西.基于Quartz的分布式定时任务调度系统的设计与实现[D].东南大学,2022.DOI:10.27014/ki.gdnau.2022.000925.孙岩.基于分布式架构的高可用定时任务调度系统的设计与实现[D].哈尔滨工业大学,2018.陈素琴.Linux中的定时任务探讨[J].现代计算机(专业版),2010,(13):70-71+77.KumarP,SharmaK.Anoveltaskschedulingalgorithmforrealtimesystems[C].InternationalConferenceonCommunicationandSignalProcessing.Melmaruvathur,India,2013:995~998.NathR,NagarajuA.Anoveltaskassignmentheurist
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年PHR人力资源专业人士资格考试备考题库及答案解析
- 2025年临海市机关事务中心招聘编外5人(四)考试模拟试题及答案解析
- 区块链技术投资协议2025年意向书
- 内容编辑兼职合同协议2025年规范条款
- 2025年员工档案与信息安全管理考试试题及答案
- 劳动合同2025年全职合同协议
- 2025年人力资源数字化与系统选型考试试题及答案
- 2025年创新提案与合理化建议奖励制度考试试题及答案
- 土方运输工程合同范本
- 外贸委托加工合同范本
- DB44-T 2457-2024 地质灾害自动化监测规范
- 慢性心衰患者的麻醉管理
- 河南2024定额计算规则
- 苹果树冬季修剪培训课件
- DB 33- 805-2010 压缩空气站运行电耗限额及节能 监测技术要求
- 年产1000吨饼干生产可行性研究报告建议书
- 印刷行业作业安全管理总结
- 入职的邀请函八篇
- 社区垃圾分类培训课件
- 高血压患者健康管理服务规范
- 2024年建筑艺术之美:桥梁建筑的魅力
评论
0/150
提交评论