二、数据持久化篇(深度增强版)

news/2025/2/13 5:47:46/

二、数据持久化篇(深度增强版)

2.1 JDBC Template深度解析

架构设计思想
DataSource
JdbcTemplate
执行SQL
处理结果集
转换业务对象

设计模式解析

  1. 模板方法模式

    • 封装固定流程:获取连接→准备语句→执行→处理结果→释放资源
    • 开发者只需关注SQL和结果处理
  2. 回调机制

    • 通过RowMapper实现结果集到对象的映射
    • 使用PreparedStatementCreator定制语句创建

企业级查询优化

java">// 分页查询最佳实践
public Page<User> findUsersByPage(int pageNum, int pageSize) {String countSql = "SELECT COUNT(*) FROM users";int total = jdbcTemplate.queryForObject(countSql, Integer.class);String dataSql = "SELECT * FROM users LIMIT ? OFFSET ?";List<User> content = jdbcTemplate.query(dataSql,new Object[]{pageSize, (pageNum-1)*pageSize},new BeanPropertyRowMapper<>(User.class));return new Page<>(content, pageNum, pageSize, total);
}// 查询结果缓存方案
@Cacheable(value = "users", key = "#name")
public User findByName(String name) {return jdbcTemplate.queryForObject("SELECT * FROM users WHERE name = ?",new Object[]{name},new BeanPropertyRowMapper<>(User.class));
}

2.2 事务管理引擎(原理级解析)

事务传播机制本质
java">// 传播机制伪代码实现
public void executeWithTransaction(TransactionDefinition definition) {TransactionStatus status = null;try {// 判断当前是否存在事务boolean existingTransaction = isExistingTransaction();// 根据传播行为决定事务边界if (definition.getPropagationBehavior() == PROPAGATION_REQUIRED) {if (!existingTransaction) {status = startNewTransaction(definition);} else {status = participateInExistingTransaction();}}// 执行业务逻辑businessLogic();// 提交或回滚if (status != null && !status.isCompleted()) {commitTransaction(status);}} catch (Exception ex) {handleRollback(status, ex);throw ex;}
}

隔离级别对比表

隔离级别脏读不可重复读幻读性能影响
READ_UNCOMMITTED
READ_COMMITTED×
REPEATABLE_READ××较高
SERIALIZABLE×××

生产环境配置建议

spring:datasource:hikari:isolation-level: TRANSACTION_REPEATABLE_READjpa:properties:hibernate:connection:# 设置MySQL实际隔离级别isolation_level: 4  # 对应REPEATABLE_READ

2.3 MyBatis整合方案(原理与优化)

执行过程剖析
Mapper接口 SqlSession Executor StatementHandler JDBC 调用接口方法 获取Executor 创建StatementHandler 预编译SQL 返回结果集 结果处理 返回处理结果 返回业务对象 Mapper接口 SqlSession Executor StatementHandler JDBC

二级缓存优化策略

<!-- 启用二级缓存 -->
<settings><setting name="cacheEnabled" value="true"/>
</settings><!-- Mapper级别配置 -->
<mapper namespace="com.example.UserMapper"><cache eviction="LRU" flushInterval="60000"size="1024"readOnly="true"/>
</mapper>

插件开发实战

java">// SQL执行时间监控插件
@Intercepts({@Signature(type = Executor.class,method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class,method = "update",args = {MappedStatement.class, Object.class})
})
public class PerformanceInterceptor implements Interceptor {private static final Logger logger = LoggerFactory.getLogger(PerformanceInterceptor.class);@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];String sqlId = mappedStatement.getId();long start = System.currentTimeMillis();try {return invocation.proceed();} finally {long cost = System.currentTimeMillis() - start;logger.info("SQL [{}] 执行耗时: {}ms", sqlId, cost);Metrics.counter("sql_query_count").increment();Metrics.timer("sql_duration").record(cost, TimeUnit.MILLISECONDS);}}
}

