Nối tiếp nội dung về tối ưu cho kiến trúc Microservices, lần này mình sẽ đề cập đến một bài toán cũng gặp rất nhiều và có thể coi là giải pháp khác của bài trước là Export dữ liệu. Nếu như ở bài trước, việc export dữ liệu được diễn ra ở Frontend (JS) bao gồm tải dữ liệu có phân trang và đóng gói excel thì có những hạn chế sau:
- Nếu dữ liệu nhiều sẽ ảnh hưởng đến frontend vì memory có giới hạn
- Quá trình export này là đồng bộ, tức là nếu đóng tab hoặc reload trang là tải lại từ đầu
- Tính năng cần xuất dữ liệu này chưa có giao diện frontend, kéo theo thêm việc làm (làm trang danh sách) nếu chỉ muốn export.
Do những hạn chế trên nên cách đây ít lâu vẫn còn 1 vài tính năng Export dữ liệu phải được thực hiện ở phía server và rất khó đưa xuống Frontend vì yếu tố phức tạp của lấy dữ liệu và số lượng dữ liệu lớn. Những tính năng export kiểu cũ này kéo theo hạn chế rõ ràng là script sẽ chạy lâu và luôn kích hoạt cơ chế slow log vì có những script chạy cả tiếng đồng hồ chưa xong file excel để export và Memory chiếm vài GB cho 1 process. Nếu chỉ cần vài khách hàng vào thực hiện tính năng Export thì sẽ dẫn đến hệ thống treo, và trong môi trường không kiểm soát được thì làm sao có những yêu cầu dạng “cậu chỉ được export vào lúc X giờ”…
Do những hạn chế của cả 2 hình thức công việc như trên nên Teamcrop đã hoàn thiện giải pháp khá tối ưu, hiệu quả và an toàn cho người và của, và đó chính là nội dung của bài chia sẻ này.
Big Task là gì?
Trước tiên, cần phải định nghĩa Big Task là gì để dễ dàng thảo luận. Big Task ám chỉ những task khi thực hiện sẽ tốn khá nhiều thời gian và tài nguyên (Memory, CPU..). Ví dụ như những tính năng export tồn kho hàng chục ngàn sản phẩm, SKU, import hàng ngàn sản phẩm, đơn hàng, hoặc đi spam email, sms…
Một số đặc điểm của hệ thống BigTask mà Teamcrop đã xây dựng là:
- Có thể chia nhỏ
- Kiểm soát được tiến độ công việc (Bao nhiêu % hoàn thành..)
- Bất đồng bộ: người dùng có tắt trình duyệt hay tắt máy thì hệ thống vẫn cứ làm việc
- Có khả năng retry
Big Task được vận hành thế nào?
Tất nhiên, mỗi task bây giờ được định nghĩa là một row trong Database, mỗi task sẽ có 3 giai đoạn:
- Bước 1: Chuẩn bị
- Bước 2: Xử lý dữ liệu
- Bước 3: Kết thúc
Bước chuẩn bị thường được trigger bởi người dùng và từ giao diện frontend, như submit form chứa thông tin. Ở bước chuẩn bị này chính là giai đoạn quan trọng nhất, bao gồm khởi tạo tổng số record cần xử lý (để kiểm soát progress), ghi nhận các cấu hình cần thiết cho task như số lượng record cần xử lý 1 trang, các dữ liệu cài đặt khi người dùng submit form và một bước quan trọng là khởi tạo 1 file excel chỉ có header (không có dữ liệu) ở môi trường local.
Bước xử lý dữ liệu là công việc chính liên quan đến nhiệm vụ, như lấy dữ liệu để insert vào file excel theo từng batch, ví dụ nếu task được giao mỗi trang lấy 100 record thì chỉ lấy 100 record và đẩy nhiệm vụ trang tiếp theo vào Messsage Queue (ví dụ RabbitMQ), hệ thống Queue worker sẽ chịu trách nhiệm thực thi trang tiếp theo dựa vào nội dung trong message đã được đẩy vào queue.
Bước kết thúc chính là đảm bảo dữ liệu đã đầy đủ và đưa các file cần thiết vào hệ thống, đối với Teamcrop là gọi File Service để lưu file tạm ở trên, thông báo và kết thúc task để đánh dấu task hoàn tất.
Như vậy, với sự giúp đỡ của kiến trúc Message Queue thì những task lớn có thể chia nhỏ và tiến trình được kiểm soát, đặc biệt là giúp cho hệ thống không có những script chạy quá lâu và tốn quá nhiều tài nguyên. Hiện tại bên Tuấn đã bắt đầu migrate dần các task dạng này vào mô hình Big Task của mình để tăng performance của hệ thống.
Hy vọng bài viết này sẽ giúp các bạn đối phó với một trong những bài toán đau đầu khi scale.
Rất hay và dễ hiểu anh (y)