业界前沿 分布式定时任务开源框架

laofo · 发布于 2018年11月20日 · 最后由 laofo 回复于 2018年11月20日 · 48 次阅读
4

分布式定时任务开源框架

  • Elastic-Job(当当网)
  • light-task-scheduler
  • clover
  • TBSchedule(阿里)
  • niubi-job
  • Uncode-Schedule
共收到 3 条回复
4
laofo · #1 · 2018年11月20日

单机定式任务调度的问题 在很多应用系统中我们常常要定时执行一些任务。比如,订单系统的超时状态判断、缓存数据的定时更新、定式给用户发邮件,甚至是一些定期计算的报表等等。常见的处理方式有线程的while(true) 和sleep组合、使用Timer定时器触发任务又或者是使用quartz框架。貌似这些方法可以完美的解决方案,为什么还需要分布式呢?主要有如下两点原因:

1.高可用:单机版的定式任务调度只能在一台机器上运行,如果程序或者系统出现异常就会导致功能不可用。虽然可以在单机程序实现的足够稳定,但始终有机会遇到非程序引起的故障,而这个对于一个系统的核心功能来说是不可接受的。

2.单机处理极限:原本1分钟内需要处理1万个订单,但是现在需要1分钟内处理10万个订单;原来一个统计需要1小时,现在业务方需要10分钟就统计出来。你也许会说,你也可以多线程、单机多进程处理。的确,多线程并行处理可以提高单位时间的处理效率,但是单机能力毕竟有限(主要是CPU、内存和磁盘),始终会有单机处理不过来的情况。

这个时候就需要分布式的定时任务来实现了。业内常用的分布式定式任务解决方案主要有quartz、淘宝的TBSchedule和当当的elastic-job。

quartz的集群解决方案

quartz的单机版本大家应该比较熟悉,它的集群方案是使用数据库来实现的。 上图三个节点在数据库中都拥有同一份Job定义,如果某一个节点失效,那么Job会在其他节点上执行。由于三个节点上的Job执行代码是一样的,那么怎么保证只有在一台机器上触发呢?答案是使用了数据库锁。在quartz的集群解决方案里有张表scheduler_locks,quartz采用了悲观锁的方式对triggers表进行行加锁,以保证任务同步的正确性。一旦某一个节点上面的线程获取了该锁,那么这个Job就会在这台机器上被执行,同时这个锁就会被这台机器占用。同时另外一台机器也会想要触发这个任务,但是锁已经被占用了,就只能等待,直到这个锁被释放。之后会看trigger状态,如果已经被执行了,则不会执行了。

简单地说,quartz的分布式调度策略是以数据库为边界资源的一种异步策略。各个调度器都遵守一个基于数据库锁的操作规则从而保证了操作的唯一性。同时多个节点的异步运行保证了服务的可靠。但这种策略有自己的局限性:集群特性对于高CPU使用率的任务效果很好,但是对于大量的短任务,各个节点都会抢占数据库锁,这样就出现大量的线程等待资源。这种情况随着节点的增加会越来越严重。

另外,quartz的分布式只是解决了高可用的问题,并没有解决任务分片的问题,还是会有单机处理的极限。

TBSchedule

TBSchedule是一款非常优秀的高性能分布式调度框架,广泛应用于阿里巴巴、淘宝、支付宝、京东、聚美、汽车之家、国美等很多互联网企业的流程调度系统。tbschedule在时间调度方面虽然没有quartz强大,但是它支持分片功能。和quartz不同的是,tbschedule使用ZooKeeper来实现任务调度的高可用和分片。

TBSchedule的分布式机制是通过灵活的Sharding方式实现的,分片的规则由客户端决定,比如可以按所有数据的ID按10取模分片、按月份分片等等。TBSchedule的宿主服务器可以进行动态扩容和资源回收,这个特点主要是因为它后端依赖的ZooKeeper,这里的ZooKeeper对于TBSchedule来说是一个NoSQL,用于存储策略、任务、心跳信息数据,它的数据结构类似文件系统的目录结构,它的节点有临时节点、持久节点之分。调度引擎启动后,随着业务量数据量的增多,当前Cluster可能不能满足目前的处理需求,那么就需要增加服务器数量,一个新的服务器上线后会在ZooKeeper中创建一个代表当前服务器的一个唯一性路径(临时节点),并且新上线的服务器会和ZooKeeper保持长连接,当通信断开后,节点会自动摘除。

TBSchedule会定时扫描当前服务器的数量,重新进行任务分配。TBSchedule不仅提供了服务端的高性能调度服务,还提供了一个scheduleConsole的war包,随着宿主应用的部署直接部署到服务器,可以通过web的方式对调度的任务、策略进行监控管理,以及实时更新调整。

elastic-job

Elastic-Job当当开源的分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务。一般我们只要使用Elastic-Job-Lite就好。