扩展说明总结

  1. JDBC Template设计哲学

    • 通过模板方法消除样板代码
    • 分离资源管理与业务逻辑
    • 适合需要精细控制SQL的场景
  2. 事务管理的本质

    • 通过AOP实现声明式事务
    • 传播机制本质是事务上下文的传递策略
    • 隔离级别需要与数据库实际级别对齐
  3. MyBatis最佳实践

    • 动态SQL适合复杂查询场景
    • 二级缓存适合读多写少的业务
    • 插件机制可扩展监控能力
  4. 性能优化方向

    数据持久化优化
    连接池配置
    批处理操作
    合理使用缓存
    索引优化
    最大连接数
    超时配置
    批量插入
    批量更新
    一级缓存
    二级缓存

2.4 JPA规范实践(高效ORM解决方案)

2.4.1 JPA核心概念与实体映射

实体类映射规范

java">@Entity
@Table(name = "orders", indexes = {@Index(name = "idx_order_user", columnList = "user_id"),@Index(name = "idx_order_status", columnList = "status")
})
public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false, length = 50)private String orderNumber;@Enumerated(EnumType.STRING)@Column(length = 20)private OrderStatus status;@CreationTimestampprivate LocalDateTime createTime;@UpdateTimestampprivate LocalDateTime updateTime;// 关联关系配置@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)private List<OrderItem> items = new ArrayList<>();// 省略getter/setter
}

Repository接口智能方法推导

java">public interface OrderRepository extends JpaRepository<Order, Long> {// 根据状态分页查询Page<Order> findByStatus(OrderStatus status, Pageable pageable);// 复杂条件查询@Query("SELECT o FROM Order o WHERE " +"o.createTime BETWEEN :start AND :end " +"AND o.totalAmount > :minAmount")List<Order> findRecentHighValueOrders(@Param("start") LocalDateTime start,@Param("end") LocalDateTime end,@Param("minAmount") BigDecimal minAmount);// 动态查询interface OrderSpec {static Specification<Order> hasStatus(OrderStatus status) {return (root, query, cb) -> cb.equal(root.get("status"), status);}static Specification<Order> createdAfter(LocalDateTime time) {return (root, query, cb) -> cb.greaterThan(root.get("createTime"), time);}}List<Order> findAll(Specification<Order> spec, Sort sort);
}

2.4.2 关联关系映射实战(电商订单系统案例)

一对多关系配置

java">@Entity
public class OrderItem {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "order_id", nullable = false)private Order order;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "product_id", nullable = false)private Product product;@Column(nullable = false)private Integer quantity;// 省略其他字段
}// 级联操作示例
Order order = new Order();
order.addItem(new OrderItem(product1, 2));
order.addItem(new OrderItem(product2, 1));
orderRepository.save(order); // 自动保存所有关联项

多对多关系配置

java">@Entity
public class Product {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToMany@JoinTable(name = "product_category",joinColumns = @JoinColumn(name = "product_id"),inverseJoinColumns = @JoinColumn(name = "category_id"))private Set<Category> categories = new HashSet<>();
}@Entity
public class Category {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToMany(mappedBy = "categories")private Set<Product> products = new HashSet<>();
}

2.4.3 N+1查询问题解决方案(性能优化关键)

问题复现与诊断

java">// 危险查询方式
List<Order> orders = orderRepository.findAll();
orders.forEach(order -> {System.out.println(order.getItems().size()); // 每次访问触发查询
});

优化方案一:@EntityGraph立即加载

java">public interface OrderRepository extends JpaRepository<Order, Long> {@EntityGraph(attributePaths = {"items", "items.product"})@Query("SELECT o FROM Order o WHERE o.id = :id")Optional<Order> findByIdWithDetails(@Param("id") Long id);
}// 生成SQL:
SELECT o.*, i.*, p.* 
FROM orders o
LEFT JOIN order_item i ON o.id = i.order_id
LEFT JOIN product p ON i.product_id = p.id
WHERE o.id = ?

优化方案二:批量抓取策略

# application.properties
spring.jpa.properties.hibernate.default_batch_fetch_size=20
-- 优化后的查询:
SELECT * FROM order_item WHERE order_id IN (?, ?, ...) -- 一次查询20个订单项

优化方案三:JOIN FETCH查询

java">@Query("SELECT o FROM Order o " +"LEFT JOIN FETCH o.items i " +"LEFT JOIN FETCH i.product " +"WHERE o.createTime > :startDate")
List<Order> findRecentOrdersWithDetails(LocalDateTime startDate);

