对工作中遇到的数据处理Job做了一些梳理,这里试图总结一种通用的Job开发思路。
1. Job的构成
Job 的核心元素包含: 任务、数据、接口、结果。
1.1 任务
数据处理任务。有些业务场景下,Job与任务是绑定的,执行一次Job就对应一个任务。有些业务场景下,任务由用户随意添加,Job执行一次需要处理多个任务。
1.2 数据
每次任务需要处理的数据。根据业务场景不同,数据可能本身存在数据库里,也有可能存在文件中(如Excel)。
1.3 接口
处理数据的接口,每条数据都需要经过接口的处理。
1.4 结果
数据的处理结果。成功或者失败都需要被记录下,如果失败还需要记录失败的原因,可能是业务原因(数据异常、业务规则等),也可能是技术原因(代码bug、执行异常等)。
2. Job流程
画一张通用版的数据处理Job的流程图如下
阶段 | 具体步骤 |
---|---|
任务开始 | 1. 查询待处理的任务,并取第一个任务 |
准备数据 | 2. 把任务需要处理的数据保存进数据库,并初始化数据状态为待处理。 (如果数据本身就在数据库中可以选择忽略这一步) |
数据分片 | 3. 查询一批待处理或处理中的数据 (如果数据列表为空则更新任务状态为完成并结束Job) |
数据处理 | 4. 取一定量的数据(具体的量根据下游接口实际情况确定) 5. 调用处理接口 6. 等待处理完成后更新数据的结果, 7. 继续执行3,4,5,6步骤,直到没有待处理或处理中的数据 |
任务完成 | 8. 更新任务状态为已处理 9. 继续执行下一个任务 |
3. 注意事项
3.1 健壮的Job
3.1.1 源数据异常
数据处理任务常遇到的异常来自于不合法的原始数据,特别是当原始数据来自于人工数据的情况(如导入的文件)。在处理原始数据时要注意做好异常的捕获。捕获的范围不要太大,最好作用于单条数据的处理过程,这样可以做到某条数据异常不影响其他数据的正常处理。
3.1.2 下游接口异常
接口调用不论是RPC调用还是本地方法调用都应当做好异常捕获,否则容易导致整个任务处理失败。
3.1.3 接口调用超时
接口调用超时是需要特别注意的一种异常,特别点在于接口调用的结果未知。不能简单的记录调用结果为成功或失败,可以记录数据状态为 未处理 或 处理中 等待下次Job再次执行时重试。另外,下游接口一定要做好幂等处理,不然会出现重复数据。
3.1.4 数据量突增
Job处理的数据量非常可能随着业务发展而快速增长,所以需要在处理数据时做好数据分片,以防出现调用处理接口超时等情况。
3.2 中断恢复方案
3.2.1 接口实现幂等
下游接口实现幂等非常重要,幂等使得任务可以重复执行,而无需担心产生重复数据。
3.2.2 增加处理状态
处理状态有待处理、处理中、处理完成等。处理状态可以记录处理进度,在中断发生后可以根据处理状态区分出剩余未处理的数据。
- 任务状态。一共两种:待处理、已处理。待处理 的任务执行完成后流转成 已处理。如果出现了任务中断的情况,因为有中断恢复的能力,所以可以重复执行。
- 数据状态。数据状态有待处理、处理成功、处理失败、处理中(可选)。处理中状态可以清晰的标识出某条数据发生了接口超时未返回的情况,需要等待下次重试。处理中是可选的,可以和 待处理 合并。处理失败时需要记录失败原因,如果是异常导致则记录异常提示。
3.3 高性能
3.3.1 多线程
不一定每个Job都需要配置多线程,但是大多数数据处理Job都对性能有要求。多线程是最简单易实现的性能提升方案之一。