二、数据持久化篇(深度增强版)
2.1 JDBC Template深度解析
架构设计思想
设计模式解析:
-
模板方法模式:
- 封装固定流程:获取连接→准备语句→执行→处理结果→释放资源
- 开发者只需关注SQL和结果处理
-
回调机制:
- 通过
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整合方案(原理与优化)
执行过程剖析
二级缓存优化策略:
<!-- 启用二级缓存 -->
<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);}}
}
扩展说明总结
-
JDBC Template设计哲学:
- 通过模板方法消除样板代码
- 分离资源管理与业务逻辑
- 适合需要精细控制SQL的场景
-
事务管理的本质:
- 通过AOP实现声明式事务
- 传播机制本质是事务上下文的传递策略
- 隔离级别需要与数据库实际级别对齐
-
MyBatis最佳实践:
- 动态SQL适合复杂查询场景
- 二级缓存适合读多写少的业务
- 插件机制可扩展监控能力
-
性能优化方向:
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();
}
扩展说明总结
-
JPA核心价值:
- 通过对象映射简化数据库操作
- 提供标准化的持久层接口
- 支持面向对象的查询语言(JPQL)
-
关联关系设计原则:
- 优先使用
LAZY
加载避免不必要查询 - 明确维护方(mappedBy)
- 谨慎使用级联操作
- 优先使用
-
性能优化重点:
-
复杂查询选择策略:
- 简单查询:使用方法推导
- 中等复杂度:使用
@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);}}
}
扩展技术总结
-
QueryDSL最佳实践:
-
缓存策略选择:
策略类型 适用场景 注意事项 READ_ONLY 只读数据(字典表等) 不支持更新操作 NONSTRICT_READ_WRITE 偶尔更新的数据 可能短暂数据不一致 READ_WRITE 高频读写数据 需要事务支持 TRANSACTIONAL 分布式事务环境 性能开销较大 -
乐观锁实现要点:
- 使用
@Version
字段控制版本 - 结合重试机制处理并发冲突
- 前端需处理HTTP 409 Conflict响应
- 使用
-
复杂类型存储方案:
- JSON类型:适合非结构化数据
- XML类型:适合严格模式数据
- 二进制类型:适合文件存储
2.5 分布式事务方案(Saga模式深度实践)
2.5.1 分布式事务核心挑战
典型问题场景:
电商系统下单流程:
1. 订单服务 → 创建订单
2. 库存服务 → 扣减库存
3. 物流服务 → 生成物流单异常场景:
- 订单创建成功但库存不足
- 库存扣减后物流服务不可用
- 网络分区导致部分服务成功
事务模式对比:
模式 | 一致性模型 | 实现复杂度 | 适用场景 |
---|---|---|---|
2PC | 强一致性 | 高 | 数据库层跨库事务 |
TCC | 最终一致性 | 高 | 高一致性要求的金融交易 |
Saga | 最终一致性 | 中 | 长事务、跨服务操作 |
本地消息表 | 最终一致性 | 低 | 异步通知型业务 |
2.5.2 Saga模式实现原理
模式架构图
实现方式对比
类型 | 控制方式 | 优点 | 缺点 |
---|---|---|---|
编排式(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模式适用场景:
实施要点:
- 服务自治:每个参与者服务需独立管理本地事务
- 幂等设计:所有操作必须支持重试
- 补偿事务:确保每个正向操作都有对应的补偿逻辑
- 可视化监控:记录完整事务链路
- 压力测试:验证分布式锁和重试机制的性能
容错模式推荐:
故障类型 | 处理策略 |
---|---|
业务校验失败 | 立即中断并触发补偿 |
网络临时故障 | 指数退避重试 |
服务不可用 | 熔断降级+人工干预 |
数据不一致 | 定时对账修复 |