2.4.4 审计与版本控制(企业级数据管理)

自动审计字段配置

java">@EntityListeners(AuditingEntityListener.class)
@Entity
public class Product {// ...@CreatedByprivate String createdBy;@LastModifiedByprivate String modifiedBy;@Versionprivate Long version;
}// 配置审计信息获取
@Configuration
@EnableJpaAuditing
public class AuditConfig {@Beanpublic AuditorAware<String> auditorAware() {return () -> Optional.ofNullable(SecurityContextHolder.getContext()).map(SecurityContext::getAuthentication).map(Authentication::getName);}
}

乐观锁控制案例

java">@Service
@RequiredArgsConstructor
public class InventoryService {private final ProductRepository productRepository;@Transactionalpublic void reduceStock(Long productId, int quantity) {Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException(productId));if (product.getStock() < quantity) {throw new InsufficientStockException();}product.setStock(product.getStock() - quantity);productRepository.save(product); // 自动检查@Version字段}
}// 异常处理:
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(OptimisticLockingFailureException.class)public ResponseEntity<?> handleOptimisticLocking() {return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("error", "数据版本冲突,请刷新后重试"));}
}

2.4.5 复杂查询解决方案(动态条件组合)

Criteria API动态查询

java">public class OrderSpecifications {public static Specification<Order> buildSearchSpec(String orderNumber, LocalDate startDate, LocalDate endDate,BigDecimal minAmount) {return (root, query, cb) -> {List<Predicate> predicates = new ArrayList<>();if (StringUtils.hasText(orderNumber)) {predicates.add(cb.like(root.get("orderNumber"), "%" + orderNumber + "%"));}if (startDate != null) {predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), startDate.atStartOfDay()));}if (endDate != null) {predicates.add(cb.lessThanOrEqualTo(root.get("createTime"), endDate.plusDays(1).atStartOfDay()));}if (minAmount != null) {predicates.add(cb.greaterThanOrEqualTo(root.get("totalAmount"), minAmount));}return cb.and(predicates.toArray(new Predicate[0]));};}
}// 业务层使用
public Page<Order> searchOrders(OrderSearchCriteria criteria, Pageable pageable) {Specification<Order> spec = OrderSpecifications.buildSearchSpec(criteria.getOrderNumber(),criteria.getStartDate(),criteria.getEndDate(),criteria.getMinAmount());return orderRepository.findAll(spec, pageable);
}

QueryDSL集成方案

<!-- Maven依赖 -->
<dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId><version>5.0.0</version>
</dependency>
java">// 自动生成Q类
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QOrder extends EntityPathBase<Order> {// 自动生成查询元模型
}// 动态查询实现
public List<Order> findOrders(QOrderQuery query) {QOrder order = QOrder.order;JPAQuery<Order> jpaQuery = new JPAQuery<>(entityManager);return jpaQuery.select(order).from(order).where(order.status.eq(query.getStatus()).and(order.totalAmount.goe(query.getMinAmount())).and(order.createTime.between(query.getStart(), query.getEnd()))).orderBy(order.createTime.desc()).fetch();
}

扩展说明总结

  1. JPA核心价值

    • 通过对象映射简化数据库操作
    • 提供标准化的持久层接口
    • 支持面向对象的查询语言(JPQL)
  2. 关联关系设计原则

    • 优先使用LAZY加载避免不必要查询
    • 明确维护方(mappedBy)
    • 谨慎使用级联操作
  3. 性能优化重点

    JPA性能优化
    避免N+1查询
    合理使用二级缓存
    批量操作优化
    @EntityGraph
    Batch Fetch
    Ehcache集成
    批量插入
    批量更新
  4. 复杂查询选择策略

    • 简单查询:使用方法推导
    • 中等复杂度:使用@Query注解
    • 动态条件:使用Specification或QueryDSL
      以下针对关键技术的深度扩展说明:

2.4.6 QueryDSL深度集成(企业级动态查询方案)

完整集成流程

1. Maven配置(含APT插件)

