一、背景
1.1.什么是批量处理
1.2.批量处理拥有广泛的使用场景
1.3.批量处理需要良好的架构设计
二、批量处理中的关键设计
2.1从SpringBatch看批量任务设计模式
2.2任务调度设计
三、总结
一、背景
1.1.什么是批量处理
维基百科给批量处理的定义是指在没有人工干预的情况下,由一个计算机程序基于一份批量的输入执行一系列的任务的一种处理模式。这句话可能有点拗口,简单来说,批量处理是一种处理模式,这种模式在进行数据处理时,输入数据一般包含多条,处理过程中一般没有人工交互。而另一种主流的处理模式,联机处理与批量处理的最主要区别就是,联机处理中一般一条输入数据就产生一次处理过程,然后直接将结果反馈给调用方。批量处理曾经在早期的计算机处理模式中占据统治地位。
1.2.批量处理拥有广泛的使用场景
我们先来看下批量处理的特点:
从批量处理的特点我们可以看到,在实时性、交互性要求不高,同时待处理的数据量比较大的场景下,就可以考虑使用批量处理的模式。而实际各种业务系统中通常都会存在大量适合使用或者正在使用批量处理的场景,常见的如银行的对账、网银的批量待发工资、日志系统中批量备份日志等。我们大家可能都会有从支付宝里提现至银行卡的经历,通常提现并不是实时的,支付宝会给你一个deadline,这中间支付宝与银行之间数据对账就是采用批量处理完成的。
1.3.批量处理需要良好的架构设计
在最简单的批量处理场景下,我们可以通过编写脚本,在类Unix系统中通过cron程序定时启动执行。但是这种模式仅仅适合单机处理的情况,没有分布式处理的能力,同时也没有办法进行统一的监控管理。在实际使用时,可能同时存在数量巨大的批量任务,如何管理与调度这些任务将是个巨大的挑战。设计良好的批量处理框架可以简化批量任务开发过程,减少配置时间,提高整体稳定性。笔者曾经参与过某银行BPM系统批量处理框架的设计,一开始设计比较简单,在各个服务器部署批量脚本,基于cron执行,通过数据库进行结果统计,在项目上线初始阶段,由于批量任务比较少,所做的工作也比较简单,该设计能够基本满足需求,但是随着项目上线后,批量任务越来越多,场景越来越复杂(比如需要支持数据库服务器HA切换时批量任务不重复执行),原有设计已经越来越力不从心,最后只有推倒重新设计,费时又费力,由此可见一个好的批量处理框架设计是多么的重要。本文将通过分析批量处理中的两个关键环节,结合一些开源的批量处理框架,来聊一聊如何更好地进行批量处理型架构的设计。
二、批量处理中的关键设计
批量处理中两个关键环节是批量任务设计和任务调度设计:
批量任务设计:统一规定了作业的定义、编排、执行等过程,良好的作业模型可以隐藏了内部复杂性,简化具体作业开发难度,更好的支持调度过程。
任务调度设计:通俗的说调度就是控制作业在什么时候由那些资源(节点、线程等)去执行,同时还包含作业执行失败后的处理等内容。
2.1从SpringBatch看批量任务设计模式
2.1.1传统批量作业结构
我们首先来看一下过去几十年间已经被广泛使用的批量作业结构:
图1 批量作业结构
这个架构图非常简单,传递了批量作业中最重要的几个领域概念:
在这种设计模式下,任务的定义执行过程变得非常清晰,使用这只需要关注于每个Step中的具体业务实现即可,通过简单的配置就能完成任务的设计。
2.1.2. SpringBatch中的任务设计模式:
传统批量作业结构在好几代平台和编程语言中已经被证明为非常合理和有效。著名Java开源批处理框架SpringBatch就是实现了这种作业结构,不过除此之外,SpringBatch还加入了自身一些设计:
图2 SpringBatch作业模型
上图展现了SpringBatch中的几个概念模型:
同时,为了提高作业运行时效率, SpringBatch中还同时提供了几种并行处理方案:
图3 远程分片模型 在远程分片模型中,某一个Step中由Master节点去读取数据,但是处理的过程,由Master分配给多个Slaves去处理,在这种模型中,Master节点的读取能力不能成为整个Step的瓶颈。
2.1.3 SpringBatch的不足
可以看到SpringBatch中提供了一套非常完善的批量任务设计模式,但是SpringBatch也有不足的地方:
2.2任务调度设计
2.2.1两种调度模式
常见分布式调度系统在设计上主要有中心化和去中心化两种模式:
2.2.1.1. 中心化的调度模式
下图为中心化的调度模式结构图:
图4中心化的调度模型
如上图所示,在中心化的调度模式下,一般都有一个Leader节点用来负责拉取任务的调度信息,然后向各个Follower节点分派任务,由Follower节点完成任务的执行。同时为了保证整个系统的高可用,Leader节点一般会采取主备模式,当一个Leader节点失效时,备用节点会接管Leader节点工作。
2.2.1.2. 去中心化的调度模式
下面再来看一下去中心化模式:
图5去中心化的调度模型
在去中心化的调度模式下,没有调度中心节点这个概念,所有节点都是工作节点,节点之间通过注册中心进行分布式协调,但是在这种模式下,一般会有一个主节点用于处理一些集中式任务,如分片,清理运行时信息等,并无调度功能,定时调度都是由作业节点自己触发执行。
下面对比一下两种调度模式各自的优缺点:
中心化 | 去中心化 | |
---|---|---|
实现难度 | 高 | 低 |
部署难度 | 高 | 低 |
触发时间统一控制 | 可以 | 不可以 |
触发延迟 | 有 | 无 |
异构语言支持 | 容易 | 困难 |
表1 中心化和去中心化调度比较
2.2.2. TBSchedule中的调度设计
TBSchedule是由Taobao开源的一款非常优秀的高性能分布式调度框架,TBSchedule的使用非常广泛,目前被应用于淘宝、京东、国美、等很多互联网企业的调度系统。TBSchedule有如下特点:
TBSchedule支持Cluster,可以宿主在多台服务器多个线程组并行进行任务调度,或者说可以将一个大的任务拆成多个小任务分配到不同的服务器。
TBSchedule的分布式机制是通过Sharding方式实现的,比如可以按所有数据的ID按10取模分片、按月份分片等等,根据不同的需求,不同的场景由客户端配置分片规则。TBSchedule的宿主服务器可以进行动态扩容和资源回收,这个特点主要是因为它后端依赖的ZooKeeper,这里的ZooKeeper对于TBSchedule来说是一个NoSQL,用于存储策略、任务、心跳信息数据,它的数据结构类似文件系统的目录结构,它的节点有临时节点、持久节点之分。调度引擎上线后,随着业务量数据量的增多,当前Cluster可能不能满足目前的处理需求,那么就需要增加服务器数量,一个新的服务器上线后会在ZooKeeper中创建一个代表当前服务器的一个唯一性路径(临时节点),并且新上线的服务器会和ZooKeeper保持长连接,当通信断开后,节点会自动摘除。下图为TBSchedule的基本结构图,从图上可以到,TBSchedule从整体上来说遵循的是去中心化的调度模式,每个节点都可以从ZooKeeper中拉取任务去执行。
图6 TBSchedule结构图
TBSchedule提供了两个核心组件ScheduleServer、TBScheduleManagerFactory。
ScheduleServer即任务处理器,的主要作用是任务和策略的管理、任务采集和执行,由一组工作线程组成,这组工作线程是基于队列实现的,进行任务抓取和任务处理。每个任务处理器和ZooKeeper有一个心跳通信连接,用于检测Server的状态和进行任务动态分配。
调度服务器TBScheduleManagerFactory的主要工作ZooKeeper连接参数配置和ZooKeeper的初始化、调度管理。
TBSchedule中的用户目标任务是通过实现任务接口实现的,任务接口中包含selectTasks和execute两个方法,分别对应任务的采集和执行过程。
2.2.3. TBSchedule的不足
尽管TBSchedule已经很优秀,尤其是资源调度这块,但是TBSchedule也有不足的地方:
四、总结
随着计算机技术的发展,在C/S和B/S软件体系结构中,联机处理模式已经慢慢成为最主要的数据处理模式,尽管如此,批量处理作为一种古老的处理模式,任然以其高吞吐、高性能的特性占据着一席之地。
本文从批量处理的概念出发,结合开源批量框架SpringBatch和TBSchedule,简要介绍了批处理型服务架构的设计。可以看到目前虽然有很多已经被广泛使用的批量处理框架,但是还是存在着很多不完善的地方。
冰冻三尺非一日之寒,任何事物的发展和完善都不是一朝一夕的事,对于批量处理框架设计而言也是如此。我们自己在设计时可以考虑站在巨人的肩膀上,借鉴成熟的框架设计,同时结合具体的业务场景,加入符合需求的功能特性,完善出功能强大、运行稳定和易于使用的批量处理框架。
本文仅仅是抛砖引玉,对于具体设计时的很多细节问题并没有进行深入讨论。希望本文对于正在设计批量处理框架的同学能有那么一点帮助和指导。
关于作者
张京晶
现任普元信息SOA产品部开发工程师,普元新一代数字化企业云平台开发团队成员,参与云平台中UMC领域系统开发。过去两年中曾参与了浦发银行新一代BPM业务流程管理平台项目开发。