数字化时代的到来,让我们面临越来越多的批量数据定时集中处理的业务场景,如运营商月底批量结算话费,银行批量代发工资,云计算提供商批量结算资源费用等等。为了保障日间实时业务资源充足,这些批处理任务多在夜间系统空闲时定时启动处理,并要求在白天实时业务开始前结束,因此对批处理系统的性能要求很高。随着业务的不断扩大,需要处理的数据量级不断上升,单机任务系统的处理能力往往无法承担,分布式定时任务处理系统解决了这一难题,它通过分片处理、分布式调度协调来提高处理效率,并支持弹性扩容缩容。当前比较流行的分布式任务调度系统有当当公司开源的elastic-job和大众点评公司开源的xxl-job。这些分布式任务调度系统能够满足绝大多数数据批处理业务的需求,但是由于系统只提供执行器数量级别的任务切分,任务并发执行的能力取决于执行器集群中节点的数量,对于单个执行器并没有提供并发框架,所以并发能力有限,在处理超大数量级的作业时仍有性能瓶颈。以xxl-job为例, XXL-JOB 的官方说明中使用“分片广播”路由策略时,可以看到业务逻辑中可以根据系统传入的分片参数(shardingVO.getIndex(), shardingVO.getTotal())来获取数据,但是对于数据的处理系统没有提供并发机制。如果希望执行器节点内任务分片也并行处理,需要用户在任务处理类中进行多线程开发,但这样会增加用户的代码开发量和开发难度,并且自行实现的并发功能不具备通用性,无法被复用。
本解决方案通过引入消息中间件和一个二次分片参数解决上述问题,执行器承担任务二次分解分发和任务执行,进一步提升分布式任务系统的并发能力。在任务分解分发类中,根据系统传递的分片参数,获得本执行器要处理的数据,将数据按照调度中心配置的二次分片参数拆解为小的数据分片,并发送到该任务的分片队列。任务执行类订阅该任务的分片队列,作为消息消费者,在消费逻辑中实现业务处理。分片的消费可利用消息中间件的多线程处理机制实现高并发。
具体方案如下:
1.系统提供执行器节点基础开发框架,用户使用该框架完成执行器节点任务分解分发类和任务执行类的开发。
2.用户在调度中心登记任务,对任务属性进行配置,主要为任务名称、任务定时执行的周期、任务使用的执行器集群名称、一次分片参数,二次分片参数等。
3.执行器集群各个节点启动后,每个执行器节点向调度中心注册自己,提供自己的集群名称,并定时发送心跳告知存活状态。
4.任务定时启动时间到,调度中心向集群中存活的执行器节点发起调度,并传递执行器总数、执行器序号、一次分片参数、二次分片参数等。其中一次分片参数支持可以为自定义格式的字符串,执行器节点任务分解类可解析该字符串作为一次分片的参数使用;二次分片参数为指定二次分片内数据条数的数字。
5.执行器节点的任务分解分发类接收到任务调度请求,根据执行器总数、执行器序号、一次分片参数筛选出需该节点处理的数据,按照二次分片参数指定的数目将数据拆解为小的数据分片,组织成消息体发送到消息中间件该任务的数据分片队列。
例如:一次分片参数=“北京,上海,广州,深圳”,二次分片参数=200,执行器总数=3,当前执行器序号=0 (共3个执行器,序号0、1、2),在类的实现中可以将一次分片参数按分隔符“,”解析为数组[“北京”,“上海”,“广州”,“深圳”],用“数组下表标mod执行器总数,余数=当前执行器序号”的策略取一次分片参数,则当前执行器0负责“北京”, “深圳”的数据,按这个条件筛选出数据后,再按配置的二次分片参数,每200条数据组合成一个集合作为消息体发送到该任务的分片队列。这样,假如取到了10000条数据,将会被拆解为50个小的任务分片。
6.执行器节点的任务执行类作为分片队列的消费者,收到消息队列中间件推送的分片数据,按照业务逻辑进行处理。消息中间件的使用细节封装在执行器节点基础开发框架内,对用户屏蔽。由于执行器集群内各节点同属一个消费组,分片数据消息分发到各节点并行处理,并且利用消息中间件消费端多线程配置,单个节点内也实现了并行消费。可见,对用户来说,只需关注业务逻辑实现消费接口,并配置一些多线程参数就可以实现高并发,使用非常简单。
7.执行器任务执行类处理数据同时向调度中心回传执行状态和结果。可通过调度中心前端查看任务执行状态,进行失败处理等操作。