နားလည်ထားရမယ့် အချက်
User request တစ်ခုကနေ trigger ဖြစ်တဲ့ အလုပ်တချို့ — confirmation email ပို့တာ၊ upload လုပ်ထားတဲ့ ပုံကို resize လုပ်တာ၊ search index entry ပြန်တည်ဆောက်တာ — ဟာ user ကို response ပြမခင် ပြီးစီးဖို့ မလိုအပ်ပါဘူး၊ ဒါပေမဲ့ naive implementation တစ်ခုက ဒါကို synchronous inline လုပ်ပြီး user ကို ရလဒ်ကို သူတို့ဂရုမစိုက်တောင် step အနှေးဆုံးအထိ စောင့်ခိုင်းတတ်ပါတယ်။ Message queue တစ်ခုက ဒါကို decouple လုပ်ပါတယ် — web server (producer) က fast, essential အလုပ်ကိုပဲ လုပ်ပြီး task ကိုဖော်ပြတဲ့ message သေးသေးလေးကို queue ပေါ်ပို့ကာ user ဆီ ချက်ချင်း response ပြန်ပေးလိုက်ပါတယ်။ Worker process (consumer) သီးသန့်တစ်ခုက အားလပ်တဲ့အချိန် queue က message တွေကို ဆွဲထုတ်ပြီး slow work ကို သီးခြားလုပ်ဆောင်ပါတယ်။ ဒါက producer နဲ့ consumer ကို time နဲ့ identity ကြားမှာ decouple လုပ်ပေးပါတယ် — နှစ်ဖက်စလုံး တစ်ချိန်တည်း online ဖြစ်ဖို့ မလိုပါဘူး၊ worker ကိုလည်း web server နဲ့ သီးခြားစီ scale လုပ်နိုင်ပါတယ်။ Catch ကတော့ delivery guarantee ပါ — real queue အများစုက at-least-once delivery ကိုပဲ ကတိပေးနိုင်ပါတယ်၊ ဆိုလိုတာက message တစ်ခုက ပို့ပြီး process လုပ်တာ တစ်ကြိမ်ထက်ပိုနိုင်ပါတယ် (worker task အလယ်မှာ crash ဖြစ်ပြီး retry ဖြစ်လို့) — ဒါကြောင့် consumer တွေက idempotent ဖြစ်ရပါမယ် — message တစ်ခုတည်းကို နှစ်ကြိမ် process လုပ်တာက တစ်ကြိမ်ပဲ process လုပ်သလို result တူညီရမယ်၊ side effect ထပ်ဖြစ်စေလို့ မရပါဘူး။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Tutorial Platform မှာ learner တစ်ယောက် course တစ်ခု ပြီးဆုံးတဲ့အခါ congratulation email ပို့တာ၊ PDF certificate ထုတ်တာ၊ leaderboard update လုပ်တာ၊ search အတွက် learner profile ပြန် index လုပ်တာ စတဲ့ အလုပ်များစွာ ဖြစ်ရပါတယ် — ဒါတွေကို learner က ဘာမှစောင့်စရာမလိုပါဘူး။ ဒါအားလုံးကို synchronous လုပ်ရင် 'course complete' mark လုပ်တာ နှေးကွေးနေမယ်၊ email service ခဏတာ down သွားရင် အားလုံး fail ဖြစ်သွားနိုင်ပါတယ်။ ဒီအစား web server က 'course-completed' message တစ်ခုတည်း queue ပေါ်ထားပြီး ချက်ချင်း response ပြန်ပေးလိုက်ပါတယ်။ Worker သီးခြားတွေက ဒီ message ကို consume လုပ်ပြီး downstream task တစ်ခုချင်းစီကို ကိုင်တွယ်ကာ fail ရင် သီးခြားစီ retry လုပ်ပါတယ် — PDF generator နှေးရင် leaderboard update ကို မထိစေဘူး၊ email service ခဏ down ရင် certificate generation ကို မထိစေပါဘူး။
အတူတူ စမ်းရေးကြည့်မယ်
REQUEST FLOW
User --> [Web Server / Producer]
|
| 1. enqueue "course-completed" message
v
+----------+
| QUEUE |
+----------+
|
| 2. respond to user IMMEDIATELY (doesn't wait)
v
User sees "Course complete!" (fast)
meanwhile, asynchronously:
|
+--------+--------+--------+
v v v v
Worker1 Worker2 Worker3 Worker4
(email) (PDF cert)(leader- (search
board) reindex)
If Worker1 crashes mid-task -> message redelivered -> retried
(consumer must be idempotent: processing twice = same end result)User ဟာ background task အားလုံးပြီးအောင် မစောင့်ဘဲ ချက်ချင်း response ရရှိပြီး worker တွေက slow work ကို သီးခြားစီ async လုပ်ဆောင်ကြောင်း ပြသပါတယ်။၅ မိနစ် စမ်းကြည့်
Tutorial Platform မှာ learner တစ်ယောက် quiz တစ်ခု submit လုပ်တဲ့အခါ score calculate လုပ်တာ (user စောင့်ရမယ်) နဲ့ analytics event log တာ (user မစောင့်စရာမလို) ကို ခွဲခြားပါ — ဘယ်ဟာက synchronous ဖြစ်သင့်ပြီး ဘယ်ဟာက queue ကနေ async လုပ်သင့်လဲ ဆုံးဖြတ်ပါ။
သတိလေးတစ်ချက်
Worker consumer ကို idempotent မလုပ်ဘဲ message ထပ်ရောက်လာရင် (at-least-once delivery ကြောင့်) congratulations email ကို ထပ်ခါထပ်ခါ ပို့မိတာလို duplicate side effect ဖြစ်တတ်ပါတယ်။
'Critical' အလုပ် (ဥပမာ payment ခေါင်းစဉ်တပ်တာ) ကို queue ကနေ async လုပ်လိုက်ရင် user က payment success ကို မြင်ပေမယ့် backend processing fail သွားနိုင်ပြီး error handling/monitoring မထားရင် ဘယ်သူမှ မသိတဲ့ silent failure ဖြစ်တတ်ပါတယ်။
Wikipedia — Message queue — System Design