[Spring Cloud Task]5 Spring Batch数据分片探究

概述

本文是Spring Cloud Task系列的第五篇文章,如果你尚未使用过Spring Cloud Task,请 移步spring cloud task1 简介与示例
本文主要讲述的是Spring的另一个核心子项目 Spring Batch中的数据分片的设计,数据分片是分而治之的编程思想提现。分片的意义是利用多核cpu并行处理的优势,将数据量大且执行时间长的任务,依照一定规则,拆分成多个平等的可同时执行的任务。通过分而治之的思想,来减少批处理程序的整体运行时间,加快应用的执行效率。

详情

数据分片具体的表现是将数据处理应用部署多个版本并行运行。其目标是通过并行运行,减少需要极长时间才能完成的批处理任务的整体执行时间。数据分片能够显著减少批处理任务执行时间,但也并非银弹。只有在业务所用到的资源文件支持拆分,或业务表支持同时操作完全不同的数据集时,才可以考虑使用数据分片。

设计分片任务时应该注意,首先我们应该准守单一智能原则,一个分片任务应该只处理被分配分配给它的数据集。其次分片任务应用的架构最好跟数据库的分区设计保持一致(这里指的数据库分区不只是物理数据库分区,逻辑的垂直分表也应该被看做分区)。图1展示了典型分片处理应用的逻辑架构。

分片处理应用的逻辑架构

通过分析这个架构图,一个可分片的批处理应用应满足可以使用户自定义配置且可以动态的决定启用多少个分片任务。如何去让应用自动配置呢?举个例子,我们可以取输入文件的文件大小或者是数据纪录条数作为参数来动态控制分片任务的数量。

分片方法

分片应用的分片方法取决于其面对的业务场景,下面介绍几个常用的分片方法

1. 固定分片法

将数据集平均分配给固定数量的分片任务中(例如一共有10个分片任务,每个分配任务将得到1/10的数据集),每个分片任务都是批处理任务的一个部署实例。

使用这种分片方式需要设计一个预处理程序来切分总数据集。预处理程序可以计算出每个分片任务要处理的数据的上下边界,并作为输入参数传递给分片任务,这样分片任务就能做到处理自己的数据。

不过预处理任务需要计算和确定每个批处理任务需要处理的数据集的边界,所以其本身可能会有很大的性能开销。

2. 关键列分片法

关键列区分发是通过某个特殊的列的值来分割数据集,这种分配方式会为每一个域值分配一个批处理应用实例(例如通过地区编号区分)。一般情况以下两种方案进行关键列区分:

  • 通过表分区来为批处理实例分配输入数据集
  • 通过区间数据集来为批处理实例分配数据集(如0000-0999,1000-1999等)

关于方法一,该列一般是枚举值。注意在添加新枚举选项时,需要重新配置批处理程序需要处理的关键字。

关于方法二,字段区间的特性使方法二能够覆盖到所有的字段可能值,但正因一个批处理实例所分配到的数据是完全分散于该列的各个区间值上的,这有可能造成在0000-0999区间上有大量数据,而1000-1999上仅分布极小的数据集。所以在采用方法二时,应当先考虑清楚数据的分布区间问题。

上面两种方法中批处理应用实例的数量无法根据数据分布的特性进行动态调整,我们还需要根据实际业务需求寻找最佳方案。

3. 视图分片法

视图分片法是完全基于数据库的,借助关系型数据库的视图的概念,为每个批处理应用实例分配一个专有的视图。原理就是利用数据库的分组group语句,来为批处理应用隔离数据。

这个方法需要批处理应用实例自行配置自己所需处理的视图(而不是直接使用主表),并且在新增group的值时,还需要配置新的视图。这种方法完全没有动态扩展能力,每新增一个视图的同时就需要新配置一个批处理应用实例。

4. 标识分片法

标识分片法是在数据库表中新增一个数据处理标识的列来作为指示器。预处理数据阶段,所有指示器的值都是待处理状态。数据读取阶段,只读取指示器为未处理的数据行。一旦读取到数据后,立刻将数据锁定。当数据处理完成后,指示器被标记为完成或错误状态。

标识分片法的指示器也可以防止批处理应用多次执行时会重复处理数据。不过标记分片法I/O占用很多,所以它更适合用在以写操作为主的应用上,这样对性能的影响才能降到最低。

5. 临时文件法

将表中的数据导出到文件,文件可以采用多种标记进行分割并作为批处理应用实例的输入数据。

将表提取到文件并分割数据在一定程度上能够降低任务分片的复杂度,如此只需要修改文件分割脚本便可以实现分片的动态配置。

6. 哈希法

哈希法指的是通过数据库表中的哈希列来检索数据,哈希列作为一个指示器,来计算每个数据行应该被哪一个批处理应用实例来处理。

这种方法在检索数据时使用 WHERE 子句来选取带有特定指示器的所有行,且每次插入数据时,都应该为标识器设置一个值来决定日后分配给哪一个批处理实例来处理。