<dependencies><!-- QueryDSL核心依赖 --><dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId><version>5.0.0</version></dependency><!-- 代码生成插件 --><dependency><groupId>com.querydsl</groupId><artifactId>querydsl-apt</artifactId><version>5.0.0</version><scope>provided</scope></dependency>
</dependencies><build><plugins><!-- APT处理器配置 --><plugin><groupId>com.mysema.maven</groupId><artifactId>apt-maven-plugin</artifactId><version>1.1.3</version><executions><execution><phase>generate-sources</phase><goals><goal>process</goal></goals><configuration><outputDirectory>target/generated-sources/querydsl</outputDirectory><processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor></configuration></execution></executions></plugin></plugins>
</build>

2. 自动生成的Q类示例

java">// QOrder.java(自动生成)
@Generated("com.querydsl.codegen.EntitySerializer")
public class QOrder extends EntityPathBase<Order> {private static final PathInits INITS = PathInits.DIRECT2;public static final QOrder order = new QOrder("order");public final NumberPath<Long> id = createNumber("id", Long.class);public final StringPath orderNumber = createString("orderNumber");public final ListPath<OrderItem, QOrderItem> items = this.<OrderItem, QOrderItem>createList("items", OrderItem.class, QOrderItem.class, PathInits.DIRECT2);public QOrder(String variable) {super(Order.class, forVariable(variable));}
}

3. 复杂查询构建示例

java">@Repository
public class OrderCustomRepositoryImpl implements OrderCustomRepository {@PersistenceContextprivate EntityManager em;@Overridepublic Page<Order> searchOrders(OrderSearchCondition condition, Pageable pageable) {QOrder order = QOrder.order;QOrderItem item = QOrderItem.orderItem;JPAQuery<Order> query = new JPAQueryFactory(em).selectFrom(order).leftJoin(order.items, item).fetchJoin().where(order.status.eq(condition.getStatus()).and(order.createTime.between(condition.getStartDate().atStartOfDay(),condition.getEndDate().plusDays(1).atStartOfDay())).and(item.product.price.gt(condition.getMinPrice()))).orderBy(order.createTime.desc()).groupBy(order.id);// 分页处理long total = query.fetchCount();List<Order> content = query.offset(pageable.getOffset()).limit(pageable.getPageSize()).fetch();return new PageImpl<>(content, pageable, total);}
}

4. 动态排序支持

java">private OrderSpecifier<?>[] createOrderSpecifiers(Pageable pageable) {return pageable.getSort().stream().map(order -> {PathBuilder<Order> path = new PathBuilder<>(Order.class, "order");return new OrderSpecifier(order.isAscending() ? Order.ASC : Order.DESC,path.get(order.getProperty()));}).toArray(OrderSpecifier[]::new);
}

2.4.7 二级缓存配置(生产级优化方案)

Ehcache3集成全流程

1. 依赖配置

<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-jcache</artifactId>
</dependency>
<dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.10.8</version>
</dependency>

2. ehcache.xml配置

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"><persistence directory="/data/cache"/><cache alias="productCache"><key-type>java.lang.Long</key-type><value-type>com.example.Product</value-type><expiry><ttl unit="minutes">30</ttl></expiry><resources><heap unit="MB">100</heap><offheap unit="MB">200</offheap><disk persistent="true" unit="GB">1</disk></resources></cache>
</config>

3. 实体类缓存注解

java">@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region = "productCache"
)
public class Product {// ...
}

4. Spring Boot配置

# application.properties
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=jcache
spring.jpa.properties.hibernate.javax.cache.provider=org.ehcache.jsr107.EhcacheCachingProvider
spring.jpa.properties.hibernate.javax.cache.uri=classpath:ehcache.xml

5. 缓存监控方案

java">@Bean
public MeterRegistryCustomizer<MeterRegistry> cacheMetrics(CachingProvider provider) {return registry -> {CacheManager cacheManager = provider.getCacheManager();cacheManager.getCacheNames().forEach(name -> {Cache<?, ?> cache = cacheManager.getCache(name);registry.gauge("cache.size", Tags.of("name", name), cache::size);});};
}

2.4.8 乐观锁与审计增强实现

