学习笔记-如何设计离线跑批系统
Posted 欧阳青星
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记-如何设计离线跑批系统相关的知识,希望对你有一定的参考价值。
一、基本概念
离线跑批:通常指批量加工数据、完成一系列流程的定时任务。
业务场景:在银行、金融、支付出现较多,其他行业也可能涉及。
1. 定时的数据状态更新(到期失效)
2. 数据计算(计算罚息、计提)
3. 文件处理、生成文件(对账,同步文件)
二、系统特点
1. 容易造成OOM。对文件或数据库进行读取时,必须考虑线上数据量,如果一次性查询的数据量太大,则需要想办法从业务上拆分数据或进行数据分片,否则容易OutOfMemory。
2. 容易造成慢SQL。由于离线跑批通常会基于日期来做查询,而非实时接口中常见的有索引的查询字段——证件号、会员号等,对数据库进行读时,必须检查SQL是否能走索引及未来数据增长量。
3. 一定要高容错,否则运维成本极高。
- 从离线跑批的概念我们可知,一旦任务出现程序bug、中间件或依赖服务宕机,这些批量处理的海量数据和执行流程,就极难人为恢复或处理(特别是和钱打交道的业务)。
- 因此,需要有重试、重跑、兜底处理、重复校验等等代码机制,这些机制则由更底层的事务、任务状态来保障。
重试 / 重跑 / 重复校验 | 任务应是可以手动或自动多次重复执行的,例如虽然在业务上要求每天执行1次,但考虑到异常情况将任务配置成每天执行3次,则在当天有成功执行后就不必再执行了。 |
兜底处理 | 与实时接口相同,在依赖第三方服务、中间件、文件处理等流程时,需要考虑边界值、异常值、空值等情况,结合业务为程序设计兜底处理方式。 |
事务 / 任务状态 | 要保证任务能够重复校验,则需要依赖任务状态,进一步讲,任务的状态从初始态到终态,则又由事务来保障。 |
三、设计思路
1. 将整个业务流程拆分为多个步骤,步骤之间可串行或并行。步骤是带状态的,步骤在正常或异常结束后通过事务将状态更新。
2. 其他Tips
- 可根据业务进行技术选型,xxl-job、Spring Batch等。
- 数据库批量写处理。
- 有顺序的数据即可分片,分片后应可定位到每片数据。
- 纯运算型可通过 lambda并行流运算。
四、实例分析
1. 土豆烧牛肉(仅通过此例简单解释下设计思路,不必纠结细节)
整个流程:每天12点和18点需要制作10000份儿土豆烧牛肉,包括买菜、备菜、烹饪的过程。
步骤拆分:
- 买菜。提交金钱转换为食材事务。该定时任务可在0点~10点每小时执行一次,如果当天食材足够则跳过,否则进行食材购买。
- 备菜。提交食材转换为处理好的食材的事务。该定时任务可在8点~18点每10分执行一次。
- 烹饪。执行成功时,将处理好的食材转换为成品。该定时任务可在9点~18点每10分钟执行一次。
- 食材校验告警。每天10点执行一次,如果当天食材不足够,则发送告警短信提醒,需要人为干预处理。
2. 客户文件管理系统
流程背景:系统首先去指定SFTP下载合同文件到本地目录,之后进行文件签章,上传文件归档平台,最后清理本地目录文件。
步骤拆分:由于该业务流程天然面向过程化,可直接按照业务分为文件下载、文件签章、文件上传、文件清理备份。
3. 银行代扣系统
流程背景:用户从银行贷款后,银行每个月从客户的卡里扣钱。不同贷款产品代扣的时间不同,如房贷A每天9点扣款,车贷B每天12点扣款。每个客户的还款日不同。
步骤拆分:
- 生成批次。提交初始化批次数据的事务(按产品维度,每一个产品一条批次数据)。定时任务可每5分钟执行一次,每次扫描±10分钟内需要进行代扣的产品(这种情况是默认有一个业务配置中心,维护了每个产品的代扣时间,如果没有统一的配置中心,也可以每个产品为一个定时任务仅生成自己的批次)。
- 生成任务。提交初始化任务数据、更新批次表状态为处理中的事务。该定时任务可每5分执行一次。
- 发起代扣。查询任务表中非终态的任务数据,调用代扣接口,提交任务表更新、批次表更新的事务。任务包括初始化、进行中、失败、成功等状态,同时会进行失败重试,记录失败次数和失败原因。
- 失败告警任务。根据实际业务情况,针对失败次数和原因进行统计,或实时SQL进行短信告警。
五、参考文档
高效跑批设计思路——针对系统中的批量、日终任务 - appinn - 博客园
以上是关于学习笔记-如何设计离线跑批系统的主要内容,如果未能解决你的问题,请参考以下文章