Elastic-Job-Lite并没有宿主程序,而是基于部署作业框架的程序在到达相应时间点时各自触发调度。它的开发也比较简单,引用Jar包实现一些方法即可,最后编译成Jar包运行。Elastic-Job-Lite的分布式部署全靠ZooKeeper来同步状态和原数据。实现高可用的任务只需将分片总数设置为1,并把开发的Jar包部署于多个服务器上执行,任务将会以1主N从的方式执行。一旦本次执行任务的服务器崩溃,其他执行任务的服务器将会在下次作业启动时选择一个替补执行。如果开启了失效转移,那么功能效果更好,可以保证在本次作业执行时崩溃,备机之一立即启动替补执行。

Elastic-Job-Lite的任务分片也是通过ZooKeeper来实现,Elastic-Job并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系。框架也预置了一些分片策略:平均分配算法策略,作业名哈希值奇偶数算法策略,轮转分片策略。同时也提供了自定义分片策略的接口。

另外Elastic-Job-Lite还提供了一个任务监控和管理界面:Elastic-Job-Lite-Console。它和Elastic-Job-Lite是两个完全不关联的应用程序,使用ZooKeeper来交换数据,管理人员可以通过这个界面查看、监控和管理Elastic-Job-Lite的任务,必要的时候还能手动触发任务。

elastic-job结合了quartz非常优秀的时间调度功能,并且利用ZooKeeper实现了灵活的分片策略。除此之外,还加入了大量实用的监控和管理功能,以及其开源社区活跃、文档齐全、代码优雅等优点,是分布式任务调度框架的推荐选择。

Saturn

Saturn是唯品会在github开源的一款分布式任务调度产品。它是基于当当elastic-job来开发的,其上完善了一些功能和添加了一些新的feature。目前在github上开源大半年,470个star。Saturn的任务可以用多种语言开发比如python、Go、Shell、Java、Php。其在唯品会内部已经发部署350+个节点,每天任务调度4000多万次。同时,管理和统计也是它的亮点。

4
laofo · #2 · 2018年11月20日

分布式调度在互联网企业中占据着十分重要的作用,尤其是电子商务领域,由于存在数据量大、高并发的特点,对数据处理的要求较高,既要保证高效性,也要保证准确性和安全性,相对比较耗时的业务逻辑往往会从中剥离开来进行异步处理。

接下来,推荐几款优秀和极具潜力的国产开源分布式任务调度系统,希望能对大家有所帮助。

1、opencron opencron 是一个功能完善且通用的开源定时任务调度系统,拥有先进可靠的自动化任务管理调度功能,提供可操作的 web 图形化管理满足多种场景下各种复杂的定时任务调度,同时集成了 linux 实时监控、webssh 等功能特性。

2、LTS LTS,light-task-scheduler,是一款分布式任务调度框架, 支持实时任务、定时任务和 Cron 任务。有较好的伸缩性和扩展性,提供对 Spring 的支持(包括 Xml 和注解),提供业务日志记录器。支持节点监控、任务执行监、JVM 监控,支持动态提交、更改、停止任务。

3、XXL-JOB XXL-JOB 是一个轻量级分布式任务调度框架,支持通过 Web 页面对任务进行 CRUD 操作,支持动态修改任务状态、暂停/恢复任务,以及终止运行中任务,支持在线配置调度任务入参和在线查看调度结果。

4、Elastic-Job Elastic-Job 是一个分布式调度解决方案,由两个相互独立的子项目 Elastic-Job-Lite 和 Elastic-Job-Cloud 组成。定位为轻量级无中心化解决方案,使用 jar 包的形式提供分布式任务的协调服务。支持分布式调度协调、弹性扩容缩容、失效转移、错过执行作业重触发、并行调度、自诊断和修复等等功能特性。

5、Uncode-Schedule Uncode-Schedule 是基于 ZooKeeper + Quartz / spring task 的分布式任务调度组件,确保每个任务在集群中不同节点上不重复的执行。支持动态添加和删除任务,支持添加 ip 黑名单,过滤不需要执行任务的节点。

6、Antares Antares 是一款基于 Quartz 机制的分布式任务调度管理平台,内部重写执行逻辑,一个任务仅会被服务器集群中的某个节点调度。用户可通过对任务预分片,有效提升任务执行效率;也可通过控制台 antares-tower 对任务进行基本操作,如触发,暂停,监控等。

4
laofo · #3 · 2018年11月20日

分布式定时任务框架---Uncode Schedule

作为一个支付公司的项目组,经常会有很多对账功能(签约对账、支付订单对账、记账对账),这些都是以定时任务的形式实现,组内经常需要维护一些定时任务,在使用过程中主要关注定时任务的稳定性、健壮性和可控性,分布式定时任务+任务监控基本满足使用需求。

定时任务的现状 就定时任务来说,首先是操作系统层面一直支持的功能,所以我们的各种对定时任务的实现手段才能得以发挥。由于操作系统和编程语言种类繁多,本文中将重点从linux操作系统、java语言以及java生态中开源框架来介绍定时任务。

