写的比较好的博客:https://www.cnblogs.com/throwable/p/11955154.html
本文只做分析不做实现
项目上很多时候会使用定时任务,对应有很多分布式定时框架,比较优秀的例如elastic-job、xxl-job,两者都能实现分布式任务调度;但两者有差异性;而项目上有动态添加定时任务、延迟定时任务的需求,这两款框架就不是太满足了,下面分析下两个框架的差异性、不适合动态添加定时任务和延时定时任务的原因
elastic-job
定位为轻量级无中心化解决方案,使用 jar 的形式提供分布式任务的协调服务。分片、失效转移等功能由zookeeper进行;
xxl-job
定位为轻量级中心化管理解决方案,包含“调度中心”和“执行器(自己的项目)”两部分组成,分片、失效转移等由“调度中心”+“DB锁”保证;底层是Quartz;
配合elastic-job-console服务,能可视化查看zk中的定时任务:
docker run -d -p 8899:8899 -e ROOT_PASSWD=root -e GUEST_PASSWD=root ypzhuang/elastic-job-console
动态添加任务、延迟任务的不支持说明
elastic-job
elastic-job没有提供动态增删服务的sdk,或许你觉得可以通过代码`new JobBootstrap`接口的实现,变相实现任务的新增,你以这种方式实现了,并且本地运行定时任务正常执行了;但实际上有个大坑,在分布式多实例部署的场景下,你通过这种方式添加一个任务后,实际上只是将接受请求的这个实例和添加的任务绑定到了zookeeper上,其他实例并没有新增的定时器的信息,那么当该节点宕机,该任务肯定丢失;
针对上面的问题,你可能会想,那可以让新任务在每台实例都进行zk注册不就行了?是的,可以实现让现存的每个实例都添加上新任务和zk进行绑定;那要是所有实例都宕机了,重启的新实例里又都不包含该新任务,那这个任务就丢失了;
所以elastic-job的使用场景应该是固定执行周期的定时任务,写在代码层面;保证每次新启动的实例都能注册所有任务到zk,达到分布式的效果。
结论:不适合做动态添加、延迟任务的场景解决方案
xxl-job
xxl-job底层使用的Quartz,本身也支持动态添加定时任务的,但官方未提供代码级别操作的sdk(往往都是通过代码触发添加任务、延时任务),所以需要自己实现,通过调用web端的接口操作api接口,进行变相动态添加定时任务;但至少是支持动态操作定时任务的;
但对于延时任务,通过设置固定cron执行时间,变相实现延迟一次性任务;
结论:能支持动态添加定时任务、实现延迟任务,但需要自己实现操作sdk
延迟队列
对于一次性任务、延迟任务,可以通过消息队列来实现
一次性任务:项目直接消息订阅消费就行;
延迟任务:利用队列的延迟功能,实现以延迟消费来达到延迟任务的效果;但mq需要遵循ttl规则,延迟时间不能自定义;
结论:支持
结论
对于一次性立马执行的任务,直接走自己项目api接口;
对于只有定时定点执行的场景,elastic-job最优,去中心化;
对于有定时定点任务、延迟任务和动态操作定时任务都有的场景,建议使用xxl-job;
对于单独延迟任务建议使用mq延迟队列;