RESTful API 是一种常用的 Web API 设计方式,可以使不同系统之间的数据交换更方便和可靠。然而,当涉及到多个系统之间的复杂业务流程时,会出现分布式事务处理的问题。本文将探讨在 RESTful API 中如何处理分布式事务,并提供实用的解决方案和示例代码。
什么是分布式事务
分布式事务是指跨越多个系统或服务的事务,分布式事务中的每个系统或服务都有自己的本地事务,当系统之间需要协调一起完成一个全局事务时,就需要进行分布式事务处理。
在传统的单一数据库事务中,所有的操作都在同一个数据库里执行,因此能够保证事务的原子性、一致性、隔离性和持久性(ACID);但在分布式系统中,对于同一事务的操作可能分布在不同的系统中执行,使得保证事务 ACID 属性变得更加复杂。因此,需要采用特定的协调机制来解决分布式事务问题。
分布式事务处理方法
在 RESTful API 中,分布式事务处理可以采用两种方式来实现:使用两阶段提交(2PC)协议或使用补偿事务(AT)机制。
两阶段提交协议
两阶段提交是一种基于协调者和参与者之间协作的分布式事务处理机制,它可以在所有参与者都就绪后一起提交,保证了全局事务的一致性和完成性。
在该协议中,当一个事务需要被提交时,有一台机器充当协调者的角色,向所有参与者发出“准备提交(Prepare)”请求。每个参与者本地执行其本地事务,并保存提交前的状态,并向协调者发送“已经准备就绪(Ready)”信号。所有参与者准备就绪后,协调者向所有参与者发送“提交(Commit)”请求,参与者在本地执行提交操作,并向协调者发送“已提交(Committed)”信号。最后,协调者在收到所有参与者的“已提交(Committed)”信号后返回“提交成功(Success)”信号。
该方法虽然能保证全局事务的 ACID 属性,但其操作过程需要多次网络通讯和持久化操作,导致性能较差,且存在单点故障问题。
补偿事务机制
补偿事务机制是另一种常用的分布式事务处理机制,它通过在每个参与者上执行“前向工作(Try)”和“后向工作(Confirm)”两个操作,来保证分布式事务的一致性和完成性。
在该机制中,当一个事务需要被提交时,协调者向所有参与者发送“前向工作(Try)”请求,每个参与者本地执行“前向工作”,并保存其执行状态。如果所有参与者都成功执行了前向工作,则协调者向所有参与者发送“正式提交(Confirm)”信号,所有参与者继续执行“后向工作”并向协调者报告其执行状态,协调者在收到所有参与者的“确认提交(Confirm)”信号后返回“提交成功(Success)”信号。如果在“前向工作”或“后向工作”中发生错误,则需要执行相应的“补偿操作(Cancel)”,撤销前向工作所产生的影响。最终达到在每个参与者上都可以执行本地事务的效果,从而解决了分布式事务问题。
补偿事务机制相对于 2PC 协议的优势在于,执行过程中不需要多次网络通讯和持久化操作,性能更好,而且操作过程中不存在单点故障问题。
应用示例
下面是一个实际应用的示例,使用了 Spring Boot、Spring Cloud、MyBatis 等框架来演示 RESTful API 中的分布式事务处理。
假设一个电商网站,需要下单时扣减库存,同时生成订单。订单系统和库存系统部署在不同的服务器上,通过调用 RESTful API 来协调执行全局事务。
- 创建订单 Service
在订单系统中,我们定义了一个创建订单 Service,代码如下:
-- -------------------- ---- ------- -------- ------ ----- ------------ - ---------- ------- ----------- ------------ --- - ---- ------- -- -------------------------- - ---------------- ------ ---- ----------------- ------ ------ --------- - -- ---- ------------------------------- -- ---- ----------------- ---------- - --- -------------------- ------------ ------------ - --- --------------- ---------------------- -------------- - --------------------------------------------------------------- --------------- ----------- -------------- -- ------------------------------- -- -------------- - ----- --- ----------------- -- ------ ------------ - - -
在创建订单时,我们先调用订单系统的 createOrder 方法生成订单,然后使用 RESTful API 调用库存系统的接口扣减库存。当库存系统返回错误时,我们使用异常机制通过注解 @Transactional 表示当前 Service 方法需要参与到分布式事务中。
- 扣减库存控制器
在库存系统中,我们定义了一个扣减库存控制器,代码如下:
-- -------------------- ---- ------- --------------- --------------------------------- ------ ----- ------------------- - ---------- ------- --------------- ---------------- --- - ---- --- -- ----------- ------ ---------------------- ---------------------------- ----- ------ - --------- --------- - --------------------------------------------------- -- ---------- -- ---- -- -------------------- - -------------------- - ------ ------------------------------------------------------------- -- --- --------- - --------------------------------------- - --------------------- ------------------------------------------- ------ ---------------------------- ------- --------------- - -
在该控制器中,我们接收到订单系统的扣减库存请求,查询出商品对应的库存量,如果库存不足,则返回错误信息;否则继续减去库存量,并保存到库存数据库中。如果保存出错,则会抛出异常,从而保证了事务的回滚。
结论
在 RESTful API 中,分布式事务处理是一项非常重要的技术。本文介绍了两种处理方式:2PC 协议和补偿事务机制,并提供了实用的示例代码。在实际应用中,我们需要根据系统架构和业务需求,综合考虑性能和可靠性等因素,选择适合自己系统的分布式事务处理方式。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6747d3d75883fc5ebfe4a03d