1. linux系统级的定时任务执行器:crontab

这是一个系统级的定时器,具有灵活简单的特性,同时也是缺乏管理功能和分布式支持。一般的使用方法是,使用shell脚本调用业务实现jar包。

2. java语言中的定时器:java.util.Timer

这是一个java语言内置的定时器,这是所有基于java语言的开源框架实现的基础。其中,典型的任务调度方法:

public void schedule(TimerTask task, long delay); public void schedule(TimerTask task, Date time); public void schedule(TimerTask task, long delay, long period); public void schedule(TimerTask task, Date firstTime, long period); public void scheduleAtFixedRate(TimerTask task, long delay, long period); public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period);

3. java定时任务开源框架(常用)

3.1. Quartz(java定时任务的标准) 3.2. spring task 在spring中实现定时任务有两种方式,一是spring对quartz进行了封装,二是独立实现了定时任务的调度器称为spring task。其中spring task相对较为简单,cron表达式不支持L W;而quartz不但完整支持cron表达式,而且具有很多高级特性,如JDBCJobStore(作业仓库)、集群模式。

  1. 分布式定时任务开源框架
  2. 4.1. Elastic-Job(当当网)
  3. 4.2. light-task-scheduler
  4. 4.3. clover
  5. 4.4. TBSchedule(阿里)
  6. 4.5. niubi-job
  7. 4.6. Uncode-Schedule 基于java的分布式定时任务的开源框架还是很多的,这里没有一一列举,有些框架设计的非常完善复杂,可根据具体使用场景选择适当的框架,当某些功能不符合你的预期的时候,可以去修改一下源代码实现自己想要的功能,这是开源框架的好处。

根据我们所有定时任务的特点和实际运行需求,我选择了Uncode-Schedule框架,这个框架相对简单、灵活,并且修改源代码以满足特定需求相对容易。

分布式定时任务面临的问题 对于分布式应用来说,一致性始终是首要问题,另外就是对任务和执行任务的机器的管理问题。

  1. 一致性问题
  2. 1.1. 一个任务不能同时在多台机器上执行
  3. 1.2. 当某一台执行任务的机器宕机时,该机器上的任务自动重新分配至其他机器
  4. 1.3. 任务的均衡分配
  5. 1.4. 心跳检测

  6. 任务的管理和监控

  7. 2.1. 任务的动态添加和删除

  8. 2.2. 控制执行任务的机器

  9. 2.3. 随时手动执行任务

Uncode-Schedule开源框架分析 Uncode-Schedule是一个实现分布式定时任务的开源框架,java语言实现,本章将从上面的几个问题入手分析该框架的实现机制。

  1. 功能概述 Uncode-Schedule是基于zookeeper的分布式任务调度组件,非常小巧,使用简单,开发时只需要引入jar包,不需要单独部署服务端。而且定时任务的实现方式和原始的spring/quartz task保持一致,所以普通的定时任务改造成分布式很方便。
  • 1.1. 它能够确保所有任务在集群中不重复,不遗漏的执行。
  • 1.2. 单节点故障时,任务能够自动转移到其他节点继续执行。
  • 1.3. 支持动态添加和删除任务。
  • 1.4. 支持添加机器ip黑名单。
  • 1.5. 支持手动执行任务。
  1. 注意事项 在使用Uncode-Schedule框架开发定时任务时,需要注意几个问题:
  2. 2.1. 开发的定时任务在业务要保证幂等性。主要是为了解决单点故障时,任务转移重复执行带来的问题。
  3. 2.2. 任务节点启动时必须保证zookeeper可用。
  4. 2.3. 任务节点运行期zookeeper集群不可用时任务节点保持可用前状态运行,当zookeeper集群恢复后,任务正常运行。
  5. 2.4. 手动执行任务时,需要选择在哪台机器执行。

  6. 模块架构 3.1. Uncode-Schedule分布式定时任务的设计结构如下图:

zookeeper集群负责存储定时任务和机器的数据,起到存储数据和保持一致性的关键作用。在所有的执行任务的节点中有一个leader,它会负责任务的分配。任务的管理和监控平台可单独部署。 3.2. 每一个任务节点的内部结构如下图:

执行任务的节点上支持的任务类型包括spring的封装的quartz任务和spring task;另外该框架还自定义了一种任务Uncode Task,实际上是一种由zookeeper存储调度信息的任务,最终还是由spring的调度器ThreadPoolTaskScheduler控制的,不过这种任务是可动态添加和删除的。

  1. 使用方法 Uncode-Schedule框架的使用方法是很简单的,而且我也没有对原作者的使用方法做修改,所以具体使用方法可参考github上的README文档。

我根据对框架的功能完善,自己设计了一个任务的管理和监控平台。主要在其中添加了手动执行的功能,其他的监控功能会进一步完善。

作者:rabbitGYK 链接:https://www.jianshu.com/p/780235132d81

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册