Xây dựng Microservices Event-Driven đang trở thành xu hướng kiến trúc phổ biến trong các hệ thống hiện đại nhờ khả năng mở rộng, linh hoạt và chịu tải cao. Tuy nhiên, khi chuyển từ Monolith sang Microservices, doanh nghiệp phải đối mặt với nhiều thách thức về dữ liệu, giao dịch và truy vấn phân tán.
Bài viết này chia sẻ kinh nghiệm triển khai kiến trúc Microservices Event-Driven với Go & CQRS, dựa trên mô hình thực tế được nhiều chuyên gia hệ thống lớn áp dụng.
1. Thách Thức Lớn Nhất Khi Triển Khai Microservices
Khi tách rời hệ thống thành các dịch vụ độc lập, mỗi dịch vụ sở hữu cơ sở dữ liệu (database) riêng biệt, lập trình viên thường đối mặt với 3 bài toán nan giải:
- Dữ liệu bị phân tán: Thông tin không còn nằm tập trung, khiến việc quản lý trở nên rời rạc.
- Giao dịch (Transaction) phức tạp: Các giao dịch hiện nay thường trải dài qua nhiều dịch vụ khác nhau, khó đảm bảo tính nhất quán.
- Truy vấn khó khăn: Việc join dữ liệu giữa các dịch vụ như trong kiến trúc Monolith là điều không thể.
Ví dụ thực tế: Một quy trình từ Đặt hàng → Thanh toán → Tạo hóa đơn diễn ra trên 3 dịch vụ và 3 database khác nhau, đòi hỏi một cơ chế phối hợp cực kỳ chính xác.
2. Giải Pháp: Bộ Đôi Event Sourcing & CQRS
Để giải quyết triệt để các thách thức trên, Shiju Varghese đề xuất áp dụng mô hình kiến trúc tiên tiến:
Event Sourcing – Lưu Trữ Sự Kiện Bất Biến
Thay vì chỉ lưu trạng thái hiện tại, Event Sourcing ghi lại mọi thay đổi dưới dạng một chuỗi các sự kiện (events) bất biến vào một Event Store.
- Các sự kiện như
OrderCreated,OrderPaid, hayOrderShippedđược coi là những "sự thật" (facts) không thể thay đổi. - Hệ thống có thể "replay" (phát lại) các sự kiện này để tái tạo trạng thái tại bất kỳ thời điểm nào trong quá khứ.
CQRS – Tách Biệt Lệnh Ghi Và Truy vấn
CQRS (Command Query Responsibility Segregation) phân tách hệ thống thành hai phần riêng biệt:
- Command side: Chuyên trách thực hiện thay đổi trạng thái (ghi event).
- Query side: Chuyên cung cấp dữ liệu đã được tối ưu hóa cho giao diện người dùng (UI) hoặc API.
- Việc tách biệt này cho phép ta sử dụng các mô hình dữ liệu hoặc database khác nhau để tối ưu hóa hiệu suất cho từng tác vụ ghi và đọc.
3. Stack Công Nghệ Đề Xuất (Go, gRPC, NATS & CockroachDB)
Để hiện thực hóa kiến trúc này, bộ công nghệ sau được lựa chọn nhờ tính hiệu năng và khả năng chịu tải cao:
- Go (Golang): Ngôn ngữ chủ đạo để xây dựng các dịch vụ nhờ tốc độ xử lý nhanh và hỗ trợ concurrency tốt.
- gRPC: Giao thức API hiệu suất cao giúp các microservices giao tiếp với Event Store một cách nhanh chóng.
- NATS Streaming: Đóng vai trò là hệ thống message-broker, chịu trách nhiệm publish và subscribe các sự kiện giữa các dịch vụ.
- CockroachDB: Database phân tán mạnh mẽ, được dùng để lưu trữ cả log sự kiện và các mô hình truy vấn (query models).
- Event Store: Dịch vụ chuyên biệt để ghi các sự kiện bất biến và đẩy chúng lên NATS.
4. Workflow Thực Tế Của Một Command
Quy trình xử lý một yêu cầu tạo đơn hàng sẽ diễn ra như sau:
- Client gửi request tạo đơn hàng (Order) tới HTTP API.
- API gọi đến Event Store thông qua gRPC để thực hiện lệnh tạo sự kiện
order-created. - Event Store lưu trữ sự kiện này vào CockroachDB (persist) và đồng thời publish sự kiện
order-createdlên NATS Streaming. - Các Subscribers (dịch vụ thanh toán, kho vận...) sẽ nhận sự kiện từ NATS để tiếp tục thực hiện các logic nghiệp vụ tương ứng.
Kết Luận
Việc kết hợp Event Sourcing và CQRS không chỉ giúp tách rời (decouple) các dịch vụ mà còn giúp hệ thống Microservices trở nên linh hoạt và dễ kiểm soát hơn trong môi trường dữ liệu phân tán. Đây là hướng đi chuẩn mực cho các hệ thống yêu cầu độ tin cậy và khả năng mở rộng cao trong năm 2026.