门户网站建设方案舟山网站建设

北京淞争子青科技有限公司 2026/09/09 17:54:47

我们在开发的过程中,如果一个业务操作需要本地写MYSQL数据以及对第三方系统做写操作,那么这种流程就涉及到分布式系统一致性的问题,然而并非所有系统都能使用成熟的分布式事务方案

PS:示例代码推送到:

https://gitee.com/dailycreatebug/demo-codes

案例说明

以一个财务报账业务为例,涉及到的系统如下:

系统名

作用

实现方案

单据系统

申请单内容以及凭证的生成

JAVA

BPM

实现流程的运转

购买成熟系统(例如:泛微)

SAP

财务凭证

购买成熟系统

详细解释下各系统作用:

  • 单据系统:财务报账,会提交很多信息(例如:报账事由、报账金额与明细)。同时也会生成财务凭证(不了解凭证也没关系,它就是给财务人员看的东西,对技术人员来说就是数据库的一堆数据)

  • BPM系统:非常成熟的流程管理系统,以非常直观的方式来实现流程的搭配,不了解的可以自行百度扫盲。在此案例中,需要使用BPM的两个能力:1)调用API,审核通过 2)调用API,获取流程的待审人

  • SAP系统:财务专用系统,不用过多了解,只要知道在财务审核完成后,会将单据系统生成的凭证数据通过API调用的方式发送给SAP即可

“审核通过”业务流程

当审核人员审核通过时,大致流程如下:

  • 保存业务数据+记录审核日志

  • 调用BPM接口,审核通过

  • 调用BPM接口,获取最新待审人

  • 如果没有待审人,说明已经审完,生成凭证并推送SAP

代码如下

风险分析

如图所示,如果在1和2出现异常,由于有事务的存在,操作1内的几条mysql写操作会被回滚,因此所有数据都没有任何变化。

但如果1和2正常执行,操作3发生异常,操作1的数据会因为事务回滚,但操作2并不能。因此整个系统会出现一个很诡异的现象:单据系统内,没有任何日志记录,用户操作的数据也没有保留下来,但BPM那边却已经审核通过了,这在任何正常流程中,都是不可能出现的状态。

对于用户而言,他在页面会收到报错,然后可能会再次点击“审核通过”,而此时BPM那边却显示,流程已经走到下一个节点,该用户无权限操作。

问题分析

根本原因其实不难,因为MYSQL事务只能管他自己,没法控制第三方系统

解决思路

一个字:拆!

对于分布式系统,没有任何人能保证远程调用不出问题,因此在做设计时,就必须能够对这种情况做出应对

上面的操作,打包放进一个大事务就是根因,因此方案就是将大事务拆开,在拆分时,需要遵循以下几个原则:

  • 小事务内,尽量只有一个远程写操作

  • 该远程写操作放到方法最后,保证在其返回成功后就能立刻提交事务

  • 小事务可能会因为某些原因失败,因此需要机制来进行重试

整体思路就是这样

基于以上原则,改动如下

第一步,新建一张任务表:

