春季批次架构
Spring Batch 的设计考虑了可扩展性和多样化的终端用户群体。这 下图展示了支持可扩展性和易用性的分层架构 用于终端用户开发者。
这种分层架构突出了三个主要的高层组件:应用,
核心和基础设施。该应用程序包含所有批处理作业和自定义代码
由使用 Spring Batch 的开发者完成。批处理核心包含核心运行时类
启动和控制批处理作业所必需的。它包含以下实现作业操作员,工作和步.应用和核心都是建立在一个共同的基础之上
基础设施。该基础设施包含通用的读写器和服务
(例如重试模板),这些工具既被应用开发者(阅读器,也)使用
作家,如物品阅读器和物品写手),以及核心框架本身(重试,
这是独立的图书馆)。
一般批次原则与指导方针
应考虑以下关键原则、指导方针和一般性考虑 在构建批量溶液时。
-
请记住,批处理架构通常会影响在线架构及其反作用 反之亦然。通过使用通用架构设计,兼顾架构和环境 能挡就挡。
-
尽量简化,避免在单一结构中构建复杂的逻辑结构 批量申请。
-
保持数据的处理和存储物理上紧密相连(换句话说,保持 你的数据,处理发生的地方)。
-
尽量减少系统资源的使用,尤其是输入输出。尽可能多地执行作 内部记忆。
-
审查应用I/O(分析SQL语句),确保不必要的物理I/O出现 被回避了。特别需要注意以下四个常见缺陷:
-
每次交易都读取数据,而数据可以读取一次并缓存或保存 在工作中的储藏室里。
-
在同一笔交易中重新读取数据,而该数据之前已被读取 交易。
-
导致不必要的表格或索引扫描。
-
未在
哪里SQL语句的从句。
-
-
不要在一次批量运行中重复做同一件事。例如,如果你需要对 为了报告目的,当数据被发送时,你应该(如果可能的话)增加已存储的总额 初始处理,所以你的申报申请不需要重新处理 数据。
-
在批处理应用开始时分配足够的内存,以避免耗时 在重新分配过程中。
-
关于数据完整性,总是抱最坏的假设。插入足够的检查和 记录验证以维护数据完整性。
-
尽可能实现校验和用于内部验证。例如,平面文件 应有拖尾记录显示文件中记录的总数,以及 关键领域。
-
尽早在类似生产环境下规划并执行压力测试 数据量真实。
-
在大型批处理系统中,备份可能具有挑战性,尤其是在系统运行时 同时进行全天候在线申请。数据库备份通常得到妥善维护 但文件备份同样重要。 如果系统依赖于平面文件,文件备份程序不仅应被执行 并且有文档记录,同时也需要定期检测。
批量处理策略
帮助设计和实施批处理系统、基础批处理应用构建模块和 图样应以样本形式提供给设计师和程序员 结构图和代码壳。当开始设计批处理作业时,业务逻辑 应分解为一系列步骤,具体通过以下方式实现 标准构建模块:
-
转换应用:对于由 外部系统,必须创建一个转换应用程序来转换事务 以处理所需的标准格式提供记录。这种批次 应用可以部分或全部由翻译工具模块组成(参见基础 批处理服务)。
-
验证应用:验证应用确保所有输入和输出 记录准确且一致。验证通常基于文件头和 拖尾器、校验和和验证算法,以及记录级交叉检查。
-
提取应用:提取应用程序从数据库读取一组记录,或者 输入文件,根据预定义的规则选择记录,并将记录写入 输出文件。
-
提取/更新应用程序:提取/更新应用程序从数据库读取记录,或者 输入文件,并对数据库或输出文件进行修改,这些修改由所发现的数据驱动 在每个输入记录中。
-
申请处理与更新:处理和更新应用程序对 从提取或验证应用输入事务。处理过程通常 涉及读取数据库以获取处理所需的数据,可能还需进行更新 数据库和创建用于输出处理的记录。
-
输出/格式应用:输出/格式化应用程序读取输入文件,重构数据 根据标准格式从该记录中生成输出文件用于打印 或传输到其他程序或系统。
此外,应为无法实现的业务逻辑提供基本的应用壳 通过上述构建模块建造。
除了主要构建模块外,每个应用还可以使用一个或多个标准 效用步骤,例如:
-
排序:读取输入文件并生成输出文件的程序,其中记录 根据记录中的排序键字段重新排序。通常 由标准系统工具执行。
-
Split:一个程序读取单个输入文件,并将每条记录写入其中一个 多个基于字段值的输出文件。分段可以定制或由 参数驱动的标准系统工具。
-
合并:一个从多个输入文件读取记录并产生一个输出的程序 文件中包含了来自输入文件的合并数据。合并可以定制或执行 参数驱动的标准系统工具。
批处理申请还可以根据输入来源进行分类:
-
数据库驱动的应用由从数据库中检索的行或值驱动。
-
文件驱动应用由从文件中检索的记录或值驱动。
-
消息驱动应用由从消息队列中获取的消息驱动。
任何批次系统的基础是处理策略。影响 策略选择包括:估计批处理系统体积、并发 在线系统或其他批处理系统,可用的批处理窗口。(注意,其中 越来越多的企业想要全天候运行,清除批处理窗口 消失)。
批处理的典型处理方式有(按实现方式由高到大) 复杂度):
-
离线模式下批处理窗口内的正常处理。
-
批量处理或在线处理。
-
同时并行处理多个不同的批处理或作业。
-
分区(同时处理同一作业的多个实例)。
-
是上述选项的组合。
这些选项中的部分或全部可能由商业排程器支持。
本节剩余部分将更详细讨论这些处理选项。 请注意,作为经验法则,批处理采用的提交和锁定策略 进程取决于所执行的处理类型以及在线锁定 战略也应采用相同的原则。因此,批处理架构无法 在整体架构设计时,这只是一个事后考虑的。
锁定策略可以是仅使用普通数据库锁,也可以实现 架构中的额外自定义锁定服务。锁定服务会被追踪 数据库锁定(例如,将必要信息存储在专用的 数据库表)并赋予或拒绝请求数据库的应用程序权限 操作。该架构还可以实现重试逻辑,以避免中止 批量作业以防锁定情况。
1. 在批处理窗口中的正常处理对于在独立中运行的简单批处理 批处理窗口,在线用户或其他批处理不需要更新数据 进程,并发不是问题,可以在 批量运行。
在大多数情况下,更为严密的做法更为合适。记住那批 系统随着时间推移,无论是复杂度还是数据量,都会不断增长 他们处理的量。如果没有锁定策略,且系统仍然依赖 单提交点,修改批处理程序可能会很痛苦。因此,即使 最简单的批处理系统,考虑重启-恢复提交逻辑的需求 选项以及后面描述的更复杂案例的信息 这一部分。
2. 并发批处理或在线处理 批处理数据的应用 在线用户应同时更新任何数据(无论是在 数据库或文件中),这些数据可能被在线用户用于多个 秒。此外,更新应在每隔几次提交到数据库 交易。这样做可以减少其他进程无法访问的数据部分 以及数据不可用的经过时间。
另一种减少物理锁定的方法是逻辑行级锁定 通过乐观锁定模式或悲观锁定模式实现。
-
乐观锁定假设记录争夺的可能性较低。通常意味着 在每个数据库表中插入一个时间戳列,该列同时被批处理和 在线处理。当应用程序获取一行进行处理时,它也会读取 时间戳。当应用程序尝试更新处理后的行时,更新使用了 原始时间戳
哪里第。如果时间戳匹配,数据和 时间戳已更新。如果时间戳不匹配,说明另一个 应用程序在取取和更新尝试之间更新了同一行。因此 无法进行更新。 -
悲观锁定是指假设存在高概率 记录争用,因此需要在 下获得物理锁或逻辑锁 取回时间。一种悲观逻辑锁定使用专用锁柱 数据库表。当应用程序检索该行进行更新时,它会在 中设置一个标志 锁柱。标志已就位,其他应用程序尝试检索 同一行逻辑上失败。当设置标志的应用程序更新该行时,它也会 清除该标志,使其他应用程序能够检索该行。注意 数据的完整性还必须在初始取指与设置之间保持 例如,通过使用数据库锁(例如
选择更新).还要注意 这种方法与物理锁定有相同的缺点,只是在某种程度上有所不同 更易管理的是建立一个超时机制,如果用户解锁锁 记录被锁着去吃午饭。
这些图案不一定适合批量处理,但可以使用 用于并发批处理和在线处理(例如数据库不支持的情况下) 支持行级锁定)。一般来说,乐观锁定更适合 在线应用,而悲观锁定更适合批量应用。 每当使用逻辑锁定时,所有应用都必须采用相同的方案 访问受逻辑锁保护的数据实体。
注意,这两种解决方案都只针对单个记录进行地址锁定。很多时候,我们可能会 需要锁定逻辑相关的一组记录。用实体锁,你必须 非常谨慎地管理这些,以避免潜在的僵局。逻辑锁的话,它 通常最好构建一个理解逻辑记录的逻辑锁管理器 你想保护的群体,这样可以确保锁具连贯且 非死锁。这个逻辑锁管理器通常使用自己的锁表 管理、争用报告、超时机制及其他关注点。
3. 并行处理 并行处理允许多次批处理或作业在 并行处理以最小化总批处理时间。这不是问题,因为 只要作业不共享相同的文件、数据库表或索引空间。如果他们真的做了, 该服务应通过使用分区数据来实现。另一个选择是建造一个 架构模块,用于通过控制表维护相互依赖关系。一个控制 表应包含每个共享资源的行,以及该资源是否被 无论是否应用。批处理架构或并行作业中的应用程序 然后从该表中获取信息,以确定是否能访问 它需要的资源。
如果数据访问不是问题,可以通过 使用额外的线程进行并行处理。在大型机环境中,并行 传统上使用作业类以确保所有任务的CPU时间充足 流程。无论如何,解必须足够稳健,以确保 的时间切片 所有正在运行的进程。
并行处理中的其他关键问题还包括负载均衡和 通用系统资源,如文件、数据库缓冲池等。另外,请注意 控制表本身很容易成为关键资源。
4. 分区 使用分区可以实现多个版本的大型批处理应用程序 同时运行。这样做的目的是减少所需的时间 处理长批次作业。能够成功分区的进程是 输入文件可以被拆分,或者主数据库表被分区,以便 应用程序运行在不同的数据集上。
此外,分区进程必须设计成仅处理其 分配数据集。分区架构必须与数据库紧密相连 设计与数据库分区策略。注意数据库分区并不 必然意味着数据库的物理划分(尽管在大多数情况下,这 建议)。下图展示了分区方法:
该架构应足够灵活,允许数字的动态配置 分区。你应该同时考虑自动配置和用户控制配置。 自动配置可能基于输入文件大小和 输入记录数量。
4.1 分区方法选择分区方法必须在 具体情况具体情况。以下列表描述了一些可能的划分方式 方法:
1. 固定甚至破碎记录
这涉及将输入记录集拆分为偶数部分(例如, 10,每个部分恰好占整个记录集的十分之一)。每个部分则为 由批次/萃取应用的一个实例处理。
使用这种方法需要预处理来拆分记录设置。这 这种分割的结果是你可以使用的下界和上界位置数 作为批处理/提取应用的输入,限制其处理仅限于其 部分。
预处理可能带来较大的开销,因为它必须计算并确定边界 记录集的每个部分。
2. 按键列拆分
这涉及将输入记录拆分为关键列,例如位置代码, 并将每个密钥的数据分配到批处理实例。为此,列 数值可以是:
-
通过分区表(稍后会详细说明)分配给批处理实例 部分)。
-
批处理实例被赋予值的一部分(例如 0000-0999,1000-1999, 等等)。
在选项1中,添加新值意味着手动重新配置批次或提取到 确保新值被添加到特定实例中。
在选项2中,这确保所有值都被批处理的实例覆盖 工作。然而,一个实例处理的值数量依赖于 列值分布(0000-0999 可能有大量位置 1000-1999年间的数量很少)。在这个选项下,数据范围应该是 设计时考虑了分区。
在这两种情况下,记录最均匀分布到批处理实例都不行 实现。批处理实例数量没有动态配置。
3. 按观看次数划分
这种方法基本上是按键列拆分,但放在数据库层面。它涉及 将纪录拆分为视角。这些视图被批处理的每个实例使用 在处理过程中应用。拆分是通过将数据分组完成的。
使用此选项时,每个批处理应用实例都必须配置为 特定视图(而非主表)。此外,新增了数据 值,这组新数据必须包含在视图中。没有动态关系 配置能力,因为实例数量的变化会导致 视野。
4. 添加处理指示器
这涉及向输入表添加一列,作为 指示器。作为预处理步骤,所有指示器都被标记为未处理。 在批处理应用的记录获取阶段,记录会根据以下条件被读取 单个记录被标记为未处理,一旦读取(带锁), 它被标记为正在处理中。当该记录完成时,指示器为 已更新为完整或错误。你可以启动多个批量应用实例 没有变化,因为新增列确保记录只处理一次。
有了这个选项,桌面上的输入输出会动态增加。在更新的情况下 而批量应用则减少了这种影响,因为写入无论如何都必须进行。
5. 将表提取为平面文件
这种方法涉及将表提取到一个平面文件中。该文件随后可以拆分为 多个段,并作为批处理实例的输入。
通过这个选项,将表解压成文件的额外开销和 拆分可能抵消多分区的影响。动态配置 通过修改文件拆分脚本来实现。
6. 哈希列的使用
该方案涉及在数据库表中添加哈希列(键或索引) 用于检索驾驶记录。该哈希列带有指示器用于判断哪一列 批处理应用实例处理该特定行。例如,如果 是三个要启动的批处理实例,'A' 的指示器标记一行 实例1处理,指示“B”标记实例2处理的行, 指示“C”标记实例3处理的行。
用于检索记录的程序还会有额外的哪里第
选择所有由特定指示标记的行。这张表中的插入件会
涉及添加标记字段,该字段默认为
实例(如“A”)。
使用简单的批处理应用来更新指示符,例如: 将负载重新分配到不同的实例之间。当数量足够多时 如果新增了行,该批次可以随时运行(除了在批处理窗口内)。 将新行重新分配到其他实例。
批处理应用的额外实例只需运行批处理 应用(如前述所述)将指示符重新分配为 处理更多实例。
4.2 数据库与应用设计原则
支持多分区应用程序的架构,这些应用运行于多个分区 分区数据库表并使用键列方法应包括中央 用于存储分区参数的分区仓库。这提供了灵活性和 确保可维护性。该仓库通常由一个表组成,称为 分区表。
分区表中存储的信息是静态的,通常应被维护 由DBA决定。该表应由每个分区的一行信息组成 多分区应用。表格应包含程序ID代码的列, 分区号(分区的逻辑ID),数据库键列的低值 分区,以及该分区数据库键列的高值。
项目启动时,项目身份证分区号应传递给
从架构中应用(具体来说,来自控制处理任务项)。如果
采用键列方法,这些变量用于读取分区表
以确定应用要处理的数据范围。此外,
分区号必须在整个处理过程中使用,以实现:
-
在输出文件中添加或数据库更新,这样合并过程才能正常工作 适当地。
-
将正常处理报告到批处理日志,将错误报告到架构错误 处理器。
4.3 最小化僵局
当应用程序并行运行或分区时,数据库资源争夺 而且可能会出现死锁。数据库设计团队必须消除这一点至关重要 尽可能多地处理潜在的争用情况,作为数据库设计的一部分。
此外,开发者必须确保数据库索引表的设计为 以防止死锁和性能为核心。
死锁或热点常出现在管理表或架构表中,如日志表 表、控制表和锁表。这些影响应被纳入考量 账号也一样。现实的压力测试对于识别可能的压力至关重要 架构中的瓶颈。
为了最大限度地减少冲突对数据的影响,架构应提供服务 (例如等待重试间隔)在附加数据库或遇到 僵局。这意味着内置机制以响应某些数据库返回码, 与其立即报错,不如等待预定的时间,并且 重新尝试数据库作。
4.4 参数传递与验证
分区架构应对应用开发者相对透明。 该架构应执行所有与运行应用程序相关的任务 分区模式,包括:
-
在应用程序启动前获取分区参数。
-
在应用程序启动前验证分区参数。
-
启动时将参数传递给应用程序。
验证应包括检查以确保:
-
应用程序拥有足够的分区来覆盖整个数据范围。
-
分区之间没有间隙。
如果数据库被分区,可能需要额外的验证以确保 单个分区不跨越数据库分区。
此外,架构应考虑分区的合并。 关键问题包括:
-
所有分区都必须完成后才能进入下一个工作步骤吗?
-
如果其中一个分区中止会发生什么?