3. 错误类型分类:业务错误、系统错误与数据一致性错误

在审批流骨架事务补偿设计中,错误并非铁板一块。不同错误类型对事务边界、补偿策略和恢复路径的要求截然不同。将错误精确分类,是设计补偿动作的前提——只有知道“错在哪一层”,才能决定“补偿到哪一步”。

3.1 错误分类全景

从企业级分布式系统的视角,审批流中的错误可归纳为三大类:业务错误、系统错误和数据一致性错误。三者对事务的影响范围、可预测性和补偿复杂度依次递增。

错误类别 典型场景 可预测性 补偿策略 事务影响范围
业务错误 驳回、超时、审批人拒绝 高(业务规则可枚举) 正向回滚 + 状态回退 单流程实例
系统错误 宕机、网络分区、服务熔断 低(基础设施不可控) 幂等重试 + 状态持久化 跨服务、跨节点
数据一致性错误 脏读、幻读、写偏序 中(并发时序导致) 补偿事务 + 版本校验 跨资源、跨库
设计原则:业务错误优先用“状态机回退”解决;系统错误优先用“幂等+重试”兜底;数据一致性错误必须引入“补偿事务+乐观锁”双重保障。三种策略不可混用,否则补偿逻辑会陷入无限循环。

3.2 业务错误:驳回与超时

业务错误是审批流中最常见、最可控的错误类型。它们由业务规则触发,错误语义明确,补偿路径清晰。

  • 驳回(Rejection):审批人主动拒绝当前申请。补偿动作:将流程实例回退到上一审批节点,释放已占用的资源预留(如预算锁定、库存预占),并触发通知。
  • 超时(Timeout):审批人在规定时限内未做出响应。补偿动作:自动升级审批人、转交或按预设规则执行默认动作(如自动驳回)。超时补偿需要与业务SLA对齐。
  • 审批人拒绝(Decline):与驳回类似,但通常伴随原因说明。补偿动作:记录拒绝原因,回退状态,并允许申请人修改后重新提交。
关键指标:业务错误的补偿成功率应达到 99.9% 以上。如果补偿失败,通常是状态机设计缺陷——例如未记录前驱状态,导致无法回退。

3.3 系统错误:宕机与网络分区

系统错误是分布式系统的“常态”。它们不可预测,但可以通过架构设计降低影响。审批流作为企业业务骨架,必须对系统错误具备弹性。

  • 宕机(Crash):审批服务节点、数据库或消息队列不可用。补偿策略:本地状态持久化 + 服务重启后自动恢复未完成流程。关键设计:事务日志必须落盘,且恢复过程幂等。
  • 网络分区(Network Partition):服务间通信中断,导致审批状态无法同步。补偿策略:引入“超时+重试”机制,配合断路器防止级联故障。网络恢复后,通过补偿任务对齐状态。
  • 服务熔断(Circuit Breaker):下游依赖服务响应过慢或错误率过高。补偿策略:快速失败,将流程实例标记为“待补偿”,由后台调度器异步重试。
避坑提示:系统错误补偿最忌讳“无限重试”。必须设置最大重试次数和退避策略(如指数退避)。超过阈值后,应转入人工处理队列,避免资源耗尽。

3.4 数据一致性错误:脏读与幻读

数据一致性错误是分布式事务中最隐蔽、最难排查的错误。它们通常发生在并发访问同一资源时,导致审批流状态与真实业务状态不一致。

错误类型 定义 审批流场景 补偿方案
脏读 读取到未提交的中间状态数据 审批人A读取到审批人B尚未提交的“已通过”标记,做出错误决策 引入版本号或乐观锁,禁止读取未提交状态
幻读 同一查询在事务内返回不同结果集 审批流统计“待办数量”时,因并发插入新实例导致计数不一致 使用可重复读隔离级别,或通过补偿事务重新统计
写偏序 两个事务基于同一快照做出决策,导致最终状态冲突 两个审批人同时“通过”同一流程的不同版本,导致状态分裂 引入分布式锁或CAS(Compare-And-Swap)机制
最佳实践:在审批流核心状态变更点(如“通过”、“驳回”、“转交”)强制使用乐观锁(version 字段)。每次更新时校验 version,若不一致则回滚并提示冲突。这是防止幻读和写偏序的最轻量方案。

3.5 错误分类与补偿策略映射

将三类错误与补偿策略进行映射,形成可执行的决策矩阵。这是骨架事务补偿设计的核心参考。

错误类型 → 补偿策略映射 业务错误 驳回 / 超时 / 拒绝 系统错误 宕机 / 网络分区 / 熔断 数据一致性错误 脏读 / 幻读 / 写偏序 状态机回退 记录前驱状态 + 资源释放 幂等重试 + 状态持久化 指数退避 + 最大重试阈值 补偿事务 + 版本校验 乐观锁 + CAS 机制 补偿策略选择原则 业务错误 → 状态机回退(确定性高) 系统错误 → 幂等重试(弹性兜底) 数据一致性错误 → 补偿事务 + 版本校验(防冲突) 核心结论 错误分类越精确,补偿动作越轻量。不要用“系统错误”的补偿策略去处理“业务错误”,反之亦然。 三类错误在同一个审批流实例中可能叠加出现,补偿设计必须分层、可组合。

3.6 错误分类在补偿设计中的落地要点

  1. 错误分类必须显式编码:在错误日志和补偿事件中携带 error_category 字段(如 BUSINESS、SYSTEM、CONSISTENCY),便于补偿调度器选择正确的处理策略。
  2. 业务错误优先本地补偿:不依赖分布式协调,直接在流程引擎内部完成状态回退,延迟最低。
  3. 系统错误必须幂等:所有补偿操作(如释放资源、回退状态)必须支持重复执行,且结果一致。
  4. 数据一致性错误需要全局视角:引入分布式事务协调器(如 Saga 或 TCC),确保跨服务状态最终一致。
  5. 错误分类是动态的:同一个异常(如数据库连接超时)在不同上下文可能被归类为系统错误或数据一致性错误。设计时需保留重分类能力。
工程建议:在代码中为每个补偿操作定义 compensate() 方法,并显式标注其处理的错误类型。例如:@Compensates(errorCategory = "BUSINESS")。这能让补偿链路在运行时自检,避免错误策略误匹配。