Chào bạn,
Trong bài học trước, chúng ta đã đặt nền móng vững chắc cho việc xây dựng Saga orchestrator bằng cách mô hình hóa các giao dịch xuôi (forward transactions) – kịch bản "happy path" nơi mọi thứ diễn ra thành công. Bạn đã học cách sử dụng Service Task, Send/Receive Task, và Parallel Gateway để điều phối luồng công việc thuận.
Tuy nhiên, sức mạnh thực sự của Saga pattern nằm ở khả năng xử lý lỗi. Hôm nay, chúng ta sẽ giải quyết câu hỏi quan trọng nhất: "Điều gì xảy ra khi một bước trong chuỗi giao dịch thất bại?". Mục tiêu của bài học này là học cách sử dụng Compensation Events để implement các giao dịch bù trừ (compensating transactions). Đây là cơ chế "hoàn tác" mà BPMN cung cấp để đảm bảo tính nhất quán dữ liệu trong các quy trình phức tạp.
1. Ôn lại về Giao dịch Bù trừ (Compensating Transactions)
Trước khi đi vào các ký hiệu BPMN, chúng ta hãy cùng nhau làm rõ lại bản chất của giao dịch bù trừ trong Saga.
- Một giao dịch bù trừ là một hành động nghiệp vụ nhằm đảo ngược tác động của một giao dịch đã thành công trước đó.
- Ví dụ: Nếu giao dịch xuôi là
ReserveFlight(Đặt vé máy bay), thì giao dịch bù trừ tương ứng sẽ làCancelFlight(Hủy vé máy bay). - Quan trọng: Đây không phải là một
ROLLBACKở mức cơ sở dữ liệu. Giao dịchReserveFlightđã được commit và hoàn tất.CancelFlightlà một giao dịch mới, độc lập được thực thi để đưa hệ thống về trạng thái nhất quán về mặt logic.
Saga Pattern | Distributed Transactions | Microservices
Video này giải thích rất rõ về Saga pattern và sự khác biệt của nó so với giao thức two-phase commit (2PC). Hãy xem lại để củng cố khái niệm về giao dịch bù trừ và vai trò của nó trong việc đảm bảo tính nhất quán cuối cùng (eventual consistency).
Vui lòng xem hai đoạn sau: Từ 05:57 đến 07:32: Đoạn này định nghĩa Saga là một chuỗi các giao dịch cục bộ và giải thích rằng khi một giao dịch thất bại, các giao dịch bù trừ sẽ được thực thi để hoàn tác các thay đổi trước đó. Từ 12:59 đến 16:53: Đoạn này so sánh Saga và 2PC, nhấn mạnh rằng Saga cung cấp 'eventual consistency' và sử dụng giao dịch bù trừ để phục hồi từ lỗi. Chú ý đến sự khác biệt về tính nguyên tử (atomicity) và tính linh hoạt.
2. Các ký hiệu BPMN cho Compensation
BPMN cung cấp một bộ công cụ mạnh mẽ và trực quan để mô hình hóa logic bù trừ. Nó bao gồm ba thành phần chính hoạt động cùng nhau:
-
Compensation Boundary Event (Sự kiện Bắt Bù trừ ở biên):
- Đây là một sự kiện bắt (catching event) được đính vào biên của một activity (ví dụ:
Service Task"Đặt khách sạn"). - Nó cho biết rằng activity này có thể được bù trừ.
- Bản thân nó không kích hoạt bất cứ điều gì; nó chỉ đơn giản là "chờ" để được một sự kiện ném (throwing event) kích hoạt.
- Đây là một sự kiện bắt (catching event) được đính vào biên của một activity (ví dụ:
-
Compensation Activity (Hành động Bù trừ):
- Đây là một activity (thường là
Service TaskhoặcScript Task) định nghĩa cách thức thực hiện việc bù trừ. Ví dụ: "Hủy đặt khách sạn". - Nó được liên kết với
Compensation Boundary Eventbằng một đường nét đứt (association), không phải mộtSequence Flow. Điều này nhấn mạnh rằng nó không nằm trong luồng xử lý chính.
- Đây là một activity (thường là
-
Compensation Throw Event (Sự kiện Ném Bù trừ):
- Đây là một sự kiện ném (throwing event), có thể là Intermediate hoặc End event.
- Khi luồng quy trình đi đến sự kiện này, nó sẽ kích hoạt cơ chế bù trừ.
- Process engine sẽ tự động tìm ngược lại trong lịch sử của process instance, xác định tất cả các activity đã hoàn thành và có
Compensation Boundary Eventđính kèm, sau đó thực thi cácCompensation Activitytương ứng (thường theo thứ tự ngược lại so với khi chúng hoàn thành).
Hãy xem sơ đồ minh họa cơ chế này:

Để hình dung rõ hơn cách bạn sẽ thao tác trong Camunda Modeler, video sau sẽ rất hữu ích.
Tutorial: How Advanced BPMN Symbols Improve Business Processes
Video này từ Camunda sẽ trình bày cách mô hình hóa logic bù trừ trực tiếp trên sơ đồ BPMN.
Hãy xem từ 30:34 đến 33:12. Tác giả sẽ thêm logic bù trừ vào một quy trình. Hãy quan sát cách: Một Compensation Boundary Event được kéo và thả vào biên của một task. Một Compensation Activity mới ('quit job') được tạo ra và liên kết với boundary event bằng đường nét đứt. Một Intermediate Throwing Compensation Event được đặt trong một luồng xử lý lỗi để kích hoạt việc bù trừ.
3. Xây dựng Saga Orchestrator hoàn chỉnh với Compensation
Bây giờ, hãy áp dụng những gì đã học vào ví dụ đặt tour du lịch từ bài trước.
- Luồng xuôi (Forward Transactions):
Reserve Car->Book Hotel->Book Flight. - Kịch bản lỗi:
Book Flightthất bại (ví dụ: hết vé). - Logic bù trừ: Chúng ta cần hủy việc đặt xe (
Cancel Car Reservation) và hủy việc đặt khách sạn (Cancel Hotel Booking).
Đây là cách chúng ta sẽ mô hình hóa nó trong BPMN:
- Đính một
Compensation Boundary Eventvào taskReserve Car. Liên kết nó với mộtService Taskmới tên làCancel Car Reservation. - Làm tương tự cho
Book Hotel, liên kết nó vớiService Tasktên làCancel Hotel Booking. - Sau task
Book Flight, sử dụng mộtExclusive Gatewayđể kiểm tra kết quả.- Nếu thành công: Đi đến
End Event. - Nếu thất bại: Dẫn luồng đến một
Intermediate Throwing Compensation Event.
- Nếu thành công: Đi đến
Khi quy trình đi đến Throw Event, Camunda Engine sẽ tự động kích hoạt Cancel Hotel Booking và Cancel Car Reservation.
Bài viết và kho mã nguồn sau đây cung cấp một ví dụ thực tế, hoàn chỉnh mà bạn có thể tham khảo.
Implementing the Saga Pattern in Microservices using Camunda
Bài viết này hướng dẫn chi tiết cách triển khai Saga pattern với Camunda, bao gồm cả việc định nghĩa các giao dịch bù trừ.
Hãy đọc phần 'Example Implementation'. Chú ý đến 'Step 1' và sơ đồ được mô tả: khi 'Charge Payment' thất bại, nó sẽ kích hoạt hai Compensation Task là 'Refund Payment' và 'Release Stock'. Tiếp theo, ở 'Step 3' và 'Step 4', bạn sẽ thấy các đoạn mã Java Delegate cho các task bù trừ như ReleaseStockDelegate. Điều này cho thấy việc triển khai một task bù trừ cũng tương tự như bất kỳ Service Task nào khác.
Để có trải nghiệm thực hành sâu hơn, kho mã nguồn này là một tài nguyên tuyệt vời. Nó cung cấp một dự án hoàn chỉnh để bạn khám phá.
Camunda Saga Pattern Example - GitHub
Kho mã nguồn này là một ví dụ hoàn chỉnh về Saga Pattern sử dụng Camunda để điều phối các microservices được viết bằng JavaScript (Node.js). Nó trực tiếp thể hiện cách các ký hiệu bù trừ trong BPMN được liên kết với code thực thi.
Hãy tập trung vào các phần sau: The BPMN Process Models: Đọc phần mô tả về mô hình thứ hai. Nó giải thích rõ cách 'Compensation Throw Event' được sử dụng để kích hoạt 'Compensation Catch Event' và chạy 'Compensation Task' tương ứng. The External Task Workers (Microservices): Xem đoạn mã cho worker đăng ký vào topic 'CancelFlightBooking'. Đây chính là mã thực thi cho giao dịch bù trừ. Installation và Running the Microservice Workers: Nếu muốn, bạn có thể làm theo hướng dẫn để chạy ví dụ này trên máy của mình. Đây là một bài tập thực hành rất tốt để củng cố kiến thức.
Tổng kết
Qua bài học hôm nay, bạn đã hoàn thiện bức tranh về Saga pattern bằng cách học cách xử lý các kịch bản lỗi. Những điểm chính cần ghi nhớ là:
- Giao dịch bù trừ là các hành động nghiệp vụ để hoàn tác các bước đã thành công trước đó.
- BPMN cung cấp cơ chế bù trừ tự nhiên thông qua bộ ba: Compensation Boundary Event, Compensation Activity, và Compensation Throw Event.
- Sự kết hợp này cho phép bạn mô hình hóa logic "rollback" một cách trực quan và rõ ràng ngay trên sơ đồ quy trình, giúp tăng cường sự mạnh mẽ và dễ bảo trì cho Saga orchestrator của bạn.
- Việc triển khai một Compensation Activity (ví dụ:
CancelHotelBooking) về mặt kỹ thuật không khác gì mộtService Taskthông thường; nó có thể là một Java Delegate hoặc một External Worker.
Xem trước bài học tiếp theo
Chúng ta đã tập trung rất nhiều vào việc điều khiển luồng quy trình dựa trên dữ liệu và lỗi. Trong module tiếp theo, chúng ta sẽ khám phá một khía cạnh quan trọng khác của việc kiểm soát quy trình: thời gian. Chúng ta sẽ bắt đầu bằng cách học cách tự động khởi chạy các quy trình theo một lịch trình cụ thể hoặc vào những thời điểm định trước bằng cách sử dụng Timer Start Event.