1. Saga Pattern là gì?

Saga Pattern là một mẫu thiết kế dùng để quản lý một nghiệp vụ lớn trải qua nhiều service hoặc database độc lập. các nghiệp vụ được chia thành nhiều local transaction. mỗi transaction cập nhật nghiệp vụ của một service của nó. nếu một bước thất bại, hệ thống có thể chạy các compensating transaction để bù trừ những thay đổi đã thực hiện trước đó.

Saga thường được sử dụng trong kiến trúc microservices, nơi mỗi service sở hữu database riêng và không thể dễ dàng gộp toàn bộ nghiệp vụ vào một transaction ACID duy nhất.

2. Vì sao cần Saga Pattern?

Vấn đề của transaction truyền thống

Trong một ứng dụng đơn khối sử dụng cùng một database, việc tạo đơn hàng và giảm tồn kho có thể nằm trong một transaction:

BEGIN;

INSERT INTO orders (product_id, quantity, status)
VALUES (10, 1, 'pending');

UPDATE products
SET stock = stock - 1
WHERE id = 10
  AND stock >= 1;

COMMIT;

Đây là ví dụ minh họa; trong ứng dụng thực tế cần kiểm tra kết quả cập nhật tồn kho và rollback nếu không còn hàng.

Vấn đề khi gọi nhiều service tuần tự

giả sử chúng ta có một quy trình đặt hàng: tạo đơn hàng –> giữ hàng thành công –> thanh toán thất bại.

Lúc này, đơn hàng đã tồn tại và hàng có thể đã được giữ. Nếu chỉ trả lỗi cho client mà không xử lý các thay đổi trước đó, hệ thống có thể để lại một đơn hàng không thể hoàn thành và số lượng hàng bị giữ không cần thiết.

Saga yêu cầu thiết kế trước cả luồng thành công lẫn luồng phục hồi:

  • Khi bước tiếp theo thành công, tiếp tục quy trình.
  • Khi bước tiếp theo thất bại, xác định những bước đã hoàn thành và chạy hành động bù trừ phù hợp.
  • Nếu lỗi chỉ là tạm thời, có thể retry thay vì lập tức hủy toàn bộ nghiệp vụ.

3. Compensating Transaction

Compensating transaction là một thao tác nghiệp vụ nhằm bù trừ tác động của một transaction trước đó. Nó không đồng nghĩa với ROLLBACK của database. Giả sử Payment Service đã thu 500.000 đồng. Sau đó Shipping Service báo không thể giao hàng.

Database không thể dùng ROLLBACK để xóa ngược một khoản tiền đã được cổng thanh toán xử lý thành công từ trước. Thay vào đó, hệ thống cần gửi yêu cầu hoàn tiền và theo dõi kết quả hoàn tiền.

Tương tự:

  • Giữ hàng → giải phóng hàng đã giữ.
  • Thu tiền → hoàn tiền.
  • Tạo booking → hủy booking nếu nhà cung cấp cho phép.
  • Cộng điểm thưởng → trừ lại điểm đã cộng nếu chính sách nghiệp vụ cho phép.

4. Hai cách triển khai Saga: Choreography và Orchestration

Choreography Saga – Điều phối bằng event

Trong Choreography, không có một bộ điều phối trung tâm quyết định toàn bộ quy trình. Các service phản ứng với event do service khác phát ra.

Ví dụ:

  1. Order Service tạo đơn hàng và phát OrderCreated.
  2. Inventory Service nhận event, giữ hàng rồi phát InventoryReserved.
  3. Payment Service nhận event, xử lý thanh toán rồi phát PaymentSucceeded hoặc PaymentFailed.
  4. Order Service nhận kết quả và cập nhật trạng thái đơn hàng.
  5. Nếu thanh toán thất bại, các service liên quan nhận event phù hợp để thực hiện compensation.

mỗi serviec cần biết mình phải làm gì khi nhận được event.

Ưu điểm:

  • Các service ít phụ thuộc trực tiếp vào một bộ điều phối trung tâm.
  • Có thể phù hợp với quy trình ngắn, ít bước và ít nhánh.
  • Các service có thể phản ứng độc lập với những event thuộc nghiệp vụ.

Nhược điểm:

  • Luồng tổng thể bị phân tán qua nhiều event handler.
  • Khi số lượng service tăng, khó biết chính xác toàn bộ Saga đang ở bước nào.
  • Dễ tạo chuỗi event phức tạp, phụ thuộc vòng hoặc logic compensation khó theo dõi.
  • Việc debug và kiểm thử tích hợp có thể khó hơn.

Orchestration Saga – Điều phối bằng orchestrator

Trong Orchestration, một thành phần gọi là Saga Orchestrator quản lý trạng thái và quyết định bước tiếp theo. Orchestrator không nhất thiết trực tiếp sửa dữ liệu của các service. Nó gửi command hoặc request để yêu cầu service thực hiện local transaction, nhận kết quả rồi quyết định tiếp tục, retry hay compensation.

Ví dụ:

  1. Orchestrator bắt đầu Saga và yêu cầu tạo đơn hàng.
  2. Sau khi Order Service xác nhận, orchestrator yêu cầu giữ hàng.
  3. Sau khi Inventory Service xác nhận, orchestrator yêu cầu thanh toán.
  4. Nếu thanh toán thành công, orchestrator yêu cầu tạo vận đơn và hoàn tất Saga.
  5. Nếu thanh toán thất bại, orchestrator yêu cầu giải phóng hàng và cập nhật trạng thái đơn hàng.

