分布式调度服务浅谈

JAVA开发领域,目前可以通过以下几种方式进行定时任务:

  • Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行。提供的功能比较单一,无法实现复杂的调度任务。
  • ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。
  • Spring Task:Spring提供的一个任务调度工具,支持注解和配置文件形式,支持Cron表达式,使用简单但功能强大。 

    ThreadPoolTaskScheduler

  • Quartz:一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度,就是配置稍显复杂。

在单机模式下,定时任务是没什么问题的。但当我们部署了多台服务,同时又每台服务又有定时任务时,若不进行合理的控制在同一时间,只有一个定时任务启动执行,这时,定时执行的结果就可能存在混乱和错误了。

这里简单的说说相关的解决方案吧,一家之言,希望大家能提出自己的见解,共同进步!

  • 剥离所有定时任务到一个工程:此方案是最简单的,在定时任务相对较小,并发任务不多时,可以使用此方案。简单也容易维护。当定时任务牵扯的业务越来越多,越来越杂时,维护量就成本增加了,工程会越来越臃肿,此方案就不实用了。
  • 利用Quartz集群方案:本身Quartz是支持通过数据库实现集群的,以下是其集群架构图:

集群架构图集群架构图

其实现原理也相对简单:通过数据库实现任务的持久化,保存定时任务的相关配置信息,以保证下次系统启动时,定时任务能自动启动。同时,通过数据库行锁(for update)机制,控制一个任务只能被一个实例运行,只有获取锁的实例才能运行任务,其他的只能等待,直到锁被释放。这种方式有些弊端,就是依赖了数据库,同时也需要保证各服务器之间的时间需要同步,不然也是会混乱的。

现在Quartz也有基于Redis的集群方案,有兴趣的可以搜索下。

  • 分布式锁:可通过使用Redis或者ZooKeeper实现一个分布式锁的机制,使得只有获取到锁的实例方能运行定时任务,避免任务重复执行。可查看下开源的基于Redis实现的分布式锁项目:redisson。github地址:https://github.com/redisson/redisson有兴趣的同学可以了解下。
  • 统一调度中心:

可构建一个纯粹的定时服务,只有定时器相关配置,比如定时时间定时调度的api接口或者http服务,甚至是统一注册中心下的服务类,如dubbo服务等。而具体的任务执行操作都在各自业务方系统中,调度中心只负责接口的调用,具体实现还是在业务方。这种方案相对来说比较通用,实现起来也简单。就是需要业务方进行约定编程,或者对外提供一个api接口。

当然,为了实现定时任务的自动发现和注册功能,还是需要规范一套规则来实现自动注册功能。简单来说,以Dubbo服务为例,可以定义一个定时任务接口类,调度中心只需要获取所有实现此接口的服务,同时通过服务的相关配置(调度时间、失败策略等)进行相关定时操作。或者编写一个服务注册与发现的客户端,通过Spring获取到实现此接口的所有实现类,上送到调度中心。

而且,统一调度中心,还可以对所有的定时任务的调度情况进行有效监控,日志记录等,也可以约定接口,让定时任务回传定时结果,做到全局把控的目的。

以上就是对分布式调度的一点理解,有错误的地方还望指正,有更好的方案也希望能分享下。

参考资料

  1. https://www.cnblogs.com/yank/p/3955322.html
  2. https://blog.csdn.net/tsyj810883979/article/details/8481621
  3. https://www.cnblogs.com/javahr/p/8318728.html
  4. http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start.html
  5. https://spring.io/guides/gs/scheduling-tasks/

总结

本章节主要是讲解了通过不同的方式实现定时任务。对于定时任务而言,本身是门大学问,一俩篇文章是讲不完的。像SpringTaskQuartz都是很强大的调度器,两者很相似,像如何实现任务的动态修改调度周期,动态停止相关任务,调度任务的监控,这些本文章都没有涉及。还希望有相关需求的同学自行搜索相关资料了。

猜你喜欢

转载自www.cnblogs.com/miracle77hp/p/9915105.html