网站开发工程师简历,网站建设后期服务协议,wordpress去除标签层级,企业网站设计与实现微服务设计模式 — 补偿事务模式#xff08;Compensating Transaction Pattern#xff09; 定义
在云计算和分布式系统中#xff0c;管理跨多个微服务或组件的事务一致性是一项极具挑战性的任务#xff0c;补偿事务模式Compensating Transaction Pattern#xff09;是一种…微服务设计模式 — 补偿事务模式Compensating Transaction Pattern 定义
在云计算和分布式系统中管理跨多个微服务或组件的事务一致性是一项极具挑战性的任务补偿事务模式Compensating Transaction Pattern是一种允许在分布式系统中处理长时间运行的跨多个服务的事务一致性的方法。在执行主要事务步骤时系统记录每个步骤的补偿操作即回滚操作以便在事务失败时可以撤销已执行的操作。简而言之补偿事务通过逆向操作来确保系统达到一致性状态。
结构
补偿事务模式通常由以下几个部分组成 主事务主要事务逻辑包含一系列需要执行的业务步骤。 补偿操作用于撤销主事务中的某个步骤如果该步骤失败则触发补偿操作。 事务管理器负责协调事务步骤和补偿步骤的执行。
工作原理
补偿事务的工作原理如下
执行主事务步骤按照预定的业务逻辑依次执行每个操作步骤。记录补偿操作在每个步骤成功后记录对应的补偿操作以备将来可能的回滚。检测失败在每个步骤执行期间检测到失败时立即执行已记录的补偿操作撤销此前已完成的步骤。成功完成所有步骤成功后事务完成否则执行完整的补偿逻辑确保系统状态回滚至初始状态。
好处 高可用性即使某些服务暂时不可用补偿事务模式也能确保其他步骤的事务完成并且系统保持一致性。 灵活性补偿操作提供了更多的控制和灵活性可以根据业务逻辑定制补偿步骤。 低耦合性通过分离主事务和补偿事务可以降低服务之间的耦合性。 更好的性能相比于两阶段提交补偿事务模式更高效不需要在所有资源上保持锁定更适用于需要灵活性和容忍短暂不一致性的分布式系统而两阶段提交则适用于需要强一致性和事务原子性的关键性场景。
应用场景
在微服务架构中补偿事务模式广泛用于确保跨多个服务的长时间运行操作之间的一致性。以下是一些常见的应用场景
订单处理系统处理跨多个服务的订单如支付、库存扣减和物流等步骤。银行转账系统处理跨多个银行账户的转账操作如扣款、汇入和通知等步骤。旅游预订系统处理酒店预订、航班预订和租车预订等多个步骤。
以订单处理系统为例演示如何使用补偿事务模式。假设订单处理系统提供如下服务
服务1支付服务服务2库存扣减服务服务3物流预订服务
每个服务分别执行其操作并在失败时触发补偿操作具体流程如下 #mermaid-svg-rsNrVhEtlduSIb3A {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rsNrVhEtlduSIb3A .error-icon{fill:#552222;}#mermaid-svg-rsNrVhEtlduSIb3A .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rsNrVhEtlduSIb3A .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rsNrVhEtlduSIb3A .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rsNrVhEtlduSIb3A .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rsNrVhEtlduSIb3A .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rsNrVhEtlduSIb3A .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rsNrVhEtlduSIb3A .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rsNrVhEtlduSIb3A .marker.cross{stroke:#333333;}#mermaid-svg-rsNrVhEtlduSIb3A svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rsNrVhEtlduSIb3A .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rsNrVhEtlduSIb3A .cluster-label text{fill:#333;}#mermaid-svg-rsNrVhEtlduSIb3A .cluster-label span{color:#333;}#mermaid-svg-rsNrVhEtlduSIb3A .label text,#mermaid-svg-rsNrVhEtlduSIb3A span{fill:#333;color:#333;}#mermaid-svg-rsNrVhEtlduSIb3A .node rect,#mermaid-svg-rsNrVhEtlduSIb3A .node circle,#mermaid-svg-rsNrVhEtlduSIb3A .node ellipse,#mermaid-svg-rsNrVhEtlduSIb3A .node polygon,#mermaid-svg-rsNrVhEtlduSIb3A .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rsNrVhEtlduSIb3A .node .label{text-align:center;}#mermaid-svg-rsNrVhEtlduSIb3A .node.clickable{cursor:pointer;}#mermaid-svg-rsNrVhEtlduSIb3A .arrowheadPath{fill:#333333;}#mermaid-svg-rsNrVhEtlduSIb3A .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rsNrVhEtlduSIb3A .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rsNrVhEtlduSIb3A .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-rsNrVhEtlduSIb3A .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-rsNrVhEtlduSIb3A .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rsNrVhEtlduSIb3A .cluster text{fill:#333;}#mermaid-svg-rsNrVhEtlduSIb3A .cluster span{color:#333;}#mermaid-svg-rsNrVhEtlduSIb3A div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rsNrVhEtlduSIb3A :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 成功 成功 成功 失败 失败 失败 开始处理订单 执行支付操作 执行库存扣减 执行物流预订 订单处理成功 执行支付补偿 订单处理失败 执行库存补偿 执行物流补偿 示例代码
以下是一个简单的示例代码在 Spring Boot 中实现补偿事务并没有引入特别的事务补偿框架或者库。
项目结构
compensating-transaction/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── com/
│ │ │ │ ├── example/
│ │ │ │ │ ├── controller/
│ │ │ │ │ ├── service/
│ │ │ │ │ ├── model/
│ │ │ │ │ ├── repository/
│ │ │ │ │ ├── CompensatingTransactionApplication.java
│ ├── resources/
│ │ ├── application.properties配置文件
application.properties
spring.datasource.urljdbc:h2:mem:testdb
spring.datasource.driverClassNameorg.h2.Driver
spring.datasource.usernamesa
spring.datasource.passwordpassword
spring.jpa.database-platformorg.hibernate.dialect.H2Dialect主类
CompensatingTransactionApplication.java
package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication
public class CompensatingTransactionApplication {public static void main(String[] args) {SpringApplication.run(CompensatingTransactionApplication.class, args);}
}模型类
model/Order.java
package com.example.model;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;Entity
public class Order {IdGeneratedValue(strategy GenerationType.AUTO)private Long id;private String status;// Getters and setters
}仓储接口
repository/OrderRepository.java
package com.example.repository;import com.example.model.Order;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;Repository
public interface OrderRepository extends JpaRepositoryOrder, Long {
}服务类
service/OrderService.java
package com.example.service;import com.example.model.Order;
import com.example.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;Service
public class OrderService {Autowiredprivate OrderRepository orderRepository;Transactionalpublic void processOrder() {// 执行支付操作try {performPayment();} catch (Exception e) {performPaymentCompensation();return;}// 执行库存扣减try {performInventory();} catch (Exception e) {performInventoryCompensation();performPaymentCompensation();return;}// 执行物流预订try {performShipping();} catch (Exception e) {performShippingCompensation();performInventoryCompensation();performPaymentCompensation();return;}}private void performPayment() throws Exception {// 模拟支付操作Order order new Order();order.setStatus(PAYMENT_SUCCESS);orderRepository.save(order);// 如果支付失败抛出异常}private void performPaymentCompensation() {// 模拟支付补偿操作System.out.println(Payment compensation executed.);}private void performInventory() throws Exception {// 模拟库存扣减Order order new Order();order.setStatus(INVENTORY_SUCCESS);orderRepository.save(order);// 如果库存扣减失败抛出异常}private void performInventoryCompensation() {// 模拟库存扣减补偿操作System.out.println(Inventory compensation executed.);}private void performShipping() throws Exception {// 模拟物流预订Order order new Order();order.setStatus(SHIPPING_SUCCESS);orderRepository.save(order);// 如果物流预订失败抛出异常}private void performShippingCompensation() {// 模拟物流预订补偿操作System.out.println(Shipping compensation executed.);}
}控制器类
controller/OrderController.java
package com.example.controller;import com.example.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/orders)
public class OrderController {Autowiredprivate OrderService orderService;GetMapping(/process)public String processOrder() {orderService.processOrder();return Order processed.;}
}问题和考虑
以上代码只是理想情况下的一种的简化主要是借此来说明一下补偿机制的主要思想。尽管补偿事务模式提供了有效的方法保证分布式事务的一致性但是在设计和实现过程中仍然需要考虑以下问题 补偿逻辑的冗余需要为每个操作设定相应的补偿操作这可能增加代码的复杂性和维护成本。 不完全回滚不是所有业务操作都能被完全回滚设计补偿操作时需谨慎对待补偿事务不一定总是成功应该使补偿步骤具备幂等能力这样即使补偿事务失败也可以被安全地重复执行。 最终一致性补偿事务模式强调的是最终一致性而不是强一致性需要根据具体业务需求权衡。 补偿逻辑的专一性补偿逻辑难以通用化因为它是特定于应用程序的。应用程序需要足够的信息才能成功撤销失败操作的每一步。
在实际项目开发中一般需要有效地结合补偿事务模式和重试模式提高系统的可靠性并减少事务失败的影响。以下是一些具体的建议 优先使用重试模式 识别瞬态故障分辨出哪些故障是暂时性的如网络波动、暂时的资源不可用并优先对这些故障应用重试模式。设置重试策略配置合适的重试策略包括重试次数、重试间隔和指数退避等以确保重试时不会对系统造成过大负载。 设置明确的重试限度 重试次数限制为每个操作设置重试的最大次数。如果重试次数超过此限度则不再尝试重试转而启动补偿事务。超时机制设置合理的超时机制以防止操作长时间挂起。一旦触发超时系统应立即停止重试并启动补偿事务。 集成补偿事务模式 捕获所有重试失败确保所有重试失败的情况都会被准确捕获并且能有效地启动补偿事务。确保持久性记录每一步操作及其状态以便在重试多次失败后能够在补偿事务中撤销这些操作。 补偿事务步骤的幂等性 确保幂等性补偿事务的步骤必须是幂等的即使被多次执行也不会对系统状态产生额外影响。这确保如果补偿事务执行过程中出现故障可以安心地再次执行同样的补偿步骤。 设计良好的事务边界 明确的事务边界清晰地定义事务的开始和结束确保每个事务都是一个原子操作。尽量减少跨多个服务或数据存储的长事务减少事务失败的复杂度。 资源锁定和管理按需锁定资源并在补偿事务中优先释放资源以防止资源长时间被占用导致其他操作受阻。
总结 补偿事务模式是一种非常有效的方法用于处理分布式系统中长时间运行事务的一致性问题。通过在主事务执行失败时执行补偿操作系统能够恢复到一致性状态。尽管这一设计模式涉及较高的复杂性和代码冗余但其在保证系统一致性和稳定性方面的优势是不可忽视的。在实际应用中补偿事务模式广泛用于订单处理、银行转账等需要跨多个服务协调的业务场景。通过本文的示例希望读者能够更好地理解和应用补偿事务模式。