CQRS pattern - Thiết kế kiến trúc CQRS Command Query Responsibility Segregation

 Command : câu lệnh, ở đây có thể hiểu là các Task, CronJob chạy ngầm

Query : Việc thao tác với cơ sở dữ liệu

Responsibility : Chịu trách nhiệm

Segregation : chia tách

Nói đơn giản là Thiết kế cấu trúc hệ thống gồm hai phần riêng biệt : 

- Chỉnh sửa dữ liệu chạy riêng

- View dữ liệu chạy riêng





Ví dụ 1 use case như sau : bạn làm 1 app quản lý các order ( đơn đặt hàng) của 1 nhà hàng online. Đơn đặt hàng này dựa trên các thông tin có liên quan sau : 

1- Khách hàng ( ví dụ người đặt hàng)

2- Menu ( đặt món gì)

3 - Bếp (Bếp đã hoàn thành món ăn ngày giờ nào...)

4 - Delivery, Ship ( Đã ship đến cho khách chưa, ...)

5- Kế toán ( Khách đã trả tiền, thanh toán chưa...)

... vân vân và mây mây

App này có yêu cầu hiển thị chi tiết về đơn hàng như sau


Mã đơn hàng Người đặt Ngày đặt Địa chỉ ship Tình trạng đơn hàng Số tiền đã thanh toán
OD0001 Nguyễn Văn A Ngày đẹp trời Nhà mặt phố Đã ship xong 100k
OD0002 Nguyễn Văn B ... ... Bị Hủy Hủy rồi thì tiền nong gì?

Ví dụ để ra một bảng báo cáo như thế này về các đơn hàng, theo cách thiết kế cũ, chúng ta sẽ làm như sau


1 - Thiết kế các bảng gồm

1.1 Bảng khách hàng

1.2 Bảng Menu 

1.3 Bảng Delivery

1.4 Bảng Order

...

2- Viết các service cập nhật dữ liêu cho từng bảng

3 - Viết 1 service order, vừa cập nhật trạng thái bảng order, vừa query join các bảng để ra được báo cáo trên

Việc này thì không gì sai, thực ra nhiều ứng dụng vẫn làm cho đến khi dữ liệu trở nên ngày một lớn, và đòi hỏi các báo cáo trở nên phức tạp hơn, lúc đó ngồi nặn óc viết câu query, join các bảng là 1 việc rất khó khăn, nhức đầu, ....


Để khắc phục nhược điểm này, mô hình CQRS ra đời, về cơ bản sẽ như sau

1 - Tất cả những service liên quan đến cập nhật dữ liệu được thiết kế riêng

2- Những service nào có trách nhiệm lấy dữ liệu để hiển thị được thiết kế riêng

và những service này được chạy dưới dạng các command ( có thể hiểu là các thao tác chạy ngầm, được gọi tuần tự trên quêue, hoặc cronjob,...). Cụ thể như sau


Khi Có đơn đặt hàng từ khách, những thông tin sau sẽ được lưu ở 1 bảng riêng, hoặc 1 cơ sở dữ liệu riêng biệt (cái này tùy theo thiết kế của bạn),  được gọi là Materialized View 

View này lưu các thông tin như ở bảng trên. Chúng ta thiết kế các command như sau

Command 1 : chạy Order service, sau khi lưu xong các thông tin liên quan đến order (mã order, ngày đặt)

Command 2  : chạy Customer service, lưu các thông tin liên quan đến Khách hàng

....

Các command này chạy ngầm

cuối cùng sẽ có 1 command, ví dụ như

Command n : chạy OrderReport service, sẽ tổng hợp lại thông tin của các command 1,2...n-1 đã chạy, và lưu ra Materialized View


Việc cuối cùng của chúng ta là đọc thông tin từ Materialized View và hiển thị


Các bạn có thể tìm hiểu thêm tại

https://microservices.io/patterns/data/cqrs.html

https://viblo.asia/p/tim-hieu-command-and-query-responsibility-segregation-pattern-WAyK8o4o5xX

Comments

Popular posts from this blog

Các câu hỏi liên quan đến restful API

Active record (Eloquent) trong Laravel và Data Mapper (Doctrine) trong Symfony

CI/CD diagram, infra