乐观锁深度控制
java">// 实体类版本控制
@Entity
public class Inventory {@Idprivate Long productId;@Versionprivate Integer version;private Integer stock;
}// 重试策略实现
@Retryable(value = OptimisticLockingFailureException.class, maxAttempts = 3,backoff = @Backoff(delay = 100))
public void updateStockWithRetry(Long productId, int delta) {Inventory inv = inventoryRepo.findById(productId).orElseThrow();inv.setStock(inv.getStock() + delta);inventoryRepo.save(inv);
}
审计功能扩展
java">// 自定义审计字段
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {@CreatedDateprivate LocalDateTime createdDate;@LastModifiedDateprivate LocalDateTime modifiedDate;@CreatedByprivate String createdBy;@LastModifiedByprivate String modifiedBy;
}// 多租户审计实现
@Bean
public AuditorAware<TenantUser> auditorProvider() {return () -> Optional.ofNullable(SecurityContextHolder.getContext()).map(SecurityContext::getAuthentication).filter(authentication -> authentication.getPrincipal() instanceof TenantUser).map(authentication -> (TenantUser) authentication.getPrincipal());
}

2.4.9 复杂类型处理(JSON/XML字段映射)

JSON类型处理(Hibernate6+)

java">@Entity
public class ProductSpec {@Idprivate Long id;@JdbcTypeCode(SqlTypes.JSON)@Column(columnDefinition = "jsonb")private Map<String, Object> attributes = new HashMap<>();
}// 自定义JSON转换器
@Converter(autoApply = true)
public class JsonConverter implements AttributeConverter<Map<String, Object>, String> {private static final ObjectMapper mapper = new ObjectMapper();@Overridepublic String convertToDatabaseColumn(Map<String, Object> attribute) {try {return mapper.writeValueAsString(attribute);} catch (JsonProcessingException e) {throw new IllegalArgumentException("JSON转换失败", e);}}@Overridepublic Map<String, Object> convertToEntityAttribute(String dbData) {try {return mapper.readValue(dbData, new TypeReference<>() {});} catch (IOException e) {throw new IllegalArgumentException("JSON解析失败", e);}}
}

扩展技术总结

  1. QueryDSL最佳实践

    动态查询需求
    简单条件
    方法命名推导
    中等复杂度
    @Query注解
    高度动态
    QueryDSL
    Criteria API
  2. 缓存策略选择

    策略类型适用场景注意事项
    READ_ONLY只读数据(字典表等)不支持更新操作
    NONSTRICT_READ_WRITE偶尔更新的数据可能短暂数据不一致
    READ_WRITE高频读写数据需要事务支持
    TRANSACTIONAL分布式事务环境性能开销较大
  3. 乐观锁实现要点

    • 使用@Version字段控制版本
    • 结合重试机制处理并发冲突
    • 前端需处理HTTP 409 Conflict响应
  4. 复杂类型存储方案

    • JSON类型:适合非结构化数据
    • XML类型:适合严格模式数据
    • 二进制类型:适合文件存储

2.5 分布式事务方案(Saga模式深度实践)

2.5.1 分布式事务核心挑战

典型问题场景

电商系统下单流程:
1. 订单服务 → 创建订单
2. 库存服务 → 扣减库存
3. 物流服务 → 生成物流单异常场景:
- 订单创建成功但库存不足
- 库存扣减后物流服务不可用
- 网络分区导致部分服务成功

事务模式对比

模式一致性模型实现复杂度适用场景
2PC强一致性数据库层跨库事务
TCC最终一致性高一致性要求的金融交易
Saga最终一致性长事务、跨服务操作
本地消息表最终一致性异步通知型业务

2.5.2 Saga模式实现原理

模式架构图
协调器 订单服务 库存服务 物流服务 1. 创建订单 订单创建成功 2. 扣减库存 库存扣减成功 3. 创建物流单 物流单创建失败 4. 补偿库存 库存恢复成功 5. 取消订单 协调器 订单服务 库存服务 物流服务
实现方式对比
类型控制方式优点缺点
编排式(Choreography)事件驱动去中心化、服务自治调试困难、易现循环依赖
编排式(Orchestration)中央协调器流程可视化、易管理单点风险、耦合协调逻辑

