集群环境下定时任务调度问题与方案探讨

简介:

摘要

从改造工作量、可用性、负载均衡、资源利用等方面,简单介绍了几种集群环境下定时任务调度的方案。


问题:从单机扩展到集群

单机环境的定时任务很简单。无论是用比较原始的Timer,还是用自成体系的quartz、spring-scheduler,都可以轻松写意的实现功能。


但是,当应用水平扩展到集群环境下时, 定时任务会出现重复调度、重复执行,可能带来资源浪费、数据错误等问题。


方案一:不做改造,直接扩展

对有些定时任务来说,重复调度、重复执行并不构成大问题。例如删除过期数据任务、数据监控任务等,除了会造成一定的资源浪费之外,其实无伤大雅。


从功能上来说,只有严格幂等的任务才可以直接扩展。性能方面来说,这个方案适合对网络、内存等资源压力小的定时任务。另外,如果定时任务需要处理的资源本身不在集群服务之间共享,那么必然要使用这个方案:例如检查服务本地缓存数据过期情况的定时任务就属于这种情况。


工作量

由于不需要对单机环境的定时任务进行改造,因此这个方案的改造工作量是非常小的。

只不过,在开发单机环境的定时任务时就要重点考虑如何保证任务的幂等性,这可能是一项额外的工作。


可用性

高可用性是没的说的。集群中的每台服务都有一套独立、完整的任务调度、执行功能,只要有一台服务存活,就可以保证任务完整执行。


负载均衡

在负载均衡方面,这个方案是最差的:它实际上是“负载翻倍”。每台服务器需要都承担一个任务的全部压力;对网络、数据库等共享资源来说,压力更是N倍增长。所以前面才会提到:这个方案适合对网络、内存等资源性能压力小的任务。


资源利用

如果说这个方案在负载均衡方面得分为0的话,资源利用上就是负分。


方案二:多处调度、一处执行

方案一可以说是“多处调度、多处执行”,方案二则是“多处调度、一处执行”。这种方案的基本思路是:虽然多台服务同时运行调度机制,但通过某种机制来保证只有一台服务能最终执行任务。这种机制可以是quartz的集群调度功能,也可以是zookeeper的多活选主机制,还可以是分布式锁机制。

由于这个方案保证“一处执行”,因此它并不要求定时任务具有幂等性,适用性更广。


工作量

整体而言,这个方案只改造定时任务的调度机制,不涉及执行机制。而对于定时任务来说,调度机制比较统一,执行功能则变化更多。因此,尽管工作量与实际使用的机制有关,但这个方案并不算太麻烦。

以我此前参与过的一个的定时任务多活改造为例,从使用spring-scheduler的单机调度功能改造为quartz的集群调度功能,工作量、工期、风险等都在可控范围之内。


可用性

只要实现了集群部署,可用性一定是上了一个台阶的。


不过,一般来说,这个方案总会引入一个第三方机制来决定由哪台服务来执行任务(quartz使用数据库、zookeeper使用ZK服务等)。这个第三方机制,无论多么可靠、可用,多多少少还是会引入一些不可用风险。例如使用zookeeper选主机制,如果因为网络、机房等缘故导致选主失败,进而使得“多处调度”之后“处执行”,也会使得定时任务引发问题。


另外,“一处执行”也会增加可用性风险。如果某个定时任务由于某台服务自身的问题执行失败,我们需要额外的机制(如spring-batch的restart机制)来处理。


只不过这种风险概率非常低,大部分时候我们都直接忽略掉了。


负载均衡

负载均衡是这个方案的一个“黑点”。由于只能保证“一处执行”,同一个定时任务的所有压力都在这一台服务上;其它服务即使空闲、可用,也只能袖手旁观。


但是,这个方案可以把不同的定时任务“负载均衡”到不同的服务上执行,从而避免所有任务都在同一台服务上执行的极端情况。


资源利用

简单分析一下,我们可以知道,当不同任务的资源占用(内存/cpu/网络等资源的使用量,以及资源占用时间)比较平均时,这个方案对资源的利用率比较高。但是如果各任务间相差较大(如任务A执行时间1小时,任务B执行时间2分钟),就会造成一定的资源浪费。


方案三:一处调度、一处执行

方案二的调度机制会在多台服务上同时运行,因此也可以称之为“分布调度,一处运行”。方案三则将调度机制集中到一套调度服务上,由调服服务进行“集中调度”,然后再由应用服务“一处执行”。

关于这种方案已有不少实现,如ELASTIC-JOB等等。不过其中有一些方案,实际上是“多处调度、一处执行”。按下不表。


工作量

这种方案的改造量会比较大。