Ưu điểm:

  • Luồng nghiệp vụ được thể hiện tập trung, dễ theo dõi.
  • Có thể lưu trạng thái hiện tại của Saga và xác định bước cần retry.
  • Phù hợp với quy trình nhiều bước, nhiều nhánh và nhiều hành động bù trừ.

Nhược điểm:

  • Cần xây dựng và vận hành logic điều phối.
  • Orchestrator cần được thiết kế để phục hồi sau khi bị lỗi hoặc khởi động lại.
  • Nếu phụ thuộc vào một instance duy nhất và không có cơ chế phục hồi, orchestrator có thể trở thành điểm lỗi của hệ thống.

5. Pivot Transaction và điểm không thể quay lại

Một số Saga có pivot transaction — bước đánh dấu ranh giới quan trọng giữa phần có thể bù trừ và phần phải được hoàn thành theo chính sách của nghiệp vụ. Ví dụ, với một quy trình đặt chỗ, hệ thống có thể giữ chỗ tạm thời, xác nhận thanh toán rồi chuyển sang khâu phát hành vé. Sau khi vé đã được phát hành, việc “hủy” có thể phải tuân theo chính sách hủy vé và hoàn tiền riêng, thay vì đơn giản xóa trạng thái đặt chỗ. Pivot không nhất thiết là một câu lệnh COMMIT toàn cục. Nó là khái niệm thiết kế giúp xác định điểm chuyển đổi trong chiến lược phục hồi.

6. Saga và Eventual Consistency

Saga thường đi cùng eventual consistency — tính nhất quán cuối cùng. Trong một khoảng thời gian, các service có thể đang ở những trạng thái trung gian khác nhau. Ví dụ, Order Service đã tạo đơn hàng nhưng Inventory Service chưa xác nhận giữ hàng. Đây không nhất thiết là lỗi nếu hệ thống biểu diễn rõ trạng thái PENDING và không cho phép người dùng hiểu nhầm rằng đơn hàng đã hoàn tất. Khi các bước tiếp tục thành công, hệ thống hội tụ về trạng thái cuối cùng mong muốn. Nếu một bước thất bại, các compensation đưa nghiệp vụ về một trạng thái hợp lệ khác.

7. Tổng kết

Saga Pattern giải quyết bài toán điều phối một nghiệp vụ phân tán qua nhiều service mà không dựa vào một transaction ACID chung.

Ba nội dung quan trọng nhất cần nhớ:

  1. Local transaction: mỗi service tự đảm bảo tính nguyên tử cho thay đổi dữ liệu thuộc mình.
  2. Compensating transaction: nếu quy trình không thể tiếp tục, hệ thống thực hiện các hành động nghiệp vụ để bù trừ những thay đổi đã hoàn tất.
  3. Orchestration hoặc Choreography: hai cách phối hợp các bước Saga, khác nhau ở việc luồng được điều khiển tập trung hay thông qua event giữa các service.

Bài viết khác

Series 7 — Web Quality – Engineering :Testing – Unit Testing, Integration Testing, Web Performance – Core Web Vitals, Code Splitting, Lazy Loading

Series 7 — Web Quality – Engineering Bài 3: Testing – Unit Testing, Integration Testing và End-to-End Testing trong ứng dụng web 1. Vì sao ứng dụng web cần Testing? Trong quá trình phát triển Frontend, chúng ta thường kiểm tra ứng dụng bằng cách chạy website trên trình duyệt, nhấn vào các nút, nhập […]

Series 7 — Web Quality – Engineering : Authentication & Authorization

Series 7 — Web Quality – Engineering Bài 1: Authentication & Authorization – Xác thực và phân quyền trong ứng dụng web 1. Mở đầu Khi xây dựng một ứng dụng web có chức năng đăng nhập, chúng ta thường nghĩ rằng chỉ cần tạo biểu mẫu nhập email, mật khẩu và kiểm tra thông […]

Series 6 – Next.js Advanced – Production: Next.js Build & Deployment

Series 6 – Next.js Advanced & Production Bài 5: Next.js Build & Deployment – Từ mã nguồn đến môi trường Production 1. Mở đầu Trong quá trình phát triển một ứng dụng web, việc chạy thành công trên máy tính cá nhân chưa có nghĩa là ứng dụng đã sẵn sàng để đưa đến người […]

Series 6 – Next.js Advanced – Production: Next.js Internationalized Routing Next.js Static Export

Series 6 – Next.js Advanced & Production   Bài 3: Next.js Internationalized Routing – Tổ chức URL cho website đa ngôn ngữ 1. Mở đầu Sau khi xây dựng cơ chế dịch nội dung và định dạng theo locale, ứng dụng cần một cách để người dùng truy cập đúng phiên bản ngôn ngữ. Ví […]

Series 6 – Next.js Advanced & Production: Metadata & SEO, Internationalization (i18n) & Localization (l10n)

Series 6 – Next.js Advanced & Production Bài 1: Metadata & SEO trong Next.js – Tối ưu thông tin và khả năng hiển thị trên công cụ tìm kiếm 1. Mở đầu Khi xây dựng một website, việc hoàn thiện giao diện và chức năng mới chỉ là một phần của quá trình phát triển. […]

Series 5 – Next.js Fundamentals: CSR, SSR, SSG, ISR và cách lựa chọn

Series 5 – Next.js Fundamentals   Bài 7 : CSR, SSR, SSG và ISR – Các chiến lược Rendering trong Next.js 1. Mở đầu Khi xây dựng một website bằng React, chúng ta thường tập trung vào việc tạo component, quản lý state và hiển thị giao diện trên trình duyệt. Tuy nhiên, khi ứng dụng […]

Leave a Reply

Your email address will not be published. Required fields are marked *