همه نوشته‌ها

طراحی سیستم برای تازه‌کارها؛ چیزهایی که کاش می‌دانستم

مدل‌های ذهنی برای درک بهتر سیستم‌های توزیع‌شده

تصویر جلد مقاله طراحی سیستم برای تازه‌کارها؛ چیزهایی که کاش می‌دانستم

چرا طراحی سیستم مهم است

بیشتر توسعه‌دهندگان تازه‌کار سال‌ها قابلیت می‌سازند، بی‌آنکه فکر کنند وقتی یک سرویس به‌جای ۱۰ کاربر هم‌زمان، ۱۰ هزار کاربر داشته باشد چه اتفاقی می‌افتد. طراحی سیستم تمرین فکر کردن در همین مقیاس است.

مدل ذهنی اصلی: بده‌بستان‌ها

هر تصمیم معماری یک بده‌بستان است. پاسخ کاملاً درست و مستقلی وجود ندارد؛ تنها پاسخی وجود دارد که با توجه به محدودیت‌های شما درست است.

بده‌بستان‌های رایج:

  • سازگاری در برابر دسترس‌پذیری (قضیه CAP)
  • تأخیر در برابر توان عملیاتی
  • هزینه ذخیره‌سازی در برابر هزینه محاسبه
  • پیچیدگی در برابر مقیاس‌پذیری

از مبانی شروع کنید

توزیع بار

هر سرور منفرد سقفی دارد. وقتی به آن می‌رسید دو راه پیش رو دارید:

  1. مقیاس‌دهی عمودی — ماشین قوی‌تر که محدود و گران است
  2. مقیاس‌دهی افقی — ماشین‌های بیشتر که به توزیع‌کننده بار نیاز دارد
Request → [Load Balancer] → [Server 1]
                         → [Server 2]
                         → [Server 3]

Round-robin ساده‌ترین راهبرد است. وقتی زمان پردازش درخواست‌ها متفاوت باشد، روش کمترین اتصال انتخاب بهتری است.

پایگاه‌های داده

بیشتر برنامه‌ها با یک پایگاه داده رابطه‌ای آغاز می‌شوند و این انتخاب خوبی است. مهم است بدانیم چه زمانی گزینه‌های دیگر را بررسی کنیم:

  • نسخه‌های فقط‌خواندنی — مقیاس‌دهی بار خواندن بدون پیچیدگی sharding
  • شاردینگ پایگاه داده — تقسیم افقی داده؛ پیچیده، اما در مقیاس بسیار بزرگ ضروری
  • NoSQL — زمانی که داده واقعاً سندمحور است یا توان نوشتن بسیار بالا لازم داریم

لایه‌های کش

Redis را در نوشته قبلی بررسی کردیم. الگوی کلی چنین است:

Request → Cache hit? → Yes → Return cached data
                    → No  → DB query → Cache result → Return data

CDNها برای فایل‌های ثابت نقش کش دارند و روزبه‌روز بیشتر برای پاسخ‌های API نیز استفاده می‌شوند.

اجزایی که هر سیستم به کار می‌گیرد

  1. DNS — نام دامنه را به نشانی IP تبدیل می‌کند
  2. توزیع‌کننده بار — ترافیک را میان سرورها پخش می‌کند
  3. سرورهای وب — HTTP را مدیریت می‌کنند و بهتر است بدون وضعیت باشند
  4. سرورهای برنامه — منطق کسب‌وکار را دارند و در صورت امکان بدون وضعیت‌اند
  5. کش (Redis یا Memcached) — ذخیره‌سازی سریع در حافظه
  6. پایگاه داده — ذخیره‌سازی پایدار
  7. صف پیام (RabbitMQ یا Kafka) — ارتباط ناهم‌زمان سرویس‌ها
  8. ذخیره‌سازی شیء (S3) — فایل‌ها و داده‌های حجیم
  9. CDN — تحویل توزیع‌شده جهانی فایل‌های ثابت

مثال عملی: طراحی کوتاه‌کننده URL

این یک پرسش کلاسیک طراحی سیستم است. مرحله‌به‌مرحله بررسی‌اش کنیم.

نیازمندی‌ها:

  • کوتاه کردن URLها (برای مثال ariankoochak.com → ak.io/x7z)
  • هدایت بازدیدکننده به URL اصلی
  • مدیریت ۱۰ میلیون URL جدید و یک میلیارد هدایت در روز

نکته کلیدی: روزانه ۱۰ میلیون نوشتن، یعنی حدود ۱۱۵ در ثانیه، و یک میلیارد خواندن، یعنی حدود ۱۱٬۵۰۰ در ثانیه داریم. نسبت بار خواندن به نوشتن ۱۰۰ به ۱ است.

طراحی:

  • برای هر URL یک شناسه هفت‌کاراکتری Base62 بسازید
  • نگاشت را در پایگاه داده اصلی ذخیره کنید
  • به‌طور گسترده کش کنید؛ بیشتر هدایت‌ها بارها به لینک‌های محبوب می‌رسند
  • اگر تأخیر حیاتی است، منطق هدایت را روی CDN اجرا کنید

منابع پیشنهادی

  • کتاب Designing Data-Intensive Applications نوشته Martin Kleppmann؛ یکی از بهترین منابع این حوزه
  • خبرنامه ByteByteGo؛ توضیح‌های تصویری طراحی سیستم
  • وبلاگ High Scalability؛ گزارش‌های معماری سیستم‌های واقعی

طراحی سیستم بیش از حفظ کردن، به کنجکاوی و مطالعه صبورانه پاداش می‌دهد. از بده‌بستان‌ها آغاز کنید تا الگوها به‌تدریج روشن شوند.