CAP Theorem ရဲ့ AP vs CP

Distributed system တွေဆောက်တဲ့အခါ mental model အဖြစ်ထားကြတဲ့ CAP Theorem ဆိုတာရှိတယ်။ System မှာ Network ပြဿနာတွေ ရှိလာခဲ့မယ်ဆိုရင် distributed system တွေက consistency (system တခုလုံးက state တညီတည်းရှိတာ), availability (system ဆက်လည်ပတ်နေနိုင်တာ), partition (system ကို peer to peer ဖြန့်ကျက်ထားနိုင်တာ) ဆိုပြီး အရည်အသွေး ၃ ခုရှိတဲ့အထဲက ကြိုက်တဲ့ ၂ ခုကိုပဲ ပြေလည်စေနိုင်ပြီး ကျန်တခုကိုတော့ စတေးရလိမ့်မယ်။ တခုရှိတာက system တခုက distributed ဖြစ်ပြီဆိုကတည်းက partition လုပ်လိုက်ရတာပဲ။ single node မဟုတ်တော့ဘူးပေါ့။ အဲဒီတော့ မဖြစ်မနေ partition ဖြစ်နေပြီးသားမို့ Network ပြဿနာတွေက ရှောင်လို့ရတာ မဟုတ်တော့သလို CAP မှာလည်း ရွေးစရာ C နဲ့ A ပဲကျန်တယ်။ Consistency ဆိုတဲ့ system ကဘယ်အချိန်မှာဖြစ်ဖြစ် တူညီတဲ့ state ကိုပဲပေးနိုင်တာကို ရွေးမလား ဒါမှမဟုတ် Availability ဆိုတဲ့ ဘယ်အခြေအနေမှာဖြစ်ဖြစ် လိုအပ်တဲ့ response ကိုပေးနိုင်တယ်ဆိုတာမျိုးကို ရွေးမလား။

Cloud Native ခေတ်မှာ System အများစုကတော့ AP ဖြစ်တဲ့ Availability နဲ့ Partition ကိုရွေးပြီး Consistency ကို trade လိုက်ကြတာများတယ်။ ဒါပေမယ့် အဓိကက ကိုယ်ဘယ်ဟာကိုပဲရွေးရွေး ဘာကြောင့်ရွေးသလဲ။ ဘယ်လို အကျိုးဆက်တွေ ရှိလာနိုင်လဲဆိုတာကို နားလည်ထားဖို့ လိုပါတယ်။

AP system တွေက network fault ဖြစ်တဲ့အခါမှာ cluster ထဲက node တွေအနေနဲ့ ပြင်ပကို unified state မပေးနိုင်တဲ့ system မျိုးတွေဖြစ်တယ်။ ဥပမာ မာလာရှမ်းကောဆိုင်မှာ AYA Pay နဲ့ တသိန်းဖိုးရှင်းလိုက်တယ်ဆိုပါတော့။ customer ရဲ့ account balance မှာနဂို ၅ သိန်းရှိရာက ၁ သိန်းနှုတ်သွားတယ်။ ဒါပေမယ့် ဆိုင်ရှင်ရဲ့ account balance မှာ ၄၂ သိန်းရှိရာက ၄၃ သိန်းဖြစ်မလာဘူး။ ဒါဆို ဒီ transaction က backend မှာများ fail သွားသလား တွေးနိုင်တယ်။ AYA ကနောက်ကွယ်မှာ Relational Database တမျိုးမျိုး သုံးပြီး SELECT နဲ့ UPDATE statement တွေကို transaction တခုတည်းအဖြစ် အုပ်ထားမယ်ဆိုတာ သံသယဖြစ်စရာ မရှိပါဘူး။ ဒီတော့ fail ရင်အကုန် fail လိမ့်မယ်။ တဝက်တပျက် succeed ဖြစ်သွားတယ်ဆိုတာမျိုး မရှိပါဘူး။

ဥပမာ ကိုယ့်ဆီက 1 သိန်းနုတ်တဲ့ UPDATE ပဲ success ပြပြီး သူ့ဆီ 1 သိန်းထည့်တဲ့ UPDATE က failed သွားတယ်ဆိုတာမျိုး transaction မှာမရှိနိုင်ဘူးပေါ့။ အဆိိုးဆုံး အခြေအနေကို တွေးကြည့်လို့ transaction အလယ်မှာ process crash သွားတယ်ဆိုရင်တောင်မှ database recovery ဖြစ်ပြီး ပြန်တက်လာတဲ့အချိန်မှာ binlog/sequence log တွေကနေ မပြီးသေးတဲ့ transaction ကိုဆက်လုပ်သွားမှာပါ။ လုပ်လို့မရဘူးဆို ကိုယ့်ဆီကို တသိန်းပြန်ပေါင်းထည့်ပေးပြီး rollback/abort လိုက်မှာပါပဲ။

