spring-boot-saga-pattern by giuseppe-trisciuoglio/developer-kit
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill spring-boot-saga-pattern在以下情况下实施此技能:
触发短语:分布式事务、saga 模式、补偿事务、微服务事务、最终一致性、跨服务回滚、编排模式、协同模式
Saga 模式是一种用于管理微服务中分布式事务的架构模式。与跨多个数据库使用单一 ACID 事务不同,saga 将事务分解为一系列本地事务。每个本地事务更新其数据库并发布事件或消息以触发下一步。如果某一步失败,saga 会执行补偿事务来撤销之前步骤所做的更改。
实现 saga 时,请做出以下决策:
按照以下步骤实现分布式事务的 saga 模式:
识别业务流程中涉及的所有服务。规划出本地事务的顺序及其对应的补偿事务。
根据团队专业知识和系统复杂性,选择协同(事件驱动、去中心化)或编排(集中协调器)。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
为每个事务步骤创建事件(OrderCreated、PaymentProcessed、InventoryReserved)。包含用于追踪的 correlationId。
确保每个服务都能在其自身数据库边界内原子性地完成其本地事务。
为每个正向操作,实现一个能逆转其效果的补偿操作(取消订单、退款、释放库存)。
使用适当的主题/队列配置 Kafka 或 RabbitMQ。实现幂等的消息消费者。
创建一个 saga 协调器服务,用于跟踪 saga 状态、向参与者发送命令以及在失败时处理补偿。
在每个服务中设置事件监听器,这些监听器响应来自其他服务的事件并触发后续步骤。
为每个 saga 步骤实现超时机制。为超过处理时间限制的消息配置死信队列。
跟踪 saga 执行状态、持续时间和失败率。为卡住或失败的 saga 设置警报。
每个微服务发布事件并监听来自其他服务的事件。没有中央协调器。
最适合:参与者较少的新建微服务应用程序
优点:
缺点:
一个中央协调器管理整个事务流程并告知服务该做什么。
最适合:遗留应用程序、复杂工作流,或需要集中控制时
优点:
缺点:
识别操作序列及相应的补偿事务:
Order → Payment → Inventory → Shipment → Notification
↓ ↓ ↓ ↓ ↓
Cancel Refund Release Cancel Cancel
每个服务处理其本地 ACID 事务,并发布事件或响应命令。
每个正向事务都必须有一个对应的补偿事务。确保幂等性和可重试性。
为失败的消息实现重试逻辑、超时和死信队列。
Spring Boot 3.x 及其依赖:
消息传递:Spring Cloud Stream、Apache Kafka、RabbitMQ、Spring AMQP
Saga 框架:Axon Framework (4.9.0)、Eventuate Tram Sagas、Camunda、Apache Camel
持久化:Spring Data JPA、事件溯源(可选)、事务发件箱模式
监控:Spring Boot Actuator、Micrometer、分布式追踪(Sleuth + Zipkin)
❌ 紧耦合:服务直接相互调用而不是使用事件 ❌ 缺少补偿:未为每个步骤实现补偿事务 ❌ 非幂等操作:无法安全重试的补偿操作 ❌ 同步 Saga:同步等待每个步骤(违背了初衷) ❌ 消息丢失:未处理消息传递失败 ❌ 无监控:运行 saga 而不了解其状态 ❌ 共享数据库:跨多个服务使用同一数据库 ❌ 忽略网络故障:未妥善处理部分故障
在以下情况下不要实施此模式:
@Transactional
public Order createOrder(OrderRequest request) {
Order order = orderRepository.save(request);
paymentService.charge(request.getPayment());
inventoryService.reserve(request.getItems());
shippingService.schedule(order);
return order;
}
@Service
public class OrderSagaOrchestrator {
public OrderSummary createOrder(OrderRequest request) {
// Step 1: Create order
Order order = orderService.createOrder(request);
try {
// Step 2: Process payment
Payment payment = paymentService.processPayment(
new PaymentRequest(order.getId(), request.getAmount()));
// Step 3: Reserve inventory
InventoryReservation reservation = inventoryService.reserve(
new InventoryRequest(order.getItems()));
// Step 4: Schedule shipping
Shipment shipment = shippingService.schedule(
new ShipmentRequest(order.getId()));
return OrderSummary.completed(order, payment, reservation, shipment);
} catch (PaymentFailedException e) {
// Compensate: cancel order
orderService.cancelOrder(order.getId());
throw e;
} catch (InsufficientInventoryException e) {
// Compensate: refund payment, cancel order
paymentService.refund(payment.getId());
orderService.cancelOrder(order.getId());
throw e;
}
}
}
// Event published when order is created
@EventHandler
public void on(OrderCreatedEvent event) {
// Trigger payment processing
paymentService.processPayment(event.getOrderId());
}
@Service
public class OrderEventHandler {
@KafkaListener(topics = "order.created")
public void handleOrderCreated(OrderCreatedEvent event) {
try {
paymentService.processPayment(event.toPaymentRequest());
} catch (PaymentException e) {
kafkaTemplate.send("order.payment.failed", new PaymentFailedEvent(event.getOrderId()));
}
}
}
@Service
public class PaymentEventHandler {
@KafkaListener(topics = "payment.processed")
public void handlePaymentProcessed(PaymentProcessedEvent event) {
inventoryService.reserve(event.toInventoryRequest());
}
@KafkaListener(topics = "payment.failed")
public void handlePaymentFailed(PaymentFailedEvent event) {
orderService.cancelOrder(event.getOrderId());
}
}
@Service
public class InventoryEventHandler {
@KafkaListener(topics = "inventory.reserved")
public void handleInventoryReserved(InventoryReservedEvent event) {
shippingService.scheduleShipment(event.toShipmentRequest());
}
@KafkaListener(topics = "inventory.insufficient")
public void handleInsufficientInventory(InsufficientInventoryEvent event) {
// Compensate: refund payment
paymentService.refund(event.getPaymentId());
// Compensate: cancel order
orderService.cancelOrder(event.getOrderId());
}
}
有关详细信息,请查阅以下资源:
另请参阅 examples.md 获取完整的实现示例:
每周安装次数
343
代码仓库
GitHub 星标数
173
首次出现
2026年2月3日
安全审计
安装于
claude-code267
gemini-cli259
opencode258
codex254
cursor254
github-copilot239
Implement this skill when:
Trigger phrases : distributed transactions, saga pattern, compensating transactions, microservices transaction, eventual consistency, rollback across services, orchestration pattern, choreography pattern
The Saga Pattern is an architectural pattern for managing distributed transactions in microservices. Instead of using a single ACID transaction across multiple databases, a saga breaks the transaction into a sequence of local transactions. Each local transaction updates its database and publishes an event or message to trigger the next step. If a step fails, the saga executes compensating transactions to undo the changes made by previous steps.
When implementing a saga, make these decisions:
Follow these steps to implement saga pattern for distributed transactions:
Identify all services involved in the business process. Map out the sequence of local transactions and their corresponding compensating transactions.
Select choreography (event-driven, decentralized) or orchestration (centralized coordinator) based on team expertise and system complexity.
Create events for each transaction step (OrderCreated, PaymentProcessed, InventoryReserved). Include correlationId for tracing.
Ensure each service can complete its local transaction atomically within its own database boundary.
For each forward operation, implement a compensating operation that reverses the effect (cancel order, refund payment, release inventory).
Configure Kafka or RabbitMQ with appropriate topics/queues. Implement idempotent message consumers.
Create a saga orchestrator service that tracks saga state, sends commands to participants, and handles compensations on failure.
Set up event listeners in each service that react to events from other services and trigger next steps.
Implement timeout mechanisms for each saga step. Configure dead-letter queues for messages that exceed processing time limits.
Track saga execution status, duration, and failure rates. Set up alerts for stuck or failed sagas.
Each microservice publishes events and listens to events from other services. No central coordinator.
Best for : Greenfield microservice applications with few participants
Advantages :
Disadvantages :
A central orchestrator manages the entire transaction flow and tells services what to do.
Best for : Brownfield applications, complex workflows, or when centralized control is needed
Advantages :
Disadvantages :
Identify the sequence of operations and corresponding compensating transactions:
Order → Payment → Inventory → Shipment → Notification
↓ ↓ ↓ ↓ ↓
Cancel Refund Release Cancel Cancel
Each service handles its local ACID transaction and publishes events or responds to commands.
Every forward transaction must have a corresponding compensating transaction. Ensure idempotency and retryability.
Implement retry logic, timeouts, and dead-letter queues for failed messages.
Spring Boot 3.x with dependencies:
Messaging : Spring Cloud Stream, Apache Kafka, RabbitMQ, Spring AMQP
Saga Frameworks : Axon Framework (4.9.0), Eventuate Tram Sagas, Camunda, Apache Camel
Persistence : Spring Data JPA, Event Sourcing (optional), Transactional Outbox Pattern
Monitoring : Spring Boot Actuator, Micrometer, Distributed Tracing (Sleuth + Zipkin)
❌ Tight Coupling : Services directly calling each other instead of using events ❌ Missing Compensations : Not implementing compensating transactions for every step ❌ Non-Idempotent Operations : Compensations that cannot be safely retried ❌ Synchronous Sagas : Waiting synchronously for each step (defeats the purpose) ❌ Lost Messages : Not handling message delivery failures ❌ No Monitoring : Running sagas without visibility into their status ❌ Shared Database : Using same database across multiple services ❌ Ignoring Network Failures : Not handling partial failures gracefully
Do not implement this pattern when:
@Transactional
public Order createOrder(OrderRequest request) {
Order order = orderRepository.save(request);
paymentService.charge(request.getPayment());
inventoryService.reserve(request.getItems());
shippingService.schedule(order);
return order;
}
@Service
public class OrderSagaOrchestrator {
public OrderSummary createOrder(OrderRequest request) {
// Step 1: Create order
Order order = orderService.createOrder(request);
try {
// Step 2: Process payment
Payment payment = paymentService.processPayment(
new PaymentRequest(order.getId(), request.getAmount()));
// Step 3: Reserve inventory
InventoryReservation reservation = inventoryService.reserve(
new InventoryRequest(order.getItems()));
// Step 4: Schedule shipping
Shipment shipment = shippingService.schedule(
new ShipmentRequest(order.getId()));
return OrderSummary.completed(order, payment, reservation, shipment);
} catch (PaymentFailedException e) {
// Compensate: cancel order
orderService.cancelOrder(order.getId());
throw e;
} catch (InsufficientInventoryException e) {
// Compensate: refund payment, cancel order
paymentService.refund(payment.getId());
orderService.cancelOrder(order.getId());
throw e;
}
}
}
// Event published when order is created
@EventHandler
public void on(OrderCreatedEvent event) {
// Trigger payment processing
paymentService.processPayment(event.getOrderId());
}
@Service
public class OrderEventHandler {
@KafkaListener(topics = "order.created")
public void handleOrderCreated(OrderCreatedEvent event) {
try {
paymentService.processPayment(event.toPaymentRequest());
} catch (PaymentException e) {
kafkaTemplate.send("order.payment.failed", new PaymentFailedEvent(event.getOrderId()));
}
}
}
@Service
public class PaymentEventHandler {
@KafkaListener(topics = "payment.processed")
public void handlePaymentProcessed(PaymentProcessedEvent event) {
inventoryService.reserve(event.toInventoryRequest());
}
@KafkaListener(topics = "payment.failed")
public void handlePaymentFailed(PaymentFailedEvent event) {
orderService.cancelOrder(event.getOrderId());
}
}
@Service
public class InventoryEventHandler {
@KafkaListener(topics = "inventory.reserved")
public void handleInventoryReserved(InventoryReservedEvent event) {
shippingService.scheduleShipment(event.toShipmentRequest());
}
@KafkaListener(topics = "inventory.insufficient")
public void handleInsufficientInventory(InsufficientInventoryEvent event) {
// Compensate: refund payment
paymentService.refund(event.getPaymentId());
// Compensate: cancel order
orderService.cancelOrder(event.getOrderId());
}
}
For detailed information, consult the following resources:
See also examples.md for complete implementation examples:
Weekly Installs
343
Repository
GitHub Stars
173
First Seen
Feb 3, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code267
gemini-cli259
opencode258
codex254
cursor254
github-copilot239
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
105,000 周安装