虽然定时任务可以分为调度和执行两部分,但大部分情况下,这两部分代码结合得都比较紧密。方案三实际上是将“调度”功能与“执行”工作剥离开(有时甚至会把二者部署为不同的服务)。拆分原有代码的工作量可见一斑。


可用性

参见方案二。


负载均衡

参见方案二。


资源利用

参见方案二。


方案四:一处调度、多处执行

方案四是方案三的一个扩展。在方案三把“调度”与“执行”拆开以后, 这个方案开始把触角伸向了“执行”功能,并将“执行”功能拆分成“读取-处理”两部分(是的,参考了spring-batch的reader-processer-writer模式)。


在方案四中,“调度”功能只是调度“读取”功能,即在指定的时间点读取出所有需要处理的数据。读出数据之后,利用消息队列等机制,将数据分给多个“处理”服务。


在我们系统中就有类似机制。某个任务使用的是quartz的集群部署方案来保证“一处调度”;任务运行时,会先读取出当天需要处理的数据,并将其数据发送到ActiveMQ的队列中,交由相关功能来处理。


工作量

这个方案不仅要把“调度”功能单独拆出来,还要把“执行”功能再次拆分为“读取”和“处理”,并分别进行部署。其中的难度可想而知。


可用性

相比方案二和方案三,这个方案引入了更多的外部依赖。所以至少理论上,它的可用性(可靠性?)是最低的。


负载均衡

这个方案的负载均衡能力来自于将“读取”到的数据分发给“处理”服务时所使用的机制。如果使用消息队列(如ActiveMQ),则它也能将任务负载均衡地分发给集群中的多台服务。


资源利用

对定时任务来说,这个方案可以相当充分地利用系统资源。

但是,对消息队列、网络等“额外”资源来说,这个方案在很大程度上会加重它们的负担。


方案五:多处调度、多处执行

虽然方案一也是“多处调度、多处执行”,但方案五跟它是有差别的。


方案五将“执行”机制进一步拆分为“读取”、“判断”、“执行”三部分。首先读取定时任务所需处理的数据全集;然后利用分布式锁等机制,逐个判断读取到的某条数据是否应当由当前服务执行;只有通过了判断的数据才会进入到执行阶段。


相比“执行”,方案五对“调度”机制基本没做处理。单机环境下怎么调度,集群环境下仍然怎么调度。


工作量

方案五不变更“调度”机制,改造工作量全在“执行”机制上。而对执行机制的改造也只是“插入”一个步骤,而并不修改、拆分基本流程。这种改造工作相对来说还是比较轻松的。


可用性

同样实现了集群部署,方案五的可用性是有保证的。由于调度、执行都在多台服务上同时运行,无论哪一台服务出现问题,其它服务仍能正常的调度和执行任务,受到影响的可能只是那台服务上正在处理的一条(一批)数据。


并且,它对外部环境的依赖也比较小(基本也就引入了一个分布式锁),相对其它方案来说,风险也更低。


负载均衡

懒得敲字了。


资源利用

方案五相当于把一个任务所需处理的数据平均分成N份,均匀的交给集群中的服务来处理。因此,它对资源的利用率可以说是最高的。


不过,在读取数据阶段,由于要读取一个“全集”,可能会带来一些资源压力。



本文转自 斯然在天边 51CTO博客,原文链接:http://blog.51cto.com/winters1224/1963788,如需转载请自行联系原作者

相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
3月前
|
中间件 测试技术 调度
设计一个简易版本的分布式任务调度系统
设计一个简易版本的分布式任务调度系统
83 0
|
5月前
|
NoSQL Java 数据库连接
分布式系列教程(46) -分布式定时任务锁(ShedLock实现)
分布式系列教程(46) -分布式定时任务锁(ShedLock实现)
123 0
|
6月前
|
监控 Dubbo Java
分布式定时任务调度框架实践
分布式定时任务调度框架实践
579 1
|
10月前
|
消息中间件 开发框架 NoSQL
【工作中问题解决实践 二】分布式消息并发同步处理方案
【工作中问题解决实践 二】分布式消息并发同步处理方案
85 0
|
11月前
|
存储 缓存 固态存储
白话Elasticsearch63-生产集群部署之硬件配置、jvm以及集群规划建议
白话Elasticsearch63-生产集群部署之硬件配置、jvm以及集群规划建议
126 0
|
12月前
|
消息中间件 监控 算法
分布式定时任务框架选型
分布式定时任务框架选型
|
Kubernetes API 调度
k8s集群调度方案
k8s集群调度方案
429 1
k8s集群调度方案
|
存储 负载均衡 Java
多节点服务器定时任务重复处理的问题
多节点服务器定时任务重复处理的问题
298 0
|
消息中间件 负载均衡 Dubbo
|
SQL 缓存 网络协议
深入理解MySQL主从复制原理以及集群部署流程
主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。
442 0

热门文章

最新文章