2.5.3 订单-库存-物流Saga实现(编排式)

项目结构
saga-demo/
├── order-service/
├── inventory-service/
├── logistics-service/
└── saga-coordinator/
协调器核心实现
java">// Saga协调器配置
@Configuration
public class SagaConfig {@Beanpublic SagaCoordinator sagaCoordinator(OrderService orderService,InventoryService inventoryService,LogisticsService logisticsService) {return SagaBuilder.begin("创建订单", orderService::createOrder).then("扣减库存", inventoryService::deductStock).then("生成物流单", logisticsService::createLogistics).withCompensation("订单取消", orderService::cancelOrder).withCompensation("库存恢复", inventoryService::restoreStock).build();}
}// Saga执行器
public class SagaExecutor {private final List<SagaStep> steps;private final List<BiConsumer<SagaContext, Exception>> compensations = new ArrayList<>();public void execute(SagaContext context) {try {for (SagaStep step : steps) {step.execute(context);}} catch (Exception e) {executeCompensation(context);throw new SagaException("Saga执行失败", e);}}private void executeCompensation(SagaContext context) {Collections.reverse(compensations);compensations.forEach(comp -> comp.accept(context, null));}
}
订单服务实现
java">@Service
public class OrderService {private static final Map<Long, Order> orders = new ConcurrentHashMap<>();@SagaParticipantpublic void createOrder(SagaContext context) {Order order = new Order(context.get("userId"), context.get("productId"),context.get("quantity"));orders.put(order.getId(), order);context.put("orderId", order.getId());}@Compensationpublic void cancelOrder(SagaContext context) {Long orderId = context.get("orderId");orders.get(orderId).setStatus(OrderStatus.CANCELLED);}
}

2.5.4 异常处理与恢复机制

重试策略配置

java">@Bean
public RetryTemplate sagaRetryTemplate() {return new RetryTemplateBuilder().maxAttempts(3).exponentialBackoff(1000, 2, 5000).retryOn(SagaRetryableException.class).build();
}// 服务层应用
@SagaParticipant
@Retryable(retryFor = InventoryServiceException.class, maxAttempts = 3,backoff = @Backoff(delay = 1000))
public void deductStock(SagaContext context) {// 库存扣减逻辑if (currentStock < required) {throw new InventoryServiceException("库存不足");}// ...
}

事务日志记录

java">@Entity
public class SagaLog {@Idprivate String sagaId;private SagaStatus status;@Lobprivate String contextJson;@ElementCollectionprivate List<String> executedSteps;@ElementCollectionprivate List<String> compensatedSteps;
}// 日志切面
@Aspect
@Component
public class SagaLogAspect {@Autowiredprivate SagaLogRepository logRepository;@Around("@annotation(SagaParticipant)")public Object logStep(ProceedingJoinPoint pjp) throws Throwable {String stepName = ((MethodSignature)pjp.getSignature()).getMethod().getName();SagaContext context = (SagaContext) pjp.getArgs()[0];SagaLog log = logRepository.findBySagaId(context.getSagaId()).orElseGet(() -> new SagaLog(context.getSagaId()));try {Object result = pjp.proceed();log.addExecutedStep(stepName);logRepository.save(log);return result;} catch (Exception e) {log.addCompensatedStep(stepName);log.setStatus(SagaStatus.FAILED);logRepository.save(log);throw e;}}
}

2.5.5 生产环境部署方案

Kubernetes部署配置

# saga-coordinator-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: saga-coordinator
spec:replicas: 3strategy:rollingUpdate:maxSurge: 1maxUnavailable: 0template:spec:containers:- name: coordinatorimage: registry.example.com/saga-coordinator:1.0.0env:- name: SPRING_DATASOURCE_URLvalue: jdbc:mysql://mysql-cluster:3306/saga- name: SPRING_REDIS_HOSTvalue: redis-sentinel# 服务熔断配置
spring:cloud:circuitbreaker:resilience4j:instances:saga:failureRateThreshold: 50waitDurationInOpenState: 10sslidingWindowSize: 10

监控指标暴露

