Scalability: Vertical vs Horizontal
বড় machine নাকি বেশি machine
তোমার app চালু হলো, user বাড়ছে। একদিন দুপুরে সব ধীর হয়ে গেল, কিছু request timeout হচ্ছে। Server আর পারছে না। এখন দুইটা পথ: server টাকে বড় করো, নাকি আরও server যোগ করো। এটাই scaling এর মূল প্রশ্ন, আর system design এর প্রায় সব কিছু এখান থেকে শুরু।
#Vertical scaling: বড় machine
২ CPU আর ৪ GB RAM এর server থেকে ১৬ CPU আর ৬৪ GB RAM এর server এ যাওয়া। একে বলে scale up।
সুবিধা:
- Code এ কিছু বদলাতে হয় না
- সহজ: একটা machine, একটা জায়গায় সব
- Database এর জন্য প্রায়ই প্রথম আর সবচেয়ে কার্যকর পদক্ষেপ
অসুবিধা:
- সীমা আছে। সবচেয়ে বড় machine এর চেয়ে বড় কিছু কেনা যায় না।
- দাম দ্রুত বাড়ে। দ্বিগুণ শক্তির machine এর দাম প্রায়ই দ্বিগুণের বেশি।
- একটাই machine মানে একটাই ভাঙার জায়গা (single point of failure)। ওটা বন্ধ হলে সব বন্ধ।
- বড় করতে প্রায়ই restart লাগে, মানে কিছুক্ষণ বন্ধ।
#Horizontal scaling: বেশি machine
একটা বড় server এর বদলে অনেকগুলো সাধারণ server, সামনে একটা load balancer যে request ভাগ করে দেয়। একে বলে scale out।
সুবিধা:
- প্রায় সীমাহীন: আরও machine যোগ করতে থাকো
- একটা নষ্ট হলে বাকিরা চালিয়ে যায় (high availability)
- চাপ অনুযায়ী বাড়ানো-কমানো যায় (autoscaling): রাতে ২টা, দুপুরে ১০টা
- Update দেওয়া যায় একটা একটা করে, বন্ধ না করে (rolling deploy)
অসুবিধা:
- জটিলতা: load balancer লাগে, অনেক machine চালানো আর দেখা লাগে
- Code কে stateless হতে হবে (নিচে বিস্তারিত)
- Database এর ক্ষেত্রে অনেক কঠিন, কারণ data ভাগ করতে হয় (Sharding)
#কোনটা কখন
| পরিস্থিতি | পরামর্শ |
|---|---|
| শুরুর app, অল্প user | একটা মাঝারি server, scaling এর চিন্তা পরে |
| App server এ চাপ | Horizontal। App server সহজেই stateless করা যায়। |
| Database এ চাপ | প্রথমে vertical (বড় machine), তারপর read replica, cache, শেষে sharding |
| হঠাৎ spike (sale, result প্রকাশ) | Horizontal + autoscaling, সাথে cache আর queue |
বাস্তবে প্রায় সব বড় system দুটোই মেশায়: app server horizontal, database প্রথমে vertical।
#Stateless: horizontal scaling এর শর্ত
ধরো user Rahim login করলো। তার login এর তথ্য (session) রাখা হলো server ১ এর memory তে। পরের request এ load balancer তাকে পাঠালো server ২ এ। Server ২ জানে না Rahim কে, তাই আবার login চাইলো। 😕
Stateless মানে server নিজের memory বা disk এ এমন কিছু রাখে না যা পরের request এ লাগবে। সব "state" থাকে বাইরে:
| State | কোথায় রাখবে |
|---|---|
| Login session | JWT token (client এর কাছে) বা Redis |
| Upload করা file | Object storage (S3 ধরনের), server এর disk এ না |
| Cart, অস্থায়ী data | Redis বা database |
| Cache | Redis (প্রতিটা server এর নিজস্ব memory cache এ না, অন্তত গুরুত্বপূর্ণগুলো) |
| Background কাজ | Queue (Celery + Redis/RabbitMQ) |
#Sticky session: শর্টকাট, কিন্তু সমাধান না
Load balancer কে বলা যায় "Rahim কে সবসময় server ১ এ পাঠাও" (sticky session)। এতে stateful code ও চলে। কিন্তু server ১ বন্ধ হলে Rahim এর session হারায়, আর load সমানভাবে ভাগ হয় না। এটা পুরনো system চালানোর জন্য অস্থায়ী উপায়, নতুন design এ stateless ই লক্ষ্য। (WebSocket এর মতো স্থায়ী connection এর ক্ষেত্রে অবশ্য একটা নির্দিষ্ট server এর সাথে লেগে থাকা স্বাভাবিক।)
#Autoscaling
Cloud এ নিয়ম দেওয়া যায়: "CPU গড়ে ৭০% এর বেশি ৫ মিনিট থাকলে আরেকটা server যোগ করো, ৩০% এর নিচে থাকলে একটা কমাও।"
মনে রাখার বিষয়:
- নতুন server চালু হতে সময় লাগে (কয়েক সেকেন্ড থেকে কয়েক মিনিট)। হঠাৎ ১০ গুণ traffic এলে autoscaling ধরতে পারার আগেই ভেঙে পড়তে পারে। জানা ঘটনার (sale, খেলা) আগে থেকে বাড়িয়ে রাখো।
- নিচের অংশ ও যেন পারে। App server ২০টা হলো, কিন্তু database একটাই। ২০টা server এর সব connection database কে ডুবিয়ে দিতে পারে। Scale করলে bottleneck শুধু সরে যায়, চলে যায় না।
- সর্বোচ্চ সীমা দাও। না হলে কোনো bug বা আক্রমণে হাজার server চালু হয়ে বিশাল bill আসতে পারে।
#Bottleneck খোঁজা
Scaling শুরুর আগে জানো আসলে কোথায় আটকাচ্ছে। ভুল জায়গায় টাকা খরচ করা সাধারণ ভুল।
| লক্ষণ | সম্ভাব্য কারণ | প্রথম চেষ্টা |
|---|---|---|
| App server এর CPU ১০০% | ভারী হিসাব, অদক্ষ code | Profile করো, তারপর horizontal scale |
| App CPU কম, কিন্তু response ধীর | Database বা বাইরের API এর অপেক্ষা | Query দেখো (EXPLAIN), index, cache |
| Database CPU বেশি | ধীর query, index নেই, একই query বারবার | Index, cache, read replica |
| Memory শেষ হচ্ছে | Memory leak, বড় data একসাথে load | Pagination, generator, leak খোঁজা |
| মাঝে মাঝে সব আটকে যায় | Connection pool শেষ, lock, ধীর বাইরের API এ timeout নেই | Timeout, pool size, circuit breaker |
#অনুশীলন
#নিজেকে যাচাই করো
Vertical scaling এর দুইটা বড় সমস্যা কী?
একটা সর্বোচ্চ সীমা আছে (সবচেয়ে বড় machine এর চেয়ে বড় হয় না), আর একটাই machine হওয়ায় সেটা নষ্ট হলে পুরো system বন্ধ (single point of failure)। সাথে দামও দ্রুত বাড়ে।
Stateless server মানে কী, আর horizontal scaling এ কেন জরুরি?
Server নিজের memory বা disk এ পরের request এর জন্য দরকারি কোনো তথ্য রাখে না, সব রাখে বাইরে (Redis, database, token)। এতে load balancer যেকোনো request যেকোনো server এ পাঠাতে পারে, আর একটা server বন্ধ হলে কিছু হারায় না।
উপরের অনুশীলনের `login_attempts` code দুইটা server এ কী সমস্যা করবে?
প্রতিটা server এর আলাদা dict থাকবে। কেউ ৫ বার ভুল করলে হয়তো ৩ বার server ১ এ আর ২ বার server ২ এ গেছে, কোনোটাই ৫ এ পৌঁছায়নি, ফলে limit কাজ করবে না। Redis এর মতো shared store এ গোনা রাখতে হবে।
App server বাড়ালে সবসময় system দ্রুত হয় না কেন?
Bottleneck অন্য কোথাও থাকতে পারে, যেমন database। বেশি app server মানে database এ আরও বেশি চাপ, ফলে অবস্থা আরও খারাপ হতে পারে। আগে মেপে দেখতে হয় কোথায় আটকাচ্ছে।
চিহ্ন দিলে sidebar আর রোডম্যাপে এই অধ্যায়ের station ভরে যাবে।