thắc mắc làm sao để giải quyết vấn đề Service A publish X msg/s, B consume Y(Y<X nhiều) msg/s

trunglq

Member
Em chào các thím, em đang học SysDesign thì gặp câu hỏi như này, ngoài scale B lên 2 instance thì có cách nào không ạ?
Em cảm ơn các thím
 
Em chào các thím, em đang học SysDesign thì gặp câu hỏi như này, ngoài scale B lên 2 instance thì có cách nào không ạ?
Em cảm ơn các thím

đang dùng relayid cơ mà tùy broker chứ nhỉ nếu hỗ trợ exactly 1 thì làm sao thiếu đc nhỉ

Sent using vozFApp
 
Theo mình có đọc qua thì kafka có cơ chế read batch theo min size và max size, không biết case này có áp dụng được không

via theNEXTvoz for iPhone
 
  • Nếu rate của consumer và producer biến động, có những lúc Y > X nhiều nhưng cũng có khi nhỏ hơn, và xét trên 1 khoảng thời gian đủ dài thì tổng msg consumed > produced thì dùng queue để làm trung gian hứng message rồi consumer sẽ đọc từ queue.
  • Apply rate-limiting trên producer, nếu không thể bỏ bớt msg và msg producing rate luôn lớn hơn thì mình nghĩ k còn cách khác ngoài scale consumer lên.
 
Đầu tiên X > Y nhiều thì thằng consume đang chậm hơn nhiều thằng produce.

Làm rõ với người phỏng vấn.
1) Có chấp nhận việc hạn chế việc produce như sử dụng ratelimit chẳng hạn ~ tương đương với sẽ ko nhận thêm yêu cầu khi hệ thống đạt giới hạn. Gọi api thì trả ra HTTP 429 chẳng hạn.
2) Nếu phải nhận request thì phải hỏi việc X>Y là trong ngày lúc nào cũng thế hay chỉ thời điểm cao điểm thôi.
  1. Nếu chỉ diễn ra trong 1 khoảng thời gian cao điểm + chấp nhận việc request có thể xử lý sau đó mà không phải phản hồi ngay -> nhét 1 message queue vào giữa là được, producer cứ push và consumer xử lý dần.
  2. Nếu diễn ra thường xuyên hoặc phải xử lý nhanh để trả phản hồi thì phải làm cho consumer nhanh lên -> tìm nguyên nhân chậm và xử lý như thêm tài nguyên, node, tối ưu lại luồng xử lý ...
 
Về cơ bản thì không có silver bullet cho vấn đề này. Giống như bài toán cung / cầu của thị trường vậy, tất cả giải pháp đều là ad-hoc, cuối cùng thì X / Y nó phải cân bằng với nhau mới là chân ái. Tuy nhiên nếu consider thêm business domain thì có thể suggest vài hướng:

1. Tăng Y lên. Hơi counter-intuitive nhưng thật ra rất khả thi và hay bị bỏ qua:
  • Tăng phần cứng, nâng ram, nâng CPU lên. Đôi khi như vầy là quá đủ, code lằm code lốn
  • Hoặc optimize con consumer, đã tối ưu hóa xử lý chưa. Các tác vụ network / IO có non-blocking chưa. Có thể implement xử lý song song nhiều message (Executor, Thread pool...) được hay không ? Đã cache dữ liệu chưa ?
  • Tối ưu chung về structure hệ thống: Ví dụ nếu consumer chỉ consume message để tính toán counter hoặc một số cấu trúc đơn giản => Dùng Redis sẽ nhanh hơn nhiều. Nếu consumer là write-heavy liệu có thể dùng Cassandra.... Nói chung là đôi khi vấn đề không nằm ở producer / consumer mà cần phải nhìn rộng hơn.

2. Giảm X xuống. Một số giải pháp như rate-limiting, throttling, dropping message có thể apply tùy vào từng nhu cầu cụ thể. Ví dụ:
  • Đôi khi nhiều message nhưng ta không cần phải xử lý hết mà chỉ quan tâm đến message cuối cùng. Ví dụ: message user update location - consumer nhận và ghi lại location cuối cùng. Vậy ta có thể drop bớt các message quá gần nhau đi và chỉ gửi / xử lý message cuối cùng.
  • Hoặc các message không cần quá realtime, việc xử lý một lượng lớn message quá gần nhau là vô nghĩa mà ta chỉ cần xử lý các message cách nhau một khoảng thời gian vừa phải là đủ. Ví dụ: ghi nhận các thời điểm active của 1 user, đôi khi process ở mức mili second là không cần thiết.
  • Tránh xử lý các message trùng lắp: Đặc biệt hay gặp ở các message không đến từ user action mà từ hệ thống. Ví dụ: error message cứ đến 1 hàm nào đó là lỗi, ngày bắn cả tr message nhưng giống hệt nhau
  • Còn nhiều case nữa nhưng lười viết...
=> Một điểm đáng quan tâm của cách này là phải để ý xem việc limit này nên đặt ở vị trí nào: producer, consumer hay tạo thêm một middle layer. Mỗi phương pháp đều có lợi và bất lợi riêng nên cần phải consider kĩ.

3. Batching: Dồn nhiều message lại rồi xử lý 1 lần. Trong các tác vụ aggregation thì việc xử lý batching luôn mang lại hiệu quả lớn hơn hẳn so với xử lý single message. Nó không chỉ giúp consume được nhiều message hơn (tăng Y) mà còn cải thiện performance đáng kể. Ví dụ: Consumer chỉ đơn giản nhận message rồi lưu vào DB => Batching 1000 message rồi mới insert 1 lần. Hoặc consumer chỉ đơn giản nhận rồi tính tổng số request theo từng user: Batching 10k message lại rồi cộng dồn 1 lần.

Edit: À cũng nên tính thêm trường hợp là nhiều message không phải do high traffic mà là do bị bug / bị hack / bị DDOS => Thì đi xử lý mấy cái đó đi chứ chả lq gì producer / consumer mà chửi tụi nó tội nghiệp/.
 
Em cảm ơn các thím nhiều, em đã học hỏi đc thêm rất nhiều từ mọi người, cái này là em đang cbi cho pv môn sysDesign thôi ạ, nên cũng ko có biết cao kiến gì thêm. Một lần nữa cảm ơn mọi người đã chỉ dẫn tận tình
 
Back
Top