ဒီနေရာမှာ တခုသတိထားစေချင်တာက ACID က Consistency နဲ့ CAP က Consistency မတူဘူးဆိုတာပါ။ အပေါ်က transaction မှာ User A ဆီက ပိုက်ဆံနုတ်သွားရင် User B ဆီမှာ ပေါင်းရမယ်ဆိုတာက Business Consistency ဖြစ်တယ်။ ဒါမျိုး rule မျိုးကို Application level မှာပဲထိန်းရမှာဖြစ်ပြီး distributed system မကလို့ single-node ပဲဖြစ်ဖြစ် database က ဘာမှလုပ်ပေးလို့မရပါဘူး။ database ကအာမခံပေးနိုင်တာက UPDATE statement 2 ​ကြောင်းက အတူတူ fail ရင် fail မယ်၊ မ fail ဘူးဆို အတူတူ succeed ဖြစ်မယ်ဆိုတဲ့ Atomicity ကိုပဲ ပေးနိုင်ပါတယ်။ တဖက်မှာ CAP Theorem ရဲ့ Consistency ဆိုတာက data ဖတ်တဲ့အခါ up-to-date အဖြစ်ဆုံး data ကိုမြင်ရမယ်လို့ အာမခံတဲ့ strong consistency ကိုဆိုလိုတာဖြစ်တယ်။

ဒါဆို ဒီဥပမာမှာ ဘယ်နေရာက မှားသွားနိုင်တာလဲ။ မှားနိုင်တာတွေ အများကြီးရှိတဲ့အထဲက ဖြစ်နိုင်ချေတခုက AP vs CP tradeoff ပါ။

AYA Pay က massive scale လို့မဆိုနိုင်ပေမယ့် သာမန် web service တွေထက်လည်း အဆပေါင်းများစွာ scale ကြီးတဲ့ system တခုဖြစ်တယ်။ ဒီတော့ သူတို့ရဲ့ Customer Balance data တွေကို အကြောင်းအရင်း ၃ ခုကြောင့် Database တွေခွဲပြီး သိမ်းထားဖို့ လိုအပ်ပါတယ်။ ပထမတချက်က မမျှော်လင့်ထားတဲ့ ဖြစ်ရပ်ဆိုးတခုခု (ဥပမာ Data Center တခုလုံး မီးလောင်သွားတာ၊ ငလျင်ထဲပါသွားတာ၊ နာရီပိုင်းလောက် လျှပ်စစ်ပြတ်သွားတာ စသဖြင့်) ဖြစ်လာတဲ့အခါ system ဆက်လည်ပတ်နိုင်အောင် data တွေကို တနေရာတည်းမှာ ထားဖို့ မလုံလောက်ပါဘူး။ ဒုတိယတချက်က database server တခုက တိုးလာတဲ့ load ကိုလိုက်ဖို့ CPU နဲ့ RAM နှစ်ဆထည့်လိုက်တာနဲ့ throughput ၂ ဆတက်လာတာ မဟုတ်ပါဘူး။ တတိယအချက်က ဒုတိယအချက်မှာ ပြောခဲ့သလို vertical scaling လုပ်လိုက်တာက network round trip တွေဆီက latency ပြဿနာကိုလည်း ဖြေရှင်းမပေးနိုင်ပါဘူး။

အဲဒီတော့ ဖြစ်နိုင်တဲ့ design တွေထဲက တခုက Database ကို INSERT နဲ့ UPDATE စတဲ့ write statement တွေလက်ခံဖို့ primary database တလုံးထားပြီး SELECT လို read statement တွေလက်ခံဖို့ replica database တွေခွဲထားလိုက်တာပါပဲ။ User A က User B ကိုပိုက်ဆံလွှဲတဲ့အခါ transaction တခုလုံးက primary database ပေါ်မှာဖြစ်သွားပါတယ်။ ဒီ primary database ကသူ့နောက်က replica တွေကို log တွေလှမ်းပို့ပြီး update တွေ sync ခိုင်းတယ်။ primary database က Data Center 1 မှာရှိပြီး replica တွေက Data Center 1 နဲ့ Data Center 2 မှာရှိကြတယ် ဆိုပါ​တော့။ DC 1 နဲ့ DC 2 ကြားမှာ network partition ဖြစ်သွားခဲ့ရင် မာလာရှမ်းကောဖိုး တသိန်းလွှဲလိုက်တဲ့ transaction က DC 2 က replica ဆီမှာရှိဦးမှာ မဟုတ်သေးပါဘူး။

