Ý chính: Khi một nghiệp vụ đi qua nhiều dịch vụ, độ tin cậy đến từ quy trình bền vững chứ không phải một khóa dùng chung.
Thuật ngữ trong bài: Saga: chuỗi bước nghiệp vụ có khả năng bù trừ; compensation: hành động xử lý hậu quả khi một bước trước đã thành công; durable workflow: quy trình lưu lại được trạng thái để tiếp tục sau sự cố.
Bài toán thực tế
Thanh toán, giữ hàng và giao hàng không thể cùng nằm trong một giao dịch cơ sở dữ liệu. Một bước có thể đã thành công dù phản hồi bị mất. Hệ thống phải biết tiếp tục, thử lại hoặc thực hiện hành động bù trừ.
Điểm dễ bị bỏ qua
Khi thanh toán, tồn kho và giao hàng thuộc các dịch vụ khác nhau, không có một giao dịch cơ sở dữ liệu chung để quay lui tất cả. Mỗi bước có thể đã thành công dù phản hồi bị mất.
Saga cần lưu trạng thái bền vững, phân biệt thao tác có thể thử lại với thao tác cần bù trừ và cho phép con người can thiệp khi nghiệp vụ không thể tự quyết định.
Luồng xử lý
Khởi tạo quy trình→Máy trạng thái
Lưu từng chuyển trạng thái→Activity
Gọi service an toàn khi xử lý lặp→Bù trừ
Phục hồi nghiệp vụ
Thiết kế và triển khai
Orchestrate luồng quan trọng
Quy trình trung tâm làm rõ sequence, thời hạn và thao tác hỗ trợ. Choreography vẫn phù hợp cho phản ứng độc lập.
Lưu trạng thái trước khi hành động
Ghi chuyển trạng thái dự định trước khi gọi activity để sau restart biết phần nào còn thiếu.
Định nghĩa semantic idempotency
Dùng định danh order hoặc vận hành, không dùng yêu cầu ID ngẫu nhiên của mỗi thử lại, để một hành động nghiệp vụ chỉ có một kết quả.
Đi sâu vào thiết kế
Máy trạng thái là mô hình sản phẩm
Pending, confirmed, hủy và requires-rà soát phải có ý nghĩa chính xác với khách hàng. Support, finance và engineering cần dùng chung ngôn ngữ.
Công việc con người nằm trong thiết kế
Một số ngoại lệ không thể tự động an toàn. Manual task cần người phụ trách, thời hạn, evidence và resume action vẫn an toàn khi xử lý lặp.
Cách triển khai
- Mô hình hóa các trạng thái nghiệp vụ, thời hạn và kết quả kết thúc trước khi viết từng bước xử lý.
- Gán mã vận hành ổn định cho mỗi bước và cung cấp API tra cứu kết quả để thử lại an toàn.
- Xem bù trừ là một thao tác nghiệp vụ độc lập, có trạng thái lỗi và nhật ký kiểm toán riêng.
Mã minh họa: Quy trình đơn hàng có lưu trạng thái
workflow.save(state = 'RESERVING', version = 4)
reservation = inventory.reserve(orderId, operationId)
workflow.save(state = 'CHARGING', reservationId)
charge = payments.charge(orderId, operationId)
workflow.save(state = 'CONFIRMED', chargeId)Khi chạy lại, mỗi bước tra cứu kết quả bằng mã vận hành. Giá trị không xác định như thời gian hiện tại phải được lưu vào lịch sử trước khi sử dụng.
Rủi ro cần tính trước
- Thanh toán đã thành công nhưng phản hồi bị mất, khiến hệ thống không biết có nên thử lại.
- Thao tác bù trừ thất bại và cần thử lại sau hoặc chuyển cho người có thẩm quyền quyết định.
- Hai phiên quy trình cùng lúc thay đổi một đối tượng nghiệp vụ.
Nên theo dõi gì?
| Tín hiệu | Điều tín hiệu cho biết |
|---|---|
| Thời gian quy trình nằm ở mỗi trạng thái | Phát hiện hành trình khách hàng bị kẹt hoặc quá thời hạn. |
| Số lần thử và độ trễ của từng bước | Phát hiện dịch vụ phụ thuộc thiếu ổn định hoặc việc thử lại đang khuếch đại tải. |
| Tỷ lệ bù trừ và xử lý thủ công | Thể hiện chi phí của cả ngoại lệ kỹ thuật lẫn ngoại lệ nghiệp vụ. |
Cách kiểm chứng
- Làm mất phản hồi sau mỗi activity thành công và chứng minh quy trình vẫn hội tụ.
- Restart orchestrator ở mọi trạng thái đã lưu.
- Buộc bù trừ thất bại và kiểm tra cảnh báo cùng xử lý thủ công.
Đưa vào production từng bước
Cho quy trình mới chạy ở chế độ quan sát trên một luồng hiện có, chưa tạo tác động bên ngoài. So sánh lịch sử xử lý, chuyển từng bước một và giữ báo cáo đối soát cho tới khi luồng mới vượt qua các bài kiểm thử dừng dịch vụ, gửi trùng và khởi động lại.
Checklist trước khi vận hành
- Quy trình history bền vững và replay xác định.
- Timeout thể hiện nghiệp vụ thời hạn, không phải giới hạn HTTP tùy ý.
- Operator có thể xem, thử lại, compensate hoặc escalate an toàn.
Điều cần nhớ
Saga tốt làm mọi trạng thái dở dang có thể quan sát và phục hồi; nó không giả vờ rằng hệ thống phân tán vẫn có tính nguyên tử.
