拆解一下消息队列、任务队列、任务调度系统
最近调研了下任务调度系统中间件,包括 xxl-job、elastic-job 等,发现跟任务队列有一些类似的能力,比如通过 API(事件)触发任务执行。
随即想到,能否用任务调度系统覆盖任务队列的场景呢?
另外,一直以来,很多同学也经常会产生困惑,任务队列和消息队列究竟有什么区别?
因此,本文通过多个维度来进行拆解,试着分析 任务队列、消息队列、任务调度系统 这三类中间件 究竟有哪些不同,究竟谁更适合什么场景。
从基本功能说起
对比系统角色
本质区别
总结
1、从基本功能说起
什么是消息队列?
消息队列大家基本是耳熟能详,不管是经典的 kafka、rocketmq,还是新兴的 pulsar。虽然它们在架构上都有所区别,但是本质上都是一种 应用 对 应用的 「通信方式」。
应用程序通过读写出入队列的「消息」来通信,而无需点对点直接连接应用。主要解决应用耦合、异步消息、流量削峰等问题,用来实现高性能,高可用,可伸缩和最终一致性架构。
什么是任务调度系统?
任务调度系统也是大家比较熟悉的,从 quartz 到 xxl-job,到 elastic-job。主要解决的问题是,解决分布式场景下的 离线任务、定时任务 的调度问题,具备高可用、可视化、可运维、低延时等能力。
一些复杂场景,可能还需要进行任务编排(DAG)执行。
什么是任务队列?
任务队列可能听过的人会少一点,没有特别出名的 java 开源框架,相对活跃一点的包括 Celery、Resque 等。
它解决的问题是比较经典的,在线业务如何 实时 处理 长耗时 任务。
任务队列通过封装 异步任务发送、任务处理、任务状态存储、异常处理 等环节,提供了一套完整的处理长耗时任务的编程框架,实现了 隔离性、容错性 的应用架构。
2、对比系统角色
2.1 任务队列 VS 消息队列
认识一个系统,除了通过文字简单了解基本功能外,最直接的方式是看看整体系统架构的角色。
先看下消息队列的系统角色。
主要包括:
生产者 Producer 发布消息的角色。Producer 通过 MQ 的负载均衡模块选择相应的 Broker 集群队列进行消息投递,投递的过程支持快速失败和重试。
消费者 Consumer 消息消费的角色。
代理服务器 BrokerBroker 主要负责消息的存储、投递和查询以及服务高可用保证。
然后,我们看看任务队列的系统角色包括哪些。
主要包括 4 类角色:
任务生产者 Producer 发布任务的角色。Producer 通过 MQ 的负载均衡模块选择相应的 Broker 集群队列进行消息投递,投递的过程支持快速失败和重试。
消费者 Consumer 消费任务的角色。
队列 queueBroker 主要负责任务的存储、投递和查询以及服务高可用保证。
任务状态持久化 storagestorage 主要负责任务的状态持久化、查询等能力。可以选择独立的 DB,也可以直接复用 queue。
通过系统角色对比,我们可以看到,消息队列是任务队列的其中一个角色,任务队列中 queue 的选型可以是消息队列 kafka、rocketmq,甚至可以是能提供类似能力的 redis。
除了 queue 之外,任务队列的一个显著特点是,一般还需要一个 storage 系统角色来持久化任务的状态。
2.2 任务队列 VS 任务调度系统
任务调度系统比较有代表性的开源产品包括 Quartz、Elastic-job、XXL-JOB。
我们以 XXL-JOB 为例,来看下系统角色。
包括 2 个角色:
调度模块(调度中心):负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块;
执行模块(执行器):负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效。接收“调度中心”的执行请求、终止请求和日志请求等。
从这里能看出,XXL-JOB 是一个典型的「中心化」系统,任务都是根据预设规则从 调度中心 发起,然后由执行器来执行。当然,Elastic-job 中的 ElasticJob-lite 也有「去中心化」方案,但是从逻辑模型的角度来说,仍然是一个需要调度中心进行调度的。
而任务队列的整个模型就是一个「去中心化」、「应用 对 应用 生产消费」系统,任务由 producer 发起,由 consumer 消费。
3、本质区别
结合前面的基本功能和系统角色,我们可以更好地体会三个中间件的本质区别。
消息队列 本质上都是一种 应用 对 应用 的 「通信方式」,主要解决应用耦合、异步消息、流量削锋等问题。
任务队列 本质上是一种封装好的 应用 对 应用 异步任务 「编程框架」,它封装了对异步任务的如何重试、如何消费、如何获取任务结果、如何监控任务的运行情况 等等问题,让业务开发只关心业务逻辑。
同时,任务队列也是一种典型的 「架构风格」,这个编程框架 指导 业务开发对 长耗时 任务从普通 在线业务 的服务中拆分出来,避免影响在线业务的稳定性。因此,任务队列的主要应用场景也是 在线业务。
任务调度系统 设计之初就是为了解决分布式场景下的 离线任务、定时任务 的调度问题,它的设计目标是 轻量级、可视化、易扩展。
因此,它的设计没有 应用 对 应用 的生产消费概念,也不具备对高流量的承受能力(削峰)。
当然,任务调度系统 跟 任务队列 最大的区别,它不具备将 长耗时 任务从普通 在线业务 的服务中拆分出来的这种架构思想指导(大部分定时任务都是在夜间执行)。
任务调度系统的定位还是应用于 轻量级、离线业务 场景最为合适。
4、总结
回过头看看一开始的两个问题。
1)能否用任务调度系统覆盖任务队列的场景呢?
不能。任务调度系统适用于 轻量级、离线业务 场景下的 定时任务 和 离线任务,使用调度/执行模式,不具备承接在线业务高流量的能力。
而任务队列适用于 在线业务 场景下的 长耗时任务,使用 生产消费模式,具备对高流量的承受能力(削峰)。并且指导业务开发将 长耗时 任务从普通 在线业务 的服务中拆分出来的架构思想。
2)任务队列和消息队列究竟有什么区别?
任务队列是一个封装好的 异步任务编程框架,也是一种 长耗时任务 与 普通在线业务 拆分的架构思想。消息队列只是任务队列中的一个系统角色。
总结一下,其实三者的差异还是非常大的。
原文:https://www.cnblogs.com/awan-note/p/16718373.html
如果感觉本文对你有帮助,点赞关注支持一下,想要了解更多 Java 后端,大数据,算法领域最新资讯可以关注我公众号【架构师老毕】私信 666 还可获取更多 Java 后端,大数据,算法 PDF+大厂最新面试题整理+视频精讲
评论