1. Tổng quan
Từ các nguyên tắc cốt lõi và bối cảnh thực sự của nó, một ứng dụng dựa trên microservices là một distributed system. Toàn bộ hệ thống bao gồm nhiều services nhỏ hơn và cùng nhau các services này cung cấp chức năng ứng dụng tổng thể.
Mặc dù phong cách kiến trúc này mang lại nhiều lợi ích, nhưng nó cũng có một số hạn chế. Một trong những vấn đề chính trong kiến trúc dịch vụ vi mô là cách xử lý giao dịch trải dài trên nhiều dịch vụ .
Trong hướng dẫn này, chúng ta sẽ khám phá mô hình kiến trúc Saga cho phép chúng ta quản lý các giao dịch phân tán trong kiến trúc dịch vụ vi mô.
2. Mô hình cơ sở dữ liệu theo service
Một trong những lợi ích của kiến trúc microservice là chúng ta có thể lựa chọn technology stack cho từng service.
Ví dụ, chúng ta có thể quyết định sử dụng cơ sở dữ liệu quan hệ cho service A và cơ sở dữ liệu NoSQL cho service B.
Mô hình này cho phép service quản lý domain data độc lập (manage domain data independently) trên kho dữ liệu phù hợp nhất với kiểu dữ liệu và lược đồ của nó. Hơn nữa, nó cũng cho phép service mở rộng kho dữ liệu theo yêu cầu và cách ly khỏi các lỗi của các service khác.
Tuy nhiên, đôi khi một transaction có thể trải dài trên nhiều service và việc đảm bảo tính nhất quán của dữ liệu trên toàn bộ cơ sở dữ liệu là một thách thức. Trong phần tiếp theo, chúng ta sẽ xem xét kỹ hơn thách thức của quản lý giao dịch phân tán bằng một ví dụ.
3. Giao dịch phân tán (Distributed Transaction)
Để chứng minh việc sử dụng giao dịch phân tán, chúng tôi sẽ lấy ví dụ về một ứng dụng thương mại điện tử xử lý các đơn hàng trực tuyến và được triển khai bằng kiến trúc microservice.
Có một service để tạo đơn hàng, một service xử lý thanh toán, một service khác cập nhật hàng tồn kho và service cuối cùng thực hiện giao đơn hàng.
Mỗi microservice này thực hiện một giao dịch cục bộ (local transaction) để triển khai các chức năng riêng lẻ:
Đây là ví dụ về giao dịch phân tán khi ranh giới giao dịch vượt qua nhiều service và cơ sở dữ liệu.
Để đảm bảo hệ thống xử lý đơn hàng thành công, cả bốn microservice phải hoàn tất từng giao dịch cục bộ. Nếu bất kỳ service nào không hoàn tất giao dịch cục bộ của mình, tất cả các giao dịch đã hoàn tất trước đó phải được khôi phục để đảm bảo tính toàn vẹn (integrity) của dữ liệu.
4. Thách thức của giao dịch phân tán
Trong phần trước, chúng tôi đã cung cấp một ví dụ thực tế về giao dịch phân tán. Giao dịch phân tán trong kiến trúc microservice đặt ra hai thách thức chính.
Thách thức đầu tiên là duy trì ACID. Để đảm bảo tính chính xác của một giao dịch, giao dịch đó phải là Nguyên tử (Atomic), Nhất quán (Consistent), Cô lập (Isolated) và Bền vững (Durable) (ACID). Tính nguyên tử đảm bảo rằng tất cả hoặc không có bước nào của giao dịch sẽ hoàn tất. Tính nhất quán đưa dữ liệu từ trạng thái hợp lệ này sang trạng thái hợp lệ khác. Tính cô lập đảm bảo rằng các giao dịch đồng thời sẽ tạo ra cùng một kết quả mà các giao dịch tuần tự sẽ tạo ra. Cuối cùng, tính bền vững có nghĩa là các giao dịch đã cam kết vẫn được cam kết bất kể bất kỳ loại lỗi hệ thống nào. Trong một kịch bản giao dịch phân tán, vì giao dịch trải dài trên nhiều dịch vụ, nên việc đảm bảo ACID luôn là chìa khóa.
Thách thức thứ hai là quản lý mức độ cô lập giao dịch. Nó chỉ định lượng dữ liệu có thể nhìn thấy trong một giao dịch khi các service khác truy cập cùng một dữ liệu cùng lúc. Nói cách khác, nếu một đối tượng trong một trong các microservice được lưu trong cơ sở dữ liệu trong khi một request khác đọc dữ liệu, thì service đó có nên trả về dữ liệu cũ hay mới không?
5. Hiểu về Two-Phase Commit
Giao thức Two-Phase Commit (2PC) là một mô hình được sử dụng rộng rãi để triển khai các giao dịch phân tán. Chúng ta có thể sử dụng mô hình này trong kiến trúc microservice để triển khai các giao dịch phân tán.
Trong two-phase commit protocol, có một thành phần điều phối (coordinator component) chịu trách nhiệm kiểm soát giao dịch và chứa logic để quản lý giao dịch.
Thành phần khác là các nút tham gia (participating nodes) (ví dụ: các microservices) chạy các giao dịch cục bộ của chúng:
Như tên gọi cho thấy, two-phase commit protocol chạy một giao dịch phân tán trong hai phase:
Prepare Phase – Coordinator hỏi các nút tham gia xem họ đã sẵn sàng commit giao dịch chưa. Những người tham gia trả lời có hoặc không .
Commit Phase – Nếu tất cả các nút tham gia phản hồi tích cực trong phase 1, coordinator sẽ yêu cầu tất cả các nút commit. Nếu ít nhất một nút trả về negative, coordinator sẽ yêu cầu tất cả những nút tham gia khôi phục các giao dịch cục bộ của họ (roll back their local transactions).
6. Vấn đề với 2PC
Mặc dù 2PC hữu ích để triển khai giao dịch phân tán nhưng nó có những nhược điểm sau:
Trách nhiệm của giao dịch nằm ở nút điều phối (coordinator node) và nó có thể trở thành điểm lỗi duy nhất.
Tất cả các service khác cần phải đợi cho đến khi service chậm nhất hoàn tất xác nhận. Vì vậy, hiệu suất chung của giao dịch bị ràng buộc bởi service chậm nhất.
Two-phase commit protocol chậm theo thiết kế do tính trò chuyện (chattiness) và phụ thuộc vào coordinator. Vì vậy, nó có thể dẫn đến các vấn đề về khả năng mở rộng và hiệu suất trong kiến trúc dựa trên microservice liên quan đến nhiều service.
Two-phase commit protocol không được hỗ trợ trong cơ sở dữ liệu NoSQL. Do đó, trong kiến trúc microservice, nơi một hoặc nhiều service sử dụng cơ sở dữ liệu NoSQL, chúng ta không thể áp dụng 2pc.
7. Giới thiệu về Saga
7.1. Saga Architecture Pattern là gì?
Mô hình kiến trúc Saga cung cấp khả năng quản lý giao dịch bằng cách sử dụng chuỗi các giao dịch cục bộ.
Giao dịch cục bộ là đơn vị công việc do người tham gia Saga (Saga participant) thực hiện. Mọi hoạt động là một phần của Saga đều có thể được khôi phục bằng giao dịch bù trừ. Hơn nữa, Saga pattern đảm bảo rằng tất cả các hoạt động đều hoàn thành thành công hoặc các giao dịch bù trừ tương ứng được chạy để hoàn tác công việc đã hoàn thành trước đó.
Trong Saga pattern, một giao dịch bù trừ phải có tính bất biến và có thể thử lại ( a compensating transaction must be idempotent and retryable.) . Hai nguyên tắc này đảm bảo rằng chúng ta có thể quản lý các giao dịch mà không cần bất kỳ sự can thiệp thủ công nào.
Điều phối viên thực hiện Saga (Saga Execution Coordinator) (SEC) đảm bảo các nguyên tắc sau:
Sơ đồ trên cho thấy cách trực quan hóa mô hình Saga cho tình huống xử lý đơn hàng trực tuyến mà chúng ta đã thảo luận trước đó.
Sơ đồ trên cho thấy cách trực quan hóa Saga pattern cho tình huống xử lý đơn hàng trực tuyến mà chúng ta đã thảo luận trước đó.
7.2. The Saga Execution Coordinator
Saga Execution Coordinator là thành phần trung tâm để triển khai Saga flow. Nó chứa Saga log ghi lại chuỗi sự kiện của giao dịch phân tán (sequence of events of a distributed transaction).
Đối với bất kỳ lỗi nào, thành phần SEC sẽ kiểm tra Saga log để xác định các thành phần bị ảnh hưởng và trình tự các giao dịch bù trừ sẽ chạy.
Đối với bất kỳ lỗi nào trong thành phần SEC, nó có thể đọc Saga log khi log này hoạt động trở lại.
Sau đó, nó có thể xác định các giao dịch đã được hoàn lại thành công, giao dịch nào đang chờ xử lý và có thể thực hiện các hành động thích hợp:
Có hai cách tiếp cận để triển khai Saga pattern: choreography và orchestration. Chúng ta hãy thảo luận về chúng trong các phần tiếp theo.
7.3. Implementing Saga Choreography Pattern
Trong Saga Choreography pattern, mỗi microservice là 1 phần của transaction sẽ publishes một event được xử lý bởi microservice tiếp theo.
Để sử dụng pattern này, chúng ta cần quyết định xem microservice có phải là một phần của Saga hay không. Theo đó, microservice cần sử dụng framework phù hợp để triển khai Saga. Trong pattern này, Saga Execution Coordinator được nhúng trong microservice hoặc có thể là một thành phần độc lập.
Trong Saga, choreography flow được coi là thành công nếu tất cả các microservice hoàn tất giao dịch cục bộ của chúng và không có microservice nào báo cáo bất kỳ lỗi nào.
Sơ đồ sau đây minh họa Saga flow thành công cho ứng dụng xử lý đơn hàng trực tuyến:
Trong trường hợp xảy ra lỗi, microservice sẽ báo cáo lỗi đó cho SEC và SEC có trách nhiệm thực hiện các giao dịch bồi thường có liên quan :
Trong ví dụ này, payment service báo cáo lỗi và SEC gọi giao dịch bù trừ để hủy order. Nếu lệnh gọi đến giao dịch bù trừ không thành công, SEC có trách nhiệm thử lại cho đến khi hoàn tất thành công. Hãy nhớ rằng trong Saga, giao dịch bù trừ phải có tính bất biến và có thể thử lại .
Choreography pattern hoạt động cho việc phát triển ứng dụng dịch vụ siêu nhỏ mới (greenfield). Ngoài ra, pattern này phù hợp khi có ít người tham gia giao dịch hơn.
Sau đây là một số framework có sẵn để triển khai choreography pattern:
Axon Saga – một nền tảng nhẹ và được sử dụng rộng rãi với các microservices dựa trên Spring Boot.
Eclipse MicroProfile LRA – triển khai các giao dịch phân tán trong Saga để vận chuyển HTTP dựa trên các nguyên tắc REST.
Eventuate Tram Saga – Saga orchestration framework cho các microservices dựa trên Spring Boot và Micronaut.
Seata – open-source distributed transaction framework với các distributed transaction services hiệu suất cao và dễ sử dụng.
7.4. Triển khai Saga Orchestration Pattern
Trong Orchestration pattern, một orchestrator duy nhất chịu trách nhiệm quản lý trạng thái giao dịch tổng thể.
Nếu bất kỳ microservices nào gặp lỗi, orchestrator sẽ chịu trách nhiệm thực hiện các giao dịch bù trừ cần thiết:
Mẫu dàn dựng Saga hữu ích cho kiến trúc phát triển ứng dụng microservice brownfield. Nói cách khác, mẫu này hoạt động khi chúng ta đã có một tập hợp các microservice và muốn triển khai Saga pattern trong ứng dụng. Chúng ta cần xác định các giao dịch bù trừ thích hợp để tiến hành pattern này.
Sau đây là một số framework có sẵn để triển khai orchestrator pattern:
Camunda là một framework dựa trên Java hỗ trợ tiêu chuẩn Business Process Model and Notation (BPMN) cho quy trình làm việc và tự động hóa quy trình (workflow and process automation.).
Apache Camel cung cấp triển khai cho Saga Enterprise Integration Pattern (EIP).
8. Kết luận
Trong bài viết này, chúng tôi thảo luận về Saga architecture pattern để triển khai các giao dịch phân tán trong ứng dụng dựa trên microservice.
Đầu tiên chúng tôi giới thiệu những thách thức của việc triển khai này.
Sau đó, chúng tôi khám phá two-phase commit protocol, một giải pháp thay thế phổ biến cho Saga, và xem xét hạn chế của nó trong việc triển khai các giao dịch phân tán trong các ứng dụng dựa trên microservice.
Cuối cùng, chúng tôi thảo luận về Saga architecture pattern, cách thức hoạt động của nó và hai cách tiếp cận chính để triển khai Saga pattern trong các ứng dụng dựa trên microservice.
Nguồn sưu tầm.