အဲဒီအချိန်မှာ User A နဲ့ B နှစ်ယောက်လုံးက သူတို့ရဲ့ Mobile app ထဲ refresh လုပ်ကြည့်တဲ့အခါ User A က DC 1 ကို route ခံရပြီး User B က DC 2 ကိုရောက်သွားတယ် ဆိုပါတော့။ primary database နဲ့ DC 1 က replica မှာ transaction ကရှိနှင့်ပြီးသည့်တိုင် User B က DC 2 မှာဒါကိုမြင်ရဦးမှာ မဟုတ်ပါဘူး။ ဒီတော့ customer ကို သူ့ account ထဲပိုက်ဆံဝင်မလာဘူးလို့ ထင်ရစေတယ်။ ပိုဆိုးသွားနိုင်တာက တကယ်လို့ User နှစ်ယောက်လုံးသာ DC 2 ကို route ခံခဲ့ရမယ်ဆို User A ကသူပိုက်ဆံလွှဲလိုက်တာ မရဘူးလို့ ထင်ပြီး နောက်တကြိမ် ထပ်လွှဲလိုက်ရင် ၂ သိန်းလွှဲမိရက်သား ဖြစ်သွားပါလိမ့်မယ်။ တကယ်လို့ AYA Pay သာ AP system တခုမဟုတ်ပဲ CP system ဖြစ်ခဲ့မယ်ဆိုပါတော့။ DC 2 က replica က DC 1 နဲ့အဆက်အသွယ်ပြတ်သွားတဲ့အတွက် User B ဆီက query ကို reject ပါလိမ့်မယ်။ ဒါဆို User B ရဲ့အမြင်မှာ AYA Pay App မှာ error တက်နေတယ်။ သုံးလို့မရဘူးဆိုတဲ့ အမြင်ကိုပေးပါလိမ့်မယ်။

ဒါက စောစောက ဥပမာမှာ ဖြစ်နိုင်ချေတွေ အများကြီးရှိတဲ့အထဲက တခုကိုပဲ ဆန်းစစ်ကြည့်ရသေးတာဖြစ်တယ်။ ဒီနေရာမှာ subtle detail တခုရှိတာက system က Consistency ကိုစတေးရတဲ့အခါ up-to-date data ကိုမြင်ရပြီးတဲ့ user က data အဟောင်းပြန်မြင်ရရင် အဆင်ပြေမလားဆိုတဲ့ မေးခွန်းပါ။

တကယ်လို့ ကိုယ့် system ရဲ့ nature ကအဲလိုရတယ်ဆိုရင် read statement တွေကို ကြိုက်တဲ့ replica ဆီဖြန့်ပို့လို့ရနိုင်မယ်။ ဒါဆို user တွေက DC 1 ရော၊ DC 2 ကိုပါ route ခံရနိုင်တဲ့အတွက် User A ကသူ့ acc ထဲ ၅ သိန်းဖြစ်လိုက်၊ ၄ သိန်းပြန်ဖြစ်သွားလိုက်၊ User B ကလည်း သူ့ acc ထဲ ၄၃ သိန်းဖြစ်လိုက်၊ ၄၂ သိန်းပြန်ဖြစ်သွားလိုက်နဲ့ မြင်နေရမှာပါ။ ဒါက user တွေကို တော်တော်လေး နားမလည်နိုင်ဖြစ်စေမှာမို့လို့ up-to-date data မ​မြင်ရရင်နေ၊ မြင်ရပြီးမှ stale data အဟောင်းတော့ ပြန်မပြဘူးဆိုရင်တော့ user တွေအတွက် read replica ကို Application က application level မှာတင် ရွေးချယ်ပေးဖို့ လိုပါတယ်။ ဒါမှသာ User B ကသူ့အတွက် သတ်မှတ်ထားပေးတဲ့ DC 2 က replica ဆီအမြဲရောက်မှာဖြစ်ပြီး Data Center 2 ခုကြားက network fault မပြေလည်မချင်း Balance 42 သိန်းဆိုတာကိုပဲ မြင်ရဦးမှာဖြစ်တယ်။

ဒါကြောင့် distributed system တွေဆောက်တဲ့အခါ consistency (system တခုလုံးက state တညီတည်းရှိတာ), availability (system ဆက်လည်ပတ်နေနိုင်တာ), partition (system ကို peer to peer ဖြန့်ကျက်ထားနိုင်တာ) ဆိုပြီး အရည်အသွေး ၃ ခုရှိတဲ့အထဲက ကျွန်တော်တို့တွေက ကိုယ့် application/system ရဲ့ business လိုအပ်ချက်အပေါ် မူတည်ပြီး trade off တွေ consistency tuning တွေလုပ်သွားနိုင်ဖို့ လိုအပ်သလို နောက်ကပါလာမယ့် အကျိုးဆက်တွေကိုလည်း နားလည်ထားရပါလိမ့်မယ်။