spring batch框架主要应用于批处理数据量较大的后台业务,使用这个框架能够更灵活,使用各种姿势对数据进行花样的操作,但是数据量到达千万级别之后,单机的处理任务效率明显下滑,并行和分区就是面对这个问题的灵丹妙药。
通过查阅中文官网,对Spring Bacth有了更深层次的理解,强裂推荐,文档写的真心不错,对于多种分布式实现提供了很好思路。
https://www.bookstack.cn/read/SpringBatchReferenceCN/13_integration-README.md
首先来了解并行和分区:
什么时候使用并行,多个任务不使用同一个文件,数据表,索引空间时可以使用并行,这很简单。
什么时候使用分区,如果确实存在共享和竞争,那么这个服务就应该使用分区数据来实现,另一种选择是使用控制表来构建一个架构模块以维护他们之间的相互依赖关系,控制表应该为每个共享资源分配一行记录,不管这些资源是否被某个程序所使用,执行并行作业的批处理架构或程序随后将查询这个控制表,来确定是否可以访问所需的资源。
工作中值得一探究竟是就是Spring Batch的分区,分区又分为本地分区和远程分区。我个人理解这本地和远程的分别在于:
本地分区,一个完整的reader,processor,writer执行步骤step被切割成多线程同时执行
远程分区:一个完整的reader,processor,writer执行步骤step被切割后分发到多节点执行
先从比较简单的本地分区上手。
本地分区:
通过查看spring batch官方文档,了解到分区的核心思想是master-slave:
把一个步骤,拆分成多个步骤执行:
上代码进行解析,step步骤所需的reader,processor,writer
1、本文读取数据的方式,使用的是框架提供的API实现数据库分页读取MybatisPagingItemReader,工作中常用ItemReader自定义实现
2、自定义处理类实现ItemProcessor
3、文件写入,使用框架自带的API实现写入csv文件,FlatFileItemWriter,工作中常用ItemWriter自定义实现
4、启动类代码实现
5、本地分区分割器实现
执行分区效果如下:
文件个数对应分区线程数,由参数gridSize决定,本文gridSize=10,对应生成10个文件
以上实现的是单节点多线程处理文件,但只能一定限度上提升批处理的执行效率,对于千万级的数据处理还远远不够,如过能做到多节点多线程才是真正能够更好提升效率的解决方法,这就是接下来要说的远程分区。通过看完中文官方文档,发现真正想实现远程分区的代码实现,过分复杂,并非是通过少量的伪代码就能实现功能,所以本文着重在于提供远程分区的一种实现思路,并不拓展开讲。
想明白远程分区就必须以深刻理解以下几个组件为前提,为什么呢,因为本地分区可以直接使用框架自己带实现,仅仅需要去实现Partitioner接口即可,但是远程分区涉及多节点之间的通信,往往需要自定义实现:
1、远程分区处理器(PartitionHandler),PartitionHandler组件知道远程网格环境的组织结构。 它可以发送step的上下文StepExecution请求给远端Steps,采用某种具体的数据格式,通过自定义实PartitionHandler接口,实现消息的远程分发,PartitionHandler接口可以有各种结构的实现类: 如RMI远程方法调用,EJB远程调用,自定义web服务、JMS、Java Spaces, 共享内存网格(如Terracotta或Coherence)、网格执行结构(如GridGain)。不论是哪一种选型都是为了实现网络通信。
2、分割器,Partitioner,分割器在本地分区也同样会使用,上面有相关代码贴图,它的职责就是为新的step实例生成执行环境(contexts),作为输入参数
3、各个从节点接收到分区的消息,将输入数据绑定到 Steps,并立即执行,将实现多节点处理文件