You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在联机事务中配置Spring Batch分块处理并解决同步冲突

批处理与联机工作流的同步一致性解决方案

业务场景

系统同时运行两类核心流程:

  • 批处理作业:检索未处理文档,通过分块事务将其标记为已处理(分块设计为满足性能与可靠性要求)
  • 联机工作流:收到人员离世消息时,需查找并删除该人员的所有未处理文档

两类流程运行时会出现一致性冲突问题,具体如下:

核心冲突问题

问题1:读取未提交的处理中文档

其他进程可能读取到批处理作业正在处理但尚未提交事务的文档。

现有缓解思路:两端使用写锁——文档在未提交事务中处理时,其他事务查询这些行会被阻塞,直到首个事务提交。

问题2:分块间隙的结果不一致

即便启用行锁,仍存在问题:其他进程可能查询到尚未处理、但即将被当前运行的批处理作业处理的文档。由于分块是随机排序,这个问题很难直接缓解。

现有方案弊端:若在批处理运行期间阻塞所有人员离世处理流程,会出现批处理未处理目标人员文档时的响应时间浪费。

推荐的同步模式与最佳实践

以下方案可在保证绝对一致性的前提下,尽可能提升响应速度:

1. 状态标记+原子更新锁

给文档添加status字段(可选值:unprocessed/processing/processed),配合原子性更新操作实现锁机制:

  • 批处理分块启动时,通过原子SQL将目标文档的status从unprocessed更新为processing,例如:
    UPDATE documents 
    SET status = 'processing', locked_at = NOW() 
    WHERE status = 'unprocessed' 
    LIMIT 1000; -- 分块大小
    
  • 联机工作流查询未处理文档时,仅筛选status = 'unprocessed'的记录,避免读取正在处理的文档
  • 批处理完成分块处理后,将status更新为processed并提交事务;若处理失败,回滚并将status重置为unprocessed

这种方式无需全表锁,仅锁定当前处理的分块数据,联机流程能快速获取真正未被处理的文档,避免无意义阻塞。

2. 分区隔离+优先级调度

按人员ID或文档ID做逻辑分区,缩小锁的作用范围:

  • 批处理作业按分区依次处理,每个分区处理时对该分区加排他锁
  • 联机工作流处理人员离世消息时,先检查目标人员所属分区的锁状态:
    • 若分区未被锁定,直接查询并删除该分区内的未处理文档
    • 若分区已被锁定,根据预设优先级,要么短暂等待锁释放,要么触发批处理作业优先处理该分区的文档(需批处理支持优先级调度)

该方案通过分区最小化锁冲突,同时利用优先级调度减少联机流程的等待时间。

3. 事务级别的范围锁+过滤条件

针对联机流程的查询逻辑,添加事务级别的范围锁与过滤条件:

  • 联机工作流启动事务后,先对目标人员的文档范围加共享锁:
    SELECT * FROM documents 
    WHERE user_id = '目标ID' AND status = 'unprocessed' 
    FOR SHARE;
    
  • 批处理作业处理文档时,同样先对要处理的分块加排他锁,且仅处理status = 'unprocessed'的文档
  • 这种锁机制下,若联机流程先获取了共享锁,批处理会等待联机流程完成删除后再处理;反之,联机流程会等待批处理完成后再查询,保证绝对一致性

内容的提问来源于stack exchange,提问作者Tuomas Toivonen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 16:07:26