CREATETABLE`transaction_job` ( `id`bigint(20) NOTNULL AUTO_INCREMENT COMMENT'主键', `type`varchar(255) NOTNULLCOMMENT'任务类型', `data`varchar(255) NOTNULLCOMMENT'任务数据', `error_message`varchar(255) DEFAULTNULLCOMMENT'错误信息', `context`varchar(255) DEFAULTNULLCOMMENT'任务上下文(主要是保存当前操作人)', `create_time`bigint(20) NOTNULLCOMMENT'创建时间', `update_time`bigint(20) NOTNULLCOMMENT'更新时间', `retry_times`int(11) NOTNULLDEFAULT'0'COMMENT'重试次数', PRIMARY KEY (`id`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='事务任务表';

作用:保存小事务的关键数据到data字段中,以保证通过该字段,就能正确执行小事务。另外也需要保存当前操作人的信息context。

第二步,通过定时任务,查出transaction_job表中未完成的数据,并执行对应的操作,这里通过简单的策略模式,将框架代码和业务代码做了分离

首先是框架代码核心逻辑

扫描任务

执行任务

这是一个策略模式接口,每个小事务就封装一个独立的实现类

其中更新待审人的任务实现如下,其实就是把那部分代码复制过来

第三步,改造业务代码,不再一次性把流程写完,而且是在第一个小事务中,顺便往transaction_job中插入一条数据,以执行第二个小事务

其中步骤2(插入任务数据的代码)的具体实现如下(transactionJobService.create)

优化

上述方案种,除第一个事务外,后续事务都是通过定时任务来执行的,因此这些事务都存在一定的延迟,用户体验不好,解决办法也非常简单,只需要利用好Spring对于事务的生命周期管理,稍微改造一下插入任务的方法(transactionJobService.create

这是Spring提供的工具类,afterCommit()方法会在事务提交后执行,因此加上这段代码后,思路就变成了这样

如果小事务顺利执行,会立刻将该任务改为“成功”,因此从用户端是感受不到延迟的

注意

可能存在添加任务后,定时任务也立刻扫描到了这条数据,同一任务就会被主线程与定时任务线程同时执行,所以实际应用中需要考虑这个问题(比如:加锁再执行,执行前再检查数据库状态)

结语

目前只给出了解决思路的核心,但真实项目中,还添加了不少额外功能,以后会逐渐更新进来

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

网站建设与管理网站建设报告

防逆冲MOS零件的核心作用是构建一种智能单向导通机制,在电源输入端实现反接保护和反向电流阻断,同时最大限度降低正常导通时的功率损耗。其工作原理基于MOS管导通电阻可低至毫欧

2026/06/30 11:39:57

网站建设论坛网站建设市场

CircuitJS1 Desktop Mod完全攻略:从零开始掌握电路仿真艺术【免费下载链接】circuitjs1Standalone (offline) version of the

2026/06/30 12:04:59

深圳营销型网站建设郑州网站建设公司

从“哑设备”到智能终端:工业4.0时代蜂鸣器电路的进化之路在智能制造的宏大叙事中,人们常常聚焦于机器人、数字孪生、AI质检等高光技术。然而,在产线轰鸣的背后&

2026/06/30 10:51:22

青岛网站建设深圳外贸网站建设

你是否曾经在深夜调试Pydantic AI项目时,被一个看似简单的问题折磨得焦头烂额?MCP服务器启动时环境变量神秘消失,API密钥不翼而飞,配

2026/06/30 13:13:05

网站建设与管理长安网站建设

游戏控制器兼容性问题是许多PC玩家的困扰,特别是当你的DirectInput设备无法在只支持XInput的游戏中正常使用时。XOutput作为一款小巧的DirectInput到XInpu

2026/06/30 10:59:53

郑州网站建设公司银川网站建设

当算法能力需要硬件承载,一块精心设计的开发板正成为无人机自主智能的关键基石在无人机自主飞行技术蓬勃发展的今天,算法创新与硬件支撑的深度融合正成为行业突破的关键。Deepoc

2026/06/30 12:12:29

湖州网站建设柳州网站建设

早期涉足游戏开发时,曾执着于浮点精度的极致提升,认为更高的精度就能消除所有差异,直到在一款多人协作游戏的测试中,见证过同一技能在PC端与移动端的伤害结算偏差、主机玩家与手机玩家看到的角色跳跃轨迹分歧—

2026/06/30 13:35:36

广东网站建设福田网站建设

Excalidraw动画功能探索:让静态图表动起来在技术分享或产品评审会上,你是否曾遇到这样的尴尬——精心绘制的架构图刚展示一半,同事就问:“这

2026/06/30 12:29:31

淮安网站建设塘沽网站建设

FLAC高清音频也可用!HeyGem对高质量音源有良好适配在数字内容创作的浪潮中,虚拟主播、AI讲师和智能客服正逐渐从“能说话”迈向“说得好”。过去,许多AI

2026/06/30 13:26:35

大型门户网站建设asp网站建设

Excalidraw AI助力中小企业降本增效案例在远程办公常态化、产品迭代周期不断压缩的今天,许多中小企业正面临一个看似微小却影响深远的问题:如何让“想法”更快地变成团队

2026/06/30 12:47:33