最近调研了任务调度系统的中间件,包括xxl-job、elastic-job等,发现它和任务队列有一些类似的能力,比如通过API(事件)触发任务执行。然后我想,任务调度系统是否可以覆盖任务队列场景?另外,很多同学一直都是一头雾水。任务队列和消息队列有什么区别?因此,本文通过多维度拆解,试图分析任务队列、消息队列、任务调度系统这三类中间件的区别,以及哪一种更适用于哪些场景。从基本功能出发,比较系统角色的本质区别。小结1、从基本功能来说,什么是消息队列?消息队列基本上大家都不陌生,不管是经典的kafka、rocketmq,还是新兴的pulsar。虽然它们在架构上有所不同,但本质上都是一种应用程序到应用程序的“通信方式”。应用程序通过在队列中读取和写入“消息”来进行通信,而不是直接点对点连接应用程序。主要解决应用耦合、异步消息、流量削峰等问题,用于实现高性能、高可用、可扩展、最终一致性的架构。什么是任务调度系统?任务调度系统也是大家耳熟能详的,从quartz到xxl-job再到elastic-job。主要解决的问题是解决分布式场景下离线任务和定时任务的调度问题,具备高可用、可视化、可运维、低延迟的能力。一些复杂的场景可能还需要任务安排(DAG)执行。什么是任务队列?听说过任务队列的人可能比较少。没有特别出名的java开源框架,比较活跃的有Celery、Resque等,它解决的问题比较经典,在线业务如何实时处理长时间耗时的任务。任务队列通过封装异步任务发送、任务处理、任务状态存储、异常处理等环节,为处理长时间耗时任务提供了完整的编程框架,实现了隔离和容错的应用架构。2.系统角色比较(1)任务队列VS消息队列了解一个系统,除了简单的通过文字了解基本功能外,最直接的方式就是看整个系统架构中的角色。首先看消息队列的系统作用。主要包括:ProducerProducer角色,负责发布消息。Producer通过MQ负载均衡模块选择对应的Broker集群队列进行消息投递,投递过程支持快速失败和重试。ConsumerConsumer消息消费的作用。代理服务器BrokerBroker主要负责消息的存储、传递和查询以及服务高可用性的保证。然后,我们看看任务队列包括哪些系统角色。主要包括4类角色:任务生产者Producer是发布任务的角色。Producer通过MQ负载均衡模块选择对应的Broker集群队列进行消息投递,投递过程支持快速失败和重试。ConsumerConsumer消费任务的角色。队列queueBroker主要负责任务的存储、传递和查询以及服务的高可用保障。任务状态持久化存储storage主要负责任务状态持久化、查询等能力。可以选择独立的DB,也可以直接复用队列。通过系统角色的对比,我们可以看出消息队列是任务队列的角色之一。任务队列中的队列类型可以是消息队列kafka、rocketmq,甚至可以提供类似能力的redis。除了队列之外,任务队列的一个显着特点是它一般需要一个存储系统角色来持久化任务的状态。(2)任务队列VS任务调度系统任务调度系统的代表性开源产品有Quartz、Elastic-job、XXL-JOB。下面以XXL-JOB为例,看看系统角色。包括2个角色:调度模块(调度中心):负责管理调度信息,根据调度配置发送调度请求,不负责业务代码。调度系统与任务解耦,提高了系统的可用性和稳定性,同时调度系统的性能不再受限于任务模块。执行模块(executor):负责接收调度请求,执行任务逻辑。任务模块专注于任务执行等操作,让开发和维护更简单、更高效。接收来自“调度中心”的执行请求、终止请求、日志请求等。从这里可以看出,XXL-JOB是一个典型的“中心化”系统,任务由调度中心按照预设规则发起,然后由执行者执行。当然,Elastic-job中的ElasticJob-lite也有“去中心化”的解决方案,但是从逻辑模型来看,还是需要一个调度中心来进行调度。任务队列的整个模型是一个“去中心化”、“应用到应用生产消费”的系统。任务由生产者发起,由消费者消费。3.本质区别结合前面的基本功能和系统角色,我们可以更好的理解三个中间件的本质区别。消息队列本质上是一种应用程序到应用程序的“通信方式”,主要解决应用程序耦合、异步消息、流量切割等问题。任务队列本质上是一个封装好的应用到应用的异步任务“编程框架”,封装了如何重试、如何消费、如何获取任务结果、如何监控异步任务的运行状态等,让业务开发只关心业务逻辑。同时任务队列也是典型的“架构风格”。该编程框架引导业务开发将耗时较长的任务从普通的在线业务服务中分离出来,避免影响在线业务的稳定性。所以任务队列的主要应用场景也是线上业务。任务调度系统最初是为了解决分布式场景下离线任务和定时任务的调度问题而设计的。它的设计目标是轻量级、可视化、易扩展。因此,它没有设计应用到应用生产消费的概念,也不具备承受高流量(削峰)的能力。当然,任务调度系统与任务队列最大的不同在于,它没有将耗时较长的任务从普通在线业务服务中分离出来的架构指导(调度任务大多在夜间执行)。任务调度系统的定位还是最适合轻量级、离线的业务场景。4.总结回过头来看一下开头的两道题。(1)任务调度系统能否覆盖任务队列场景?不能。任务调度系统适用于轻量级、离线业务场景下的定时任务和离线任务。采用调度/执行模式,不具备承接大流量在线业务的能力。任务队列适用于线上业务场景下的耗时较长的任务,采用生产消费模式,具有承受高流量(削峰)的能力。也引导业务开发将耗时长的任务从普通的在线业务服务中拆分出来。(2)任务队列和消息队列有什么区别?任务队列是一个封装好的异步任务编程框架,也是一种将耗时较长的任务从普通在线服务中拆分出来的架构思想。消息队列只是任务队列中的一个系统角色。综上所述,其实三者的区别还是很大的。
