0Pricing
Microservices Communication Patterns (Saga, Circuit Breaker) · 课时

确保 Saga 的幂等性

在 Saga 参与者中实现幂等操作,防止重复消息或重试产生意外副作用。

确保 Saga 的幂等性 是 CoddyKit 上的免费 Microservices Communication Patterns (Saga, Circuit Breaker) 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Microservices Communication Patterns (Saga, Circuit Breaker) 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Microservices Communication Patterns (Saga, Circuit Breaker) 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Understanding Idempotency

In distributed systems, idempotency is a crucial concept. An operation is idempotent if executing it multiple times produces the same result as executing it once.

  • Think of it like pressing a light switch: pressing it once turns it on (or off). Pressing it again doesn't change the state further if it's already on (or off).
  • This is vital because messages can be duplicated or retried.

The Challenge of Duplicates

When services communicate, especially asynchronously via message brokers, messages can sometimes be delivered more than once. This is known as "at-least-once" delivery.

  • Network issues: A service might send a response, but the sender doesn't receive it, leading to a retry.
  • Service failures: A service crashes after processing a message but before acknowledging it, so the message is redelivered.
  • Without idempotency, these duplicates can cause unintended side effects, like double-charging a customer or creating duplicate orders.

Idempotency in Sagas

The Saga pattern orchestrates complex business transactions across multiple services. Each step in a saga is an operation performed by a service.

  • If a saga step receives the same command or event twice, it could lead to inconsistent data.
  • For example, if a "deduct payment" command is processed twice, a customer's account could be overcharged.
  • Idempotency ensures that even if a saga participant receives a message multiple times, the overall business transaction remains correct.

Introducing the Idempotency Key

To achieve idempotency, we often use an idempotency key. This is a unique identifier associated with a specific operation or request.

  • The key is typically generated by the client or the initiating service and passed along with the request.
  • It allows the receiving service to detect if it has already processed this exact operation.
  • Commonly, this could be a UUID (Universally Unique Identifier) or a unique transaction ID.

The Check-Then-Act Pattern

A common approach to implementing idempotency is the "check-then-act" pattern. Before performing an action, the service checks if the operation associated with the idempotency key has already been completed.

Here's the basic logic:

  1. Receive a request with an idempotency key.
  2. Check if this key is already marked as processed.
  3. If processed, return the original result (or success) without re-executing.
  4. If not processed, execute the operation and then mark the key as processed.

Idempotent Processing Demo

Let's look at a conceptual Java example for an idempotent payment processing method. We'll use a simple in-memory set to track processed keys, though a real system would use a persistent store.

Try running this example:

import java.util.HashSet;
import java.util.Set;

public class PaymentProcessor {
  private static Set<String> processedKeys = new HashSet<>();

  public static String processPayment(String idempotencyKey, double amount) {
    if (processedKeys.contains(idempotencyKey)) {
      return "Payment (key: " + idempotencyKey + ") already processed.";
    }

    // Simulate payment processing
    System.out.println("Processing payment of $" + amount + " for key: " + idempotencyKey);
    processedKeys.add(idempotencyKey); // Mark as processed
    return "Payment of $" + amount + " (key: " + idempotencyKey + ") processed successfully.";
  }

  public static void main(String[] args) {
    System.out.println(processPayment("order-123-payment-A", 50.00));
    System.out.println(processPayment("order-124-payment-B", 75.00));
    System.out.println(processPayment("order-123-payment-A", 50.00)); // Duplicate
  }
}

Leveraging Database Features

For operations that involve database writes, you can often use database features to help enforce idempotency:

  • Unique Constraints: Add a unique constraint on the idempotency key column (e.g., request_id) in your table. If a duplicate key is inserted, the database will throw an error.
  • Conditional Updates (UPSERT): Use commands like INSERT ... ON CONFLICT DO NOTHING (PostgreSQL) or INSERT ... ON DUPLICATE KEY UPDATE (MySQL) to prevent inserting duplicates or to update only if a record exists.

Idempotent Order Creation

Consider creating an order. We want to ensure that if the same "create order" request is sent twice, only one order is created.

Using a unique request_id:

-- SQL example (conceptual)
INSERT INTO orders (order_id, customer_id, amount, request_id, status)
VALUES ('ORD001', 'CUST123', 100.00, 'req-uuid-123', 'PENDING')
ON CONFLICT (request_id) DO NOTHING;

This statement will insert the order if req-uuid-123 is new. If it already exists, the database ignores the insert, ensuring idempotency.

Idempotent Compensation Actions

Idempotency isn't just for forward-moving saga steps; it's equally important for compensation actions.

  • If a compensation request (e.g., "refund payment") is sent multiple times due to retries, you wouldn't want to issue multiple refunds.
  • Apply the same idempotency principles: use a unique key for the compensation request and check if it has already been processed before executing.
  • This ensures that the system correctly reverses the original action only once.

Idempotency Best Practices

To effectively implement idempotency in your sagas:

  • Use Robust Unique Keys: Generate truly unique, non-guessable IDs (like UUIDs) for each operation.
  • Store Processed Keys Persistently: Don't rely on in-memory storage. Use a database or a dedicated cache for tracking processed keys.
  • Handle Concurrency: Ensure your check-then-act logic is atomic to prevent race conditions where two identical requests are processed simultaneously. Database unique constraints are excellent for this.
  • Define Scope: Clearly define what constitutes an "idempotent operation" and at what level the key applies (e.g., per message, per business transaction).

Idempotency Check

A microservice receives a "charge customer" message with an idempotency key. Due to network issues, the message is delivered twice. If the service correctly implements idempotency, what will happen?

Recap: Keeping Sagas Consistent

We've learned that idempotency is critical for building robust distributed systems, especially when implementing the Saga pattern.

  • It ensures that an operation, when executed multiple times, yields the same result as executing it once.
  • This prevents unintended side effects from duplicate messages or retries, which are common in distributed environments.
  • By using idempotency keys and patterns like "check-then-act" or database unique constraints, saga participants can safely process messages, maintaining data consistency.

常见问题解答

「确保 Saga 的幂等性」课时是免费的吗?

是的 — 「确保 Saga 的幂等性」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Microservices Communication Patterns (Saga, Circuit Breaker) 课程的其余内容,请升级到 CoddyKit PRO。 Microservices Communication Patterns (Saga, Circuit Breaker) 课程共包含 4 节课。

「确保 Saga 的幂等性」这节课中我会学到什么?

在 Saga 参与者中实现幂等操作,防止重复消息或重试产生意外副作用。 你通过在浏览器中直接运行的动手代码来练习 Microservices Communication Patterns (Saga, Circuit Breaker),全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Microservices Communication Patterns (Saga, Circuit Breaker) 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Microservices Communication Patterns (Saga, Circuit Breaker) 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「确保 Saga 的幂等性」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Microservices Communication Patterns (Saga, Circuit Breaker) 课中编写并运行代码吗?

能。每节 Microservices Communication Patterns (Saga, Circuit Breaker) 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 确保 Saga 的幂等性
  2. Saga 的重试策略
  3. 高级补偿逻辑
  4. 语义锁与并发 Saga
← 返回 Microservices Communication Patterns (Saga, Circuit Breaker)