**这几天,在做一个项目的数据一键同步,原有的功能在面对大数据的时候很脆弱,非常的慢。所以上面要我重构一下(不是简单的任务呢!)。正好前段时间研究Spring架构的时候,看到有一个Spring-Batch这样的一个批处理组件,很有兴趣。决定研究一下看看,遗憾的是官方文档比较少还是英文的,国内也没有多少资料可供参考,相关书籍也几本上算是国外资料的中文翻译,所以花了不少的时间和精力研究,现将一些研究成果写出来,一来当自己的学习笔记,另一方面希望能获得高手的指点。首先要说Spring-Batch处理大数据是非常漂亮的。废话少说直接切入正题:
先看百度上的一个介绍:**
Spring Batch 是一个轻量级的、完善的批处理框架,旨在帮助企业建立健壮、高效的批处理应用。Spring Batch是Spring的一个子项目,使用Java语言并基于Spring框架为基础开发,使的已经使用 Spring 框架的开发者或者企业更容易访问和利用企业服务。
Spring Batch 提供了大量可重用的组件,包括了日志、追踪、事务、任务作业统计、任务重启、跳过、重复、资源管理。对于大数据量和高性能的批处理任务,Spring Batch 同样提供了高级功能和特性来支持,比如分区功能、远程功能。总之,通过 Spring Batch 能够支持简单的、复杂的和大数据量的批处理作业。
Spring Batch 是一个批处理应用框架,不是调度框架,但需要和调度框架合作来构建完成的批处理任务。它只关注批处理任务相关的问题,如事务、并发、监控、执行等,并不提供相应的调度功能。如果需要使用调用框架,在商业软件和开源软件中已经有很多优秀的企业级调度框架(如 Quartz、Tivoli、Control-M、Cron 等)可以使用。
经典的应用场景
- 周期性的提交批处理
- 把一个任务并行处理
- 消息驱动应用分级处理
- 大规模并行批处理
- 手工或调度使任务失败之后重新启动
- 有依赖步骤的顺序执行(使用工作流驱动扩展)
- 处理时跳过部分记录
- 成批事务:为小批量的或有的存储过程/脚本的场景使用
SpringBatch结构:
Spring-Batch版本区别:
2.1.X和2.2.X以上版本从写法上已经有很大区别,因为项目非常的老,Spring版本是2.5.6的,所以只能使用2.1.X ,从Maven的仓库来看2.1.X是可以的
2.2.X以上的版本是支持3.2以上的版本
这个大家要注意,SpringBatch的写法上也是有区别的。
2.1.X 写法如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch.xsd
">
<bean
class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry" />
</bean>
<bean id="jobRegistry"
class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
<!-- 多数据源的时候不能用动态配置 -->
<bean id="jobExplorer"
class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
<property name="dataSource" ref="dataSourceOracle" />
</bean>
<bean id="jobOperator"
class="org.springframework.batch.core.launch.support.SimpleJobOperator">
<property name="jobRepository" ref="jobRepository" />
<property name="jobLauncher" ref="jobLauncher" />
<property name="jobRegistry" ref="jobRegistry" />
<property name="jobExplorer" ref="jobExplorer" />
</bean>
<!-- 作业调度器,用来启动Job -->
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<!-- 定义了事物管理器,用于Spring Batch架构在对数据操作过程中 -->
<bean id="transactionManagerOracle"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceOracle" />
</bean>
<batch:job-repository id="jobRepository"
data-source="dataSourceOracle" transaction-manager="transactionManagerOracle"
isolation-level-for-create="SERIALIZABLE" table-prefix="BATCH_"
max-varchar-length="1000" />
<!-- job -->
<batch:job id="insertData">
<batch:step id="dbWirterStep">
<batch:tasklet transaction-manager="transactionManagerOracle">
<batch:chunk reader="restarCustomStudentItemReader" processor="partTranslateProcessor" writer="jdbcSetterItemWriter" commit-interval="4000"></batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="jdbcSetterItemWriter"
class="com.batch.MyJdbcBatchItemWriter">
<property name="dataSource" ref="dataSourceOracle"/>
<property name="itemPreparedStatementSetter">
<bean class="com.batch.DestCreditBillItemPreparedStatementSetter"/>
</property>
</bean>
<bean id="restarCustomStudentItemReader" class="com.batch.RestartableCustomStudentItemReader">
<property name="currentLocation" value="100000"></property>
</bean>
<bean id="partTranslateProcessor" class="com.batch.PartTranslateItemProcessor"/>
</beans>
2.2.X的写法如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"
>
<context:annotation-config />
<context:component-scan base-package="springbatch" />
<bean:bean
class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<bean:property name="jobRegistry" ref="jobRegistry" />
</bean:bean>
<bean:bean id="jobRegistry"
class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
<bean:bean id="jobExplorer"
class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
<bean:property name="dataSource" ref="dataSource" />
</bean:bean>
<bean:bean id="jobOperator"
class="org.springframework.batch.core.launch.support.SimpleJobOperator">
<bean:property name="jobRepository" ref="jobRepository" />
<bean:property name="jobLauncher" ref="jobLauncher" />
<bean:property name="jobRegistry" ref="jobRegistry" />
<bean:property name="jobExplorer" ref="jobExplorer" />
</bean:bean>
<!-- 作业调度器,用来启动Job -->
<bean:bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<bean:property name="jobRepository" ref="jobRepository"/>
</bean:bean>
<!-- 定义作业仓库,任何任务的操作都会被记录在作业仓库中 提供两种作业仓库,一种为内存的,一种为数据库的 -->
<job-repository id="jobRepository" data-source="dataSource"
transaction-manager="transactionManager" isolation-level-for-create="SERIALIZABLE"
table-prefix="BATCH_" max-varchar-length="1000"
/>
<!-- 定义了事物管理器,用于Spring Batch架构在对数据操作过程中 -->
<bean:bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<bean:property name="dataSource" ref="dataSource" />
</bean:bean>
<!-- 初始化表结构 -->
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" />
<jdbc:script location="org/springframework/batch/core/schema-mysql.sql" />
</jdbc:initialize-database>
<!-- <jdbc:initialize-database data-source="dataSource"> -->
<!-- <jdbc:script location="org/springframework/batch/core/schema-drop-oracle10g.sql" /> -->
<!-- <jdbc:script location="org/springframework/batch/core/schema-oracle10g.sql" /> -->
<!-- </jdbc:initialize-database> -->
</bean:beans>
主要是 job-repository 或者 job 在2.1.X版本上都加一个batch:就可以 ,还有就是生成的repository表结构是不一样的,这点请大家注意。
环境搭建:##
Maven配置如下所示:
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
在这里我要强调一下oracle 这块的驱动,不要使用ojdbc14 要使用ojdbc6
14表示的是JDK1.4、6表示JDK1.6
如果用14版本的Oracle驱动则将批量提交commit超过10000的时候必然会报错。请大家一定要注意。