Đây là một số kinh nghiệm của tôi khi thiết kế hệ thống microservice theo hướng Domain Driven Design. Mỗi microservice sẽ làm một số nhiệm vụ cụ thể, có liên quan chặt chẽ đến nhau.
Không nhất thiết mỗi microservice phải có một database riêng rẽ. Mỗi microservice sẽ được ghi / đọc vào một schema cùng tên. Hệ thống của chúng tôi có khoảng 35 microservice. Chỉ một số microservice đặt biệt sẽ kết nối database riêng của mình để tối ưu tốc độ I/O hoặc dùng loại cơ sở dữ liệu phù hợp như MongoDB hay Elastic Search thay cho cơ sở dữ liệu Postgresql truyền thống. 
  • Microservice A không được phép thay đổi dữ liệu trong schema của microservice B và ngược lại.
  • Microservice A toàn quyền thay đổi dữ liệu trong schema dành riêng cho nó
  • Microservice A muốn thay đổi dữ liệu schema không phải của nó, hay gửi event message vào queue, microservice nào quan tâm sẽ subscribe và tự thay đổi.
  • Khuyến khích mỗi schema chỉ có dưới 8 bảng. Nhiều hơn 8 hãy xem xét để tách chúng ra thành 2 microservice
Trong hầu hết các microservice có một số đối tượng dữ liệu cần phải lưu vết lại lịch sử. Chúng tôi sử dụng Event sourcing thay vì Audit Log như trước đây. Trong Event Sourcing có một khái niệm là Aggregate. Aggregate không nhất thiết phải ánh xạ phải một bảng vật lý, mà nó thể hiện một đối tượng hoàn chỉnh, có thể tồn tại độc lập. Trạng thái gần nhất của Aggregate được mô tả ở phần Query (trong CQRS) là một nhóm 1-3 bảng quan hệ với nhau.
 
Một Aggregate ứng với một đối tượng danh từ. Mà chúng ta cần lưu giữ lịch sử sự kiện tác động lên nó.
Mỗi Aggregate cần thể hiện một tập nghiệp vụ liên quan chặt chẽ theo dòng thời gian với nhau.
 
  • User /*Tài khoản người dùng*/ {UserCreated, UserEmailChanged, UserAvatarUploaded, UserRoleAssigned, UserDisabled, UserRemoved}
  • BankAccount /*Tài khoản ngân hàng*/ {AccountCreated, AccountDeposited, AccountWithDrew, AccountClosed}
  • Course /*Khóa học*/ {CourseCreated, CourseStructureUploaded, CourseAuthorAdded, CourseAuthorRemoved....}
  • Class /*Lớp học*/ {ClassCreated, ClassTrainerUpdated, ClassTypeChanged, ClassRoomChanged, ClassCommencingDateChanged, ClassCompleted}
  • Order /*Đơn hàng*/ {OrderCreated, OrderItemAdded, OrderItemRemoved, OrderItemCountUpdated, OrderDeliverAddressUpdated, OrderNotesUpdated, OrderPaymentDeposited, OrderPaymentWithDraw, OrderCancelled}
Trong một microservice, có thể có nhiều loại Aggregate. Chúng ta tạo 1 bảng event_store để lưu event stream.

Bảng này cần có những cột sau:
  1. aggregate_id: global unique id. Có nên sử dụng auto-increment id không? Không. Bởi hệ thống microservice cần đảm bảo tính duy nhất trên toàn bộ các loại CSDL, replicas
  2. aggregate: tên phân loại aggregate. Ví dụ "User", "BankAccount", "Course", "Class"... Nên chọn tên ngắn, là danh từ.
  3. event: tên của event tác động lên aggregate, hãy luôn kết thúc bằng động từ thể quá khứ.
  4. version: integer tăng dần khi có thêm event mới bổ xung vào (append)
  5. timestamp: date time sự kiện xảy ra
  6. tenantid: đánh dấu event của tenant nào.
 
Hãy chọn Aggregate khôn ngoan, đặt tên Aggregate và Event theo quy chuẩn code sẽ nhanh, dễ bảo trì.
Ảnh một hệ thống CQRS bao gồm phần Event Sourcing bên trái