5

拆解一下任务队列、消息队列、任务调度系统 - 阿丸

 1 year ago
source link: https://www.cnblogs.com/awan-note/p/16718373.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近调研了下任务调度系统中间件,包括xxl-job、elastic-job等,发现跟任务队列有一些类似的能力,比如通过API(事件)触发任务执行。

随即想到,能否用任务调度系统覆盖任务队列的场景呢?

另外,一直以来,很多同学也经常会产生困惑,任务队列和消息队列究竟有什么区别?

因此,本文通过多个维度来进行拆解,试着分析 任务队列、消息队列、任务调度系统 这三类中间件 究竟有哪些不同,究竟谁更适合什么场景。

  • 从基本功能说起
  • 对比系统角色

1、从基本功能说起

什么是消息队列?

消息队列大家基本是耳熟能详,不管是经典的kafka、rocketmq,还是新兴的pulsar。
虽然它们在架构上都有所区别,但是本质上都是一种 应用 对 应用的 「通信方式」。
应用程序通过读写出入队列的「消息」来通信,而无需点对点直接连接应用。主要解决应用耦合、异步消息、流量削锋等问题,用来实现高性能,高可用,可伸缩和最终一致性架构。

什么是任务调度系统?

任务调度系统也是大家比较熟悉的,从quartz到xxl-job,到elastic-job。
主要解决的问题是,解决分布式场景下的 离线任务、定时任务 的调度问题,具备高可用、可视化、可运维、低延时等能力。
一些复杂场景,可能还需要进行任务编排(DAG)执行。

什么是任务队列?

任务队列可能听过的人会少一点,没有特别出名的java开源框架,相对活跃一点的包括Celery、Resque等。
它解决的问题是比较经典的,在线业务如何 实时 处理 长耗时 任务。
任务队列通过封装 异步任务发送、任务处理、任务状态存储、异常处理 等环节,提供了一套完整的处理长耗时任务的编程框架,实现了 隔离性、容错性 的应用架构。

2、对比系统角色

2.1 任务队列 VS 消息队列

认识一个系统,除了通过文字简单了解基本功能外,最直接的方式是看看整体系统架构的角色。

先看下消息队列的系统角色。

10b512b7b450472885a62f3f5be0eb32~noop.image?_iz=58558&from=article.pc_detail&x-expires=1664419077&x-signature=JkHIgpVAZ6PXzE%2FtP%2FADySs5X44%3D

主要包括:

  • 生产者 Producer
    发布消息的角色。Producer通过 MQ 的负载均衡模块选择相应的 Broker 集群队列进行消息投递,投递的过程支持快速失败和重试。
  • 消费者 Consumer
    消息消费的角色。
  • 代理服务器 Broker
    Broker主要负责消息的存储、投递和查询以及服务高可用保证。

然后,我们看看任务队列的系统角色包括哪些。

ffd5e0f13eac46c699ae50b7cb1e5efd~noop.image?_iz=58558&from=article.pc_detail&x-expires=1664419077&x-signature=qtH0kc8xP9wxAUFRgo3A0IvoC%2FQ%3D

主要包括4类角色:

  • 任务生产者 Producer
    发布任务的角色。Producer通过 MQ 的负载均衡模块选择相应的 Broker 集群队列进行消息投递,投递的过程支持快速失败和重试。
  • 消费者 Consumer
    消费任务的角色。
  • 队列queue
    Broker主要负责任务的存储、投递和查询以及服务高可用保证。
  • 任务状态持久化storage
    storage主要负责任务的状态持久化、查询等能力。可以选择独立的DB,也可以直接复用queue。

通过系统角色对比,我们可以看到,消息队列是任务队列的其中一个角色,任务队列中queue的选型可以是消息队列kafka、rocketmq,甚至可以是能提供类似能力的redis。

除了queue之外,任务队列的一个显著特点是,一般还需要一个storage系统角色来持久化任务的状态。

2.2 任务队列 VS 任务调度系统

任务调度系统比较有代表性的开源产品包括Quartz、Elastic-job、XXL-JOB。

我们以XXL-JOB为例,来看下系统角色。

c2fdabfd35c3440eafeb88444690fe6b~noop.image?_iz=58558&from=article.pc_detail&x-expires=1664419077&x-signature=q7FmFfa5HV1FpC2rNVQAmNTZvoo%3D

包括2个角色:

  • 调度模块(调度中心):
    负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块;
  • 执行模块(执行器):
    负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效。接收“调度中心”的执行请求、终止请求和日志请求等。

从这里能看出,XXL-JOB是一个典型的「中心化」系统,任务都是根据预设规则从 调度中心 发起,然后由执行器来执行。当然,Elastic-job中的ElasticJob-lite也有「去中心化」方案,但是从逻辑模型的角度来说,仍然是一个需要调度中心进行调度的。

而任务队列的整个模型就是一个「去中心化」、「应用 对 应用 生产消费」系统,任务由producer发起,由consumer消费。

3、本质区别

结合前面的基本功能和系统角色,我们可以更好地体会三个中间件的本质区别。

消息队列本质上都是一种 应用 对 应用 的 「通信方式」,主要解决应用耦合、异步消息、流量削锋等问题。

任务队列本质上是一种封装好的 应用 对 应用 异步任务 「编程框架」,它封装了对异步任务的如何重试、如何消费、如何获取任务结果、如何监控任务的运行情况 等等问题,让业务开发只关心业务逻辑。
同时,任务队列也是一种典型的 「架构风格」,这个编程框架 指导 业务开发对 长耗时 任务从普通 在线业务 的服务中拆分出来,避免影响在线业务的稳定性。因此,任务队列的主要应用场景也是 在线业务。

任务调度系统设计之初就是为了解决分布式场景下的 离线任务、定时任务 的调度问题,它的设计目标是 轻量级、可视化、易扩展。
因此,它的设计没有 应用 对 应用 的生产消费概念,也不具备对高流量的承受能力(削峰)。
当然,它跟任务队列最大的区别,它不具备将 长耗时 任务从普通 在线业务 的服务中拆分出来的这种架构思想指导(大部分定时任务都是在夜间执行)。

任务调度系统的定位还是应用于 轻量级、离线业务 场景最为合适。

回过头看看一开始的两个问题。

1)能否用任务调度系统覆盖任务队列的场景呢?

不能。任务调度系统适用于 轻量级、离线业务 场景下的 定时任务 和 离线任务,使用调度/执行模式,不具备承接在线业务高流量的能力。而任务队列适用于 在线业务 场景下的 长耗时任务,使用 生产消费模式,具备对高流量的承受能力(削峰)。

2)任务队列和消息队列究竟有什么区别?

任务队列是一个封装好的 异步任务编程框架,也是一种 长耗时任务 与 普通在线业务 拆分的架构思想。消息队列只是任务队列中的一个系统角色。

总结一下,其实三者的差异还是非常大的。

1955986-20220922103843636-1855151021.png

希望能够抛砖引玉,提供一些启发和思考。如果你有其他补充和建议,欢迎留言讨论。

都看到最后了,原创不易,点个关注,点个赞吧~
文章持续更新,可以微信搜索「阿丸笔记 」第一时间阅读,回复【笔记】获取Canal、MySQL、HBase、JAVA实战笔记,回复【资料】获取一线大厂面试资料。
知识碎片重新梳理,构建Java知识图谱:github.com/saigu/JavaK…(历史文章查阅非常方便)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK