技术分享-企业分布式架构设计之分布式事务案例
Posted 得帆信息
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技术分享-企业分布式架构设计之分布式事务案例相关的知识,希望对你有一定的参考价值。
1、本地消息表(异步确保)
1.1、特点
本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证 最终一致性。
-
在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。 -
之后将本地消息表中的消息转发到 Kafka 等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。“消息队列” 可以用 “轮询程序” 替代,目的是可以通过不断重试,保障事务最终执行成功。 -
在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。该操作必须都是满足 幂等性 的,幂等性是指同一个操作无论请求多少次,其结果都相同。
1.2、案例
-
调用A系统的接口,完成事务A。 -
调用B系统的接口,完成事务B。 -
调用C系统的接口,完成事务C。
1.3、步骤
-
(本地订单表)即主业务系统的业务表,有唯一标识的“业务流水号”。 -
(本地消息表)主业务系统流程流转时,本地消息表中分别写入需要执行A系统、B系统、C系统3个不同事务的3条消息,消息的状态为【处理中】。由于都是在同一本地数据库,可保证事务一致性。 (事务A)A系统有”处理事务A的接口”,该接口保障幂等性。通过 “轮询程序” 遍历所有【处理中】状态下A事务的消息调接口,事务完成后修改消息状态;或通过 “消息队列”,保障事务最终被成功执行后消费消息。
3.1. 针对该“业务流水号”,如果A系统中未处理,则处理该事务,并更新A系统消息的状态为【已处理】。 3.2. 针对该“业务流水号”,如果A系统中已处理,则不处理该事务。 3.3. 假设:A系统是某sap系统,需要将某”业务流水号“对应的物料数量“加一”,当前物料数量基础数量是5。”处理事务A的接口”即是sap系统开发并提供的接口,该sap接口判断,如果并未处理该“业务流水号”的事务,则将物料基础数量更新为6;如果已处理过该“业务流水号”的事务,则物料基础数量不变。因为“幂等性”,不会导致每次调接口都会往上“加一”。 -
(事务B)B系统和A系统处理机制类似。 -
(事务C)C系统和A系统处理机制类似。 -
(本地订单表+本地消息表)通过轮询程序,或通过A/B/C每个消息的回调通知,触发调用一个同样幂等的方法。该方法判断该“业务流水号”在本地消息表中A、B、C事务的3条消息,是否状态都为【已处理】。如果都是【已处理】,则更新本地订单表中“业务流水号”状态,流程翻转成功。由于都是在同一本地数据库,可保证事务一致性。
2、微信支付JSAPI(异步确保)
2.1、特点
-
(API)统一下订单接口。 -
(异步SDK)用户在微信客户端上支付该订单(密码支付/指纹支付/人脸识别/等等)。 -
(API)用户异步支付成功后,触发回调接口,通知商户号。 -
(API)查询订单状态接口。
2.2、案例
-
在充值系统中,充值的金额增加到饭卡余额中。 -
在账单系统中,记录充值/消费记录。 -
在通知系统中,推送充值成功的消息(app内通知/短信通知)。
2.3、步骤
-
(本地订单表)用户输入金额,充值。后台调【微信统一下单接口】生成微信支付订单,接口返回成功后,在本地订单表中创建订单记录,状态为【支付中】。 -
前端异步回调,微信小程序拉起微信SDK组件,用户开始支付。 -
(事务P+本地消息表)提供【微信支付成功回调接口】,该接口支持幂等性-如果查询微信订单状态已支付,且本地消息表中无事务处理消息,则执行。执行操作为,在本地消息表中分别写入需要执行A、B、C3个不同事务的3条消息,消息的状态为【处理中】。 3.1. 将执行事务P的【微信支付成功回调接口】配置在微信下单的接口中,在异步支付成功后调用该接口。如果未收到成功反馈,微信官方会重发回调方法,但是有重发的次数限制。 3.2. “轮询程序”或“消息队列”,两种方案来处理未成功执行了的事务P。重试调用【微信支付成功回调接口】,直到成功支付了的订单,都能将A、B、C3个不同事务的3条消息写入本地消息表。 -
(事务P 轮询)轮询程序遍历本地订单表中【支付中】的订单,通过【微信订单查询接口】查询订单状态:
4.1、如果订单已支付,则说明【微信支付成功回调接口】未触发,或其他原因导致的事务异常。自动调用(事务B)中【微信支付成功回调接口】。
4.2、如果订单未支付,且未到取消订单的超时时间,则不处理订单。
4.3、如果订单未支付,且超过取消订单的超时时间,更新订单状态为【已作废】。 -
(事务A)充值系统中提供该接口,有幂等性。针对该唯一标识等订单流水号,如果已经在账户中完成对应充值的余额更新,则不处理,否则更新账户余额。并更新消息表中对应的消息状态为【已处理】。 -
(事务B)账单系统中提供该接口,有幂等性。针对该唯一标识等订单流水号,如果已经在账单中已记录该次充值的账单记录,则不处理,否则记录该次充值的账单记录。并更新消息表中对应的消息状态为【已处理】。 -
(事务C)通知系统中提供该接口,有幂等性。针对该唯一标识等订单流水号,如果已经在通知系统中已发送该次充值的消息,则不处理,否则发送该次充值的消息。并更新消息表中对应的消息状态为【已处理】。 -
(本地订单表+本地消息表)通过轮询程序,或通过A/B/C每个消息的回调通知,触发调用一个同样幂等的方法。该方法判断该“业务流水号”在本地消息表中A、B、C事务的3条消息,是否状态都为【已处理】。如果都是【已处理】,则更新本地订单表中“业务流水号”状态,流程翻转成功。由于都是在同一本地数据库,可保证事务一致性。
2.4、对比
差别体现在,如何将 “主业务流程触发” 和 “将A、B、C事务的3个消息写入消息中间表” 这两步操作作为一个事务,并保证它的原子性。
-
案例一:“主业务流程流转”,和“将A、B、C事务的3个消息写入消息中间表”,都是在同一个数据库下的操作,可以直接使用数据库的事务实现。 -
案例二:“主业务流程触发”实际对应的是“微信支付成功”,这个是由微信支付官方平台提供的异步触发事务,而“将A、B、C事务的3个消息写入消息中间表”则是本地数据库事务。二者本身已经是分布式事务处理了。所以引入了 “事务P”, 并提供 “执行事务P的幂等性接口”。 通过轮询或消息队列来监听本地订单表,通过不断重试该幂等性接口,保证事务的原子性。
3、商品抢购(TCC补偿)
3.1、特点
-
先是服务调用链路依次执行 Try 逻辑。 -
如果都正常的话,TCC 分布式事务框架推进执行 Confirm 逻辑,完成整个事务。 -
如果某个服务的 Try 逻辑有问题,TCC 分布式事务框架感知到之后就会推进执行各个服务的 Cancel 逻辑,撤销之前执行的各种操作。
-
某个服务的数据库宕机了。 -
某个服务自己挂了。 -
那个服务的 Redis、Elasticsearch、MQ 等基础设施故障了。 -
某些资源不足了,比如说库存不够这些。
接着,再执行各个服务的 Confirm 逻辑,基本上 Confirm 就可以很大概率保证一个分布式事务的完成了。
此时就自动执行各个服务的 Cancel 逻辑,把之前的 Try 逻辑都回滚,所有服务都不要执行任何设计的业务逻辑。保证大家要么一起成功,要么一起失败。
-
完成所有业务检查(一致性) -
预留必须业务资源(准隔离性)
-
真正执行业务 -
不作任何业务检查 -
只使用Try阶段预留的业务资源 -
Confirm操作满足幂等性
-
释放Try阶段预留的业务资源 -
Cancel操作满足幂等性
3.2、案例
-
商品系统:检查当前库存是否足够,如足够,则减去2份商品。 -
用户系统:检查余额是否足够,如足够,则扣除相应金额。 -
订单系统:检查是否满足创建订单条件,如满足,则创建订单。
3.3、步骤
3.3.1. Try
-
(事务A-商品)用户A抢购2份。检查库存数量是否大于2,如果库存充足则继续进行。更新库存表中库存数量为98,冻结数量为2。 -
(事务B-用户)用户A账户余额50元,购买商品需2元。检查余额是否大于2元,如果余额充足则继续进行。更新余额为48元,冻结2元。 -
(事务C-订单)用户A购买商品需创建订单。检查是否满足创建订单条件,如果可以则继续进行。创建订单,但该订单状态为【未生效】。
3.3.2. Confirm
-
(商品)更新冻结数量2为0。 -
(用户)更新冻结2元为0. -
(订单)更新订单状态为【有效】。
3.3.3. Cancel:
关于得帆
上海得帆信息技术有限公司(简称:得帆信息),公司注册在上海张江高科技园区,经过创始团队10年的经营发展,得帆信息已经成为中国在企业级中间件(ESB,Portal,BPM,微服务)和中间件云产品领域人员规模大、服务范围广、客户群体多的IT咨询服务公司之一。
经过10年的砥砺前行,拥有超过300+的大中型客户,实施超过1000+的中间件项目,每年收入50%以上来源于老客户,成为当之无愧的中间件技术服务领导者,用口碑和技术实力践行了得帆的使命“用信息技术帮助客户幸福和成功”。
得帆信息的服务领域包括企业级中台系统咨询和实施、ESB信息系统集成、BPM业务流程系统实施、企业集团全球官网实施、企业内网门户及身份管理实施、大数据规划和实施等服务,为推动客户在数字化,互联网+和工业4.0转型提供专业的信息化支撑和保障。
以上是关于技术分享-企业分布式架构设计之分布式事务案例的主要内容,如果未能解决你的问题,请参考以下文章
分布式技术专题「架构实践于案例分析」总结和盘点目前常用分布式事务特别及问题分析(下)
几年的架构师生涯,掏心掏肺分享在分布式“刚性事务和柔性事务”中思维逻辑!
阿里P9:做了 6 年架构设计,这次聊聊微服务与分布式事务细节