随着业务的增长,批处理数据源的增多,为提高整体效率,往往需要在多个批处理实例间重新分配要处理的数据。哈希法关注的是哈希列的值与应用实例数量的求余,在实现上它需要一个额外的应用来进行批处理用于实例的注册和待处理哈希分配。

关于

示例源码

Spring Cloud Task learning 的 task-demo-with-datasource 子项目

后记

Spring Cloud Task是一个优秀的项目,但是我找遍网络,也难以找出系统的、准确的中文相关文档。本系列文章以保证对Spring Cloud Task相关概念和设计理解的正确性为标准,尽量采用通俗易懂的语言,希望能给各位带来一些便捷。

本文内容主要是对 Spring Cloud Task 1.2.2-RELEASE 官方文档的翻译,不过作者水平有限,有不尽然的地方敬请指出。本项目和文档中所用的内容仅供学习和研究之用,转载或引用时请指明出处。如果你对文档有疑问或问题,请在项目中给我留言或发email到weiwei02@vip.qq.com 我的github:https://github.com/weiwei02/ 我相信技术能够改变世界 。

链接

Spring Cloud Task 2.2.3 是 Spring Cloud Task 框架的一个维护版本,属于 **Spring Boot 2.2.x** 和 **Spring Cloud Hoxton** 版本线的一部分。它旨在为短生命周期、可执行的任务(如批处理作业、数据迁移、定时脚本等)提供**轻量级的任务管理能力**,并记录任务的执行元数据(如开始时间、结束时间、退出码、参数等),特别适用于微服务架构中的任务型应用。 --- ### 核心特性 1. **任务执行生命周期管理** - 自动记录任务的启动与结束状态 - 支持成功、失败、异常中断等多种结果 - 提供 `TaskExecution` 实体存储执行信息 2. **任务元数据持久化** - 默认使用关系型数据库(H2, MySQL, PostgreSQL, Oracle 等) - 表结构包括: - `TASK_EXECUTION`:任务执行记录 - `TASK_TASK_BATCH`:关联 Job(与 Spring Batch 集成时使用) - `TASK_EVENT`:任务事件日志 3. **与 Spring Boot 完美集成** - 所有任务都是标准的 Spring Boot 应用 - 启动后自动注册执行记录,关闭前更新状态 4. **支持命令行参数和外部配置** - 可通过 `--name=xxx --param=value` 传参 - 参数可记录在 `TASK_EXECUTION_PARAMS` 表中 5. **与 Spring Batch 深度集成** - 若类路径中有 `spring-batch-core`,可自动关联 Batch Job - 一个 Task 可触发一个或多个 Batch Job 6. **分布式部署支持** - 支持在本地、Kubernetes、Cloud Foundry 上运行 - 多实例任务可通过数据库实现并发控制 --- ### Maven 依赖示例 ```xml <dependencies> <!-- 核心依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-task</artifactId> </dependency> <!-- 数据库支持(必须) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 可选:集成 Spring Batch --> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-core</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ``` --- ### 快速示例:创建一个简单任务 ```java @SpringBootApplication public class SimpleTaskApplication { @Bean public CommandLineRunner commandLineRunner() { return args -> { System.out.println("【任务开始】执行数据清理..."); Thread.sleep(2000); System.out.println("【任务完成】数据已清理!"); }; } public static void main(String[] args) { SpringApplication.run(SimpleTaskApplication.class, args); } } ``` --- ### 配置文件(application.yml) ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/taskdb?useSSL=false&serverTimezone=UTC username: root password: password driver-class-name: com.mysql.cj.jdbc.Driver cloud: task: table-prefix: TASK_ # 自定义表前缀(可选) initialization-mode: always # 启动时自动建表 ``` > ✅ 第一次运行会自动创建所需的 `TASK_EXECUTION` 等表。 --- ### 任务执行输出示例 运行后数据库 `TASK_EXECUTION` 表内容: | TASK_EXECUTION_ID | START_TIME | END_TIME | EXIT_CODE | EXIT_MESSAGE | TASK_NAME | |-------------------|---------------------|---------------------|-----------|--------------|------------------| | 1 | 2025-04-05 10:00:00 | 2025-04-05 10:00:02 | 0 | null | simpleTaskApp | 表示任务成功执行,耗时约 2 秒。 --- ### 与 Spring Cloud Data Flow 集成 Spring Cloud Task 常作为 **Spring Cloud Data Flow (SCDF)** 中的 `Task` 单元使用: 1. 将任务应用打包为 Docker 镜像或 JAR 2. 在 SCDF 中注册: ```bash app register --name cleanup-task --type task --uri docker://myrepo/cleanup-task:1.0 ``` 3. 创建并启动任务: ```bash task launch cleanup-task --arguments "date=2025-04-05" ``` SCDF 会调用该任务,并从数据库读取执行结果进行展示。 --- ### 注意事项 - **必须配置数据源**,否则启动报错 - 任务结束后 JVM 自动退出(除非设置 `spring.main.web-application-type=none` 并手动控制) - 推荐每个任务有唯一名称(通过 `@EnableTask` 或配置设置) ```java @EnableTask @Configuration public class TaskConfig { } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值