java">@Bean
public MeterRegistryCustomizer<MeterRegistry> sagaMetrics() {return registry -> {Gauge.builder("saga.active_count", SagaCoordinator::getActiveCount).register(registry);Timer.builder("saga.duration").publishPercentiles(0.5, 0.95).register(registry);};
}

总结与最佳实践

Saga模式适用场景

是否长周期事务?
考虑Saga
考虑本地事务
是否需要强一致性?
结合TCC模式
纯Saga实现

实施要点

  1. 服务自治:每个参与者服务需独立管理本地事务
  2. 幂等设计:所有操作必须支持重试
  3. 补偿事务:确保每个正向操作都有对应的补偿逻辑
  4. 可视化监控:记录完整事务链路
  5. 压力测试:验证分布式锁和重试机制的性能

容错模式推荐

故障类型处理策略
业务校验失败立即中断并触发补偿
网络临时故障指数退避重试
服务不可用熔断降级+人工干预
数据不一致定时对账修复

http://www.ppmy.cn/news/1571625.html

相关文章

DeepSeek遇袭后的深思:ManageEngine ITOM如何筑牢安全防线

在科技飞速发展的当下&#xff0c;大模型领域正以前所未有的速度改变着我们的生活和工作方式。DeepSeek作为大模型赛道上的重要参与者为众多行业带来了新的机遇和变革。然而&#xff0c;近期DeepSeek遭受网络攻击的事件&#xff0c;却如同一记警钟&#xff0c;在整个行业内回荡…

Django学习笔记(第一天:Django基本知识简介与启动)

博主毕业已经工作一年多了&#xff0c;最基本的测试工作已经完全掌握。一方面为了解决当前公司没有自动化测试平台的痛点&#xff0c;另一方面为了向更高级的测试架构师转型&#xff0c;于是重温Django的知识&#xff0c;用于后期搭建测试自动化平台。 为什么不选择Java&#x…

WRF-Hydro:高级水文建模系统详解

1. WRF-Hydro 概述 什么是 WRF-Hydro&#xff1f; WRF-Hydro&#xff08;Weather Research and Forecasting Hydrological modeling system&#xff09;是由美国国家大气研究中心&#xff08;NCAR&#xff09;开发的一个用于耦合气象模型和水文模型的高级建模系统。它旨在提供…

一竞技瓦拉几亚S4预选:YB 2-0击败GG

在2月11号进行的PGL瓦拉几亚S4西欧区预选赛上,留在欧洲训练的YB战队以2-0击败GG战队晋级下一轮。双方对阵第二局:对线期YB就打出了优势,中期依靠卡尔带队进攻不断扩大经济优势,最终轻松碾压拿下比赛胜利,以下是对决战报。 YB战队在天辉。阵容是潮汐、卡尔、沙王、隐刺、发条。G…

探索 API 文档新境界:Swagger 助力生成带权限控制的 API 文档

各位开发者朋友们&#xff01;在咱们的开发工作里&#xff0c;API 文档就像是项目的说明书&#xff0c;清晰准确的文档能让我们的开发效率大幅提升。而当涉及到权限控制时&#xff0c;如何生成既安全又详细的 API 文档就成了一个关键问题。今天&#xff0c;我就和大家好好唠唠如…

React进行路由跳转的方法汇总

在 React 中进行路由跳转有多种方法&#xff0c;具体取决于你使用的路由库和版本。以下是常见的路由跳转方法汇总&#xff0c;主要基于 react-router-dom 库。 1. 使用 useNavigate 钩子&#xff08;适用于 react-router-dom v6&#xff09; useNavigate 是 react-router-dom…

Android图片加载框架Coil,Kotlin

Android图片加载框架Coil&#xff0c;Kotlin implementation("io.coil-kt:coil:1.4.0") import android.os.Bundle import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import coil.Coil i…

2024 Rust现代实用教程:1.1Rust简介与安装更新

文章目录 一、Rust安装二、更新Rust三、Rust的Stable与Nightly版本四、卸载ubuntu安装的cargo和rustup五、rust源设置六、rust交叉编译工具链说明 rustup稳定版交叉编译步骤 步骤 1&#xff1a;安装目标组件步骤 2&#xff1a;安装交叉编译工具链步骤 3&#xff1a;配置环境变…