> سلام :) این ترجمه فارسی از یک منبع انگلیسی زبان هست. هدف از این ترجمه کمک به کسانی است که تا حدودی با زبان انگلیسی مشکل دارند( تا بتونن از محتویات آموزشی اون استفاده کنند). با این حال، اگر در زمینه برنامه نویسی و حوزه کامپیوتر فعالیت میکنید حتما به دنبال اون باشید که توانایی خودتون رو در مطالعه متنهای انگلیسی تقویت کنید. آخر هر بخش سعی کردم ترجمه اصطلاحات لازم رو بیارم که کمکی کرده باشم در یادگیری شما.
> در ترجمه این متن، سعی کردم که مفهوم رو منتقل کنم و از ترجمه کلمه به کلمه، که ممکنه باعث پیچیدگی بشه، خودداری کردم. با این حال در ادامه نحوه همکاری مشخص شده. خوشحال میشم کمک کنید تا این منبع رو به خوبی برای هم زبونای خودمون آماده کنیم. ممنون :)
<palign="center">
<imgsrc="http://i.imgur.com/jj3A5N8.png">
<br/>
</p>
## هدف
> یادبگیریم که چه طوری سیستم های مقیاس-بزرگ طراحی کنیم
> برای مصاحبه طراحی سیستم آماده بشیم
### یادبگیریم که چه طوری سیستم های مقیاس-بزرگ طراحی کنیم
اینکه چه طوری یک سیستم مقایس-بزرگ را طراحی کنیم کمک میکنه که یه مهندس بهتری بشیم. مبحث طراحی سیستم، یک بحث گستردهای هست و برای این موضوع **منابع زیادی داخل وب پراکنده وجود داره** . این مخزن یک مجموعهی منظم و ساختاریافته از منابعی هست که به شما کمک میکنه، یاد بگیرید چهطوری سیستمهای بسازید که بتونه در مقایس بزرگ کار کنه.
> System Design: طراحی سیستم, Large-Scale: مقیاس-بزرگ, Repository | Repo. : مخزن
### از جامعه متنباز یادبگیریم
این پروژه متن باز در حال کامل شدن هست و در حقیقت یک پیشنویسه.
از [کمک](#همکاری) به این پروژه استقبال میشه
> Open-Source: متن باز, Contributing : کمک کردن
### برای مصاحبه طراحی سیستم آماده شویم
علاوهبر آزمون کدنویسی در مصاحبه، در بسیاری از شرکتهای تکنولوژی طراحی سیستم یکی از **قسمتهای لازم** در فرآیند **مصاحبه فنی** است.
**سوالهای مصاحبه طراحی سیستم را تمرین کنید** و جوابهاتون رو با **راهکارهای نمونه** داده شده **مقایسه** کنید: توضیحات،کد و دیاگرامها
موضوعات بیشتر برای آمادگی در مصاحبه:
* [راهنمای مطالعه](#راهنمای-مطالعه)
* [چگونه به سوالات طراحی سیستم در مصاحبه پاسخ بدیم؟](#نحوه-برخورد-با-سوالات-مصاحبه-طراحی-سیستم)
محتویاتی که نیاز به پرداختن بیشتر و اضافه کردن مطلب دارند در بخش [تحت توسعه](#تحت-توسعه) هستند. قسمت قوانین همکاری رو ببینید
> [قوانین همکاری](CONTRIBUTING.md).
## فهرست موضوعات طراحی سیستم
> خلاصهای از مباحث متنوع طراحی سیستم به همراه مزیتها و معایت آنها. در حقیقت هرچیز یک تریدآف یا به عبارتی تعادلی بین مزایا و معایب هست. هر بخش شامل لینکهایی به منابعی هستند که به طور مفصلتر به موضوع مربوطه پرداختن.
بیشتر کاندیداهای باتجربه ازشون انتظار میره که بیشتر در مورد طراحی سیستم بدونن. معمارها یا تیم لیدرها ممکنه ازشون انتظار بره که از آدمهای معمولی بیشتر بدونن. توی کمپانیهای شاخ ممکنه که چند دور مصاحبه برای طراحی داشته باشند
خیلی کلی شروع کنید و بعد توی یه زمینهای برید و عمیق بشید. این آموزش باعث میشه که شما در مورد مباحث مختلف طراحی سیستم یکم دانش کسب کنید. آموزشهایی که در ادامه میاد رو بر اساس موارد مختلفی مثل زمانی که دارید، تجربهای که دارید، سمتی که دارید براش مصاحبه میرید و اینکه چه کمپانی دارید میرید تنظیم کنید.
* **اگر زمان مصاحبه کوتاهی دارید** - هدفتون باشه رو این که به صورت **موضوعی** مباحث طراحی سیستم رو بخونید از اینجا. برید سراغ حل **بعضی** از سوالات مصاحبه.
* **اگر زمان مصاحبتون متوسطه** - هدفتون باشه که هم به صورت **موضوعی** و هم **یکم عمقی** مباحث رو پیگیری کنید.توی این مرحله **تعداد زیادی** مساله حل کنید..
* **اگرزمان مصاحبتون زیاده** - هدفتون باشه که به صورت **موضوعی** و با **عمق زیاد** به مباحث طراحی سیستم بپردازید. سعی کنید تا میتویند سوالات بیشتری حل کنید.
| برای درک کلی از این که سیستمها به چه صورتی کار میکنن به قسمت [فهرست موضوعات طراحی سیستم](#فهرست-موضوعات-طراحی-سیستم) مراجعه کنید | :+1: | :+1: | :+1: |
| براساس کمپانی که قصد دارید برید مصاحبه، پستهای [وبلاگ مهندسی](#وبلاگهای-مهندسی-کمپانیها) اون رو مطالعه کنید | :+1: | :+1: | :+1: |
| قسمت [معماری دنیای واقعی](#معماری-های-دنیای-واقعی) را به خوبی مطالعه کنید | :+1: | :+1: | :+1: |
| به طور کامل روی قسمت [سوالات مصاحبه طراحی سیستم با پاسخ](#سوالات-مصاحبه-طراحی-سیستم-همراه-با-پاسخ) کارکنید | بعضی قسمتاش | قسمت زیادش | تا اونجایی که میشه |
| به طور کامل روی قسمت [سوالات مصاحبه طراحی شئ گرا با پاسخ](#سوالات-مصاحبه-طراحی-شئ-گرا-به-همراه-پاسخ) کار کنید | بعضی قسمتاش | قسمت زیادش | تا اونجایی که میشه |
مصاحبه طراحی سیستم شبیه یه مکالمهای هست که جواب قطعی و مشخصی نداره. انتظار میره با جوابهایی که میدید روندش رو مشخص کنید. یعنی این که با جوابش صرفا یک بله یا خیر نیست و با جواب شما روند مصاحبه تغییر میکنه
شما میتونید از روشی که در ادامه میاد برای پیشبرد روند مصاحبه استفاده کنید. برای این کار به طور کامل روی قسمت [سوالات مصاحبه طراحی سیستم با پاسخ](#سوالات-مصاحبه-طراحی-سیستم-همراه-با-پاسخ) کار کنید البته به صورت قدمهایی که در ادامه آورده شدن
نیازمندیها و اسکوپ مسالهای که قراره حل کنید رو دربیارید. یه سری سوال بپرسید تا بیاد دستتون که محدودیتها و کاربردهای این سیستم چیه و بعد روی فرضیات بحث کنید.
- چه کسی قراره از این سیستم استفاده کنه؟
- اون کسایی که استفاده میکنن، چطوری قرار استفاده کنند؟
- چقدر کاربر توی این سیستم هست؟
- سیستم چی کار میکنه؟
- ورودی و خروجی سیستم چیا هستن؟
- چقدر داده قراره که سیستم هندل کند؟
- چه تعداد درخواست در ثانیه انتظار داریم؟
- چه نسبتی از خوندن به نوشتن مورد انتظارمونه؟
### قدم ۲: یک طراحی سطح بالا درست کنید
یه طراحی سطح بالا و کلی از اجزای مهم بکشید
- اجزای اصلی و ارتباطشون رو بکشید
- ایده هاتون رو باهاش تایید کنید و بررسی کنید ببینید درسته یا نه
سراغ جزئیات بیشتر، برای هر المان اصلیتر و مهم، برید. به عنوان مثال اگر ازتون خواستن که [یک سرویس برای کوتاه کردن لینک](#طراحی-سرویس-کوتاه-کردن-لینک) طراحی کنید، موارد زیر رو بررسی کنید:
روشها و ترید-آف های محتمل رو مورد بحث و بررسی قرار بدید. هر چیزی یک ترید-آف هست. مشکلات و باتلنک ها رو با استفاده از [اصول طراحی سیستم های مقایس پذیر](#فهرست-موضوعات-طراحی-سیستم) مورد بررسی و چالش قرار بدید و بیان کنید.
یک سرویس رو **مقایس پذیر** میگیم وقتی که متناسب با منابعی که به سیستم اضافه میکنیم **کارایی** اون هم افزایش پیدا بکنه. به طورکلی منظور از افزایش کارایی اینه که تعداد کار بیشتری رو انجام بدیم اما ممکنه که کارهای باحجم بزرگتر هم بتونه هندل کنه مثل زمانی که مجموعه داده هامون زیاد میشه و رشد میکنه<sup><ahref=http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html>1</a></sup>
*شبکه ها قابل اتکا و اطمینان نیستن، بنابریان لازمه که شما تحمل پارتیشن رو پشتیبانی کنید و داشته باشید. بنابراین باید بین یکپارچگی و دسترس پذیری یک ترید-آف انجام بدید و یکی رو انتخاب کنید*
صبر و انتظار برای گرفتن جواب از یک نود پارتیشن شده ممکنه باعث بشه تا تایم-اوت بگیریم.اگر سیستم شما نیاز داره که به صورت اتمیک بخونه و بنویسیه ، این مدل یک انتخاب مناسبه
این مدل انتخاب خوبیه اگر شما نیاز به [یکپارچگی موکول](#یکپارچگی-موکول) دارید یا سیستم نیاز داره که مستقل از خطاهای خارج از خودش(خطاهای خارجی) به علمکردش ادامه بده
زمانی که تعدادی کپی از دادههای یکسان داریم، با مجموعهای از انتخابها درباره این که چطوری کلاینتها رو سینکرون نگه داریم موجه میشیم تا همه یک نمای یکسان از داده داشته باشند. با توجه به تعریف یکپارچگی از [تئوری کپ](#CAP-تئوری) - هر عملیات خوندن، نزدیک ترین نسخه از داده نوشته شده رو میگردونه یا خطا میده.
این روش در سیستمهای نظیر مِم-کش-دی دیده میشه. یکپارچگی ضعیف در سیستمهای با نیاز بلادرنگ مثل وویپ، ویدیو چت و بازیهای بلادرنگ چندنفره کاربرد داره. برای مثال، اگر شما پشت تلفن باشید و چند ثانیه ارتباط قطع بشه و بعد دوباره وصل بشید، اون چیزی که گفته شده رو دیگه از دست دادید.
در این مدل، هارت-بیت بین سرور فعال و سرور غیر فعال که درحالت آماده باشه، رد و بدل میشه. اگر هارت-بیت قطع بشه سرور غیرفعال آی-پی سرور فعال رو دراختیار میگیره و درخواستها رو هندل میکنه.
طول زمان پایین بودن به دو نوع معین میشه، یا اینکه سرور غیر فعال در حالت به اصطلاح هات در انتظاره یا نیاز داره از حالت به اصطلاح سرد شروع به کار کنه. فقط سرور فعال ترافیک رو هندل میکنه.
اگر سرورها به صورت عمومی روی اینترنت قابل دسترسی باشن، دی-اِن-اِس باید آی-پی هر دو سرور رو بدونه. اگر سرورها در شبکه داخلی باشن، لایه برنامه باید از حضور این دو سرور آگاهی داشه باشه.
دی-اِن-اِس به صورت سلسله مراتبی هست و تعداد کمی سرور اصلی در لایههای بالا وجود داره. روتر یا آی-اِس-پی شما اطلاعات مربوط به دی-ان-اس هایی که برای جستجو استفاده میشن رو در اختیار شما میزارن. دی-ان-اس های لایه پایینتر معمولا این نگاشت بین نام دامنه و آی-پی رو کش میکنن به خاطر این که انتشار تغییرات در دی-ان-اس کنده، که ممکنه بعد از مدتی اعتبار این نگاشتها از بین بره . نتایجی که از دی-ان-اس برای شما میاد ممکنه که در مرورگر یا سیستم عامل برای مدت مشخصی کش بشه، به این مدت مشخص تایم-تو-لیو گفته میشه
* سرویس دی-ان-اس اخیرا مورد حمله دی-داس قرارگرفته و باعث شده تا دسترسی کاربران به وب سایتها قطع بشه، وب سایتهایی نظیر توییتر - به اینصورت که کاربرا آی-پی توییتر رو نمیتونستن پیدا کنن
یک شبکه توزیع محتوا یا سی-دی-ان یک شبکه توزیع شده از پروکسی سرورهاست که محتوا را از مکانهایی که به کاربر نزدیکتره به دستشون میرسونه. به طور کلی فایلهای ایستا مثل اِچ-تی-اِم-اِل، جاوااسکریپت و سی-اِس-اِس، عکس، ویدیو از طریق سی-دی-ان به کاربر داده میشه. با این حال سی-دی-ان هایی نظیر کلود-فرانت که برای شرکت آمازون است محتوای غیر ایستا یا داینامیک رو هم پشتیبانی میکنه. عملیات سوال از دی-ان-اس برای یه سایت به کاربر میگه که باید به کدوم سرور متصل بشه.
پوش سی-دی-ان زمانی که سرورشما تغییری روی محتوا داشته باشه، تغییرات رو میگیره. در این حالت، شما مسوول آماده کردن محتوا برای سی-دی-ان هستید، باید محتوا رو مستقیم آپلود کنید روی سی-دی-اِن و یو-آر-اِل ها رو دوباره نویسی کنید که به سی-دی-ان اشاره کنه. میتونید تنظیم کنید که چه زمانی محتوایی که گذاشتید مدت استفادش از بین بره و چه زمانی آپدیت بشه. محتوا زمانی آپلود میشه که یا جدید باشه یا تغییر پیدا کرده باشه. اینکار باعث کاهش ترافیک میشه ولی افزایش میزان حافظه هم داره.
سایتهایی که ترافیک کمی دارند یا محتوایی دارند که آپدیت نمیشه اغلب اوقات با این مدل پوش سی-دی-ان به خوبی کار میکنن. به جای اینکه طی یه بازهی مشخصی همینطور از سرور محتوا آورده بشه توی سی-دی-اِن، محتوا یکبار در سی-دی-ان گذاشته میشه
وقتیکه کاربر اولین درخواست برای یک محتوای جدید رو میده، پول سی-دی-ان اون محتوا جدید رو از سرور شما میگیره . شما محتوا رو روی سرورتون میزارید و یو-آر-ال هاش روی سی-دی-ان تنظیم میکنید. تا وقتی که محتوا روی سی-دی-ان کش بشه، این کار باعث میشه درخواستها کندتر بشن .
یک تایم-تو-لیو مدت زمانی که محتوا باید کش بشه رو مشخص میکنه. پول سی-دی-اِن میزان استورج روی سی-دی-اِن رو کم میکنه اما میتونه ترافیک اضافی هم ایجاد کنه اگر فایلها قبل از این که به سی-دی-اِن بیان مدت کش اونها منتقضی بشه.
سایتهای با ترافیک سنگین خیلی خوب با این مدل پول سی-دی-ان کار میکنن چون که با آخرین درخواست برای محتوای تازه درخواست شده روی سی-دی-اِن مواجه میشه، ترافیک به صورت یکسان پخش میشه.
لودبالانسرها درخواست هایی که از سمت کاربران میاد رو بین منابع محاسباتی که هست مثل اپلیکیشن سرورها یا پایگاه دادهها توزیع میکنه. در هر کدوم از این حالات، لودبالانسر پاسخ درخواست رو از اون منبع محاسباتی به کاربر برمیگردونه. لودبالانسر ها در مورد زیر موثر هستند:
* **SSL termination** - درخواست هایی که از سمت کاربر میاد را رمزگشایی میکنه و جوابهایی که باید سرور بده رو هم رمزنگاری میکنه بنابراین سرورها لازم نیست تا این عملیاتهای سنگین محاسباتی رو انجام بدن
لودبالانسرهای لایه ۴ به اطلاعاتی که در لایهی ترسنپورت است نگاه میکنند و تصمیم میگیرن که چهطوری درخواستها رو پخش کنند. به طورکلی یعنی نگاه به اطلاعاتی نظیر مبدا درخواست، آی-پی مقصد و پورت هایی که در هدر وجود دارد، اما به محتوای پکتی که ارسال میشود نگاهی نمیشود. این نوع لودبالانسرها پکتهای شبکه را به سرورهای بالادستی ارسال و یا از آنها دریافت میکنن که به این صورت عملیات ترجمه آدرس شبکه انجام میشه.
لودبالانسرهای لایه ،۷ به لایهی برنامه نگاه میکنند و تصمیم میگیرند که چهطوری درخواست ها رو پخش کنند. این کار میتونه با استفاده از داده هایی که در هدر، محتوای پیام و کوکیهاست صورت بپذیره. این لودبالانسرها ترافیک شبکه رو تموم میکنه یعنی تا تهش میگیره، پیام رو میخونه و یک تصمیم برای توزیع بار میگیره و بعدش یک کانکشن به سروری که حاصل تصمیمش هست ایجاد میکنه. برای مثال، یه لود بالانسر لایه ۷ میتونه ترافیکهای مربوط به ویدیو رو به یک سرور بفرسته درحالیکه ترافیکهایی که مربوط به قبضهای پرداختی میشه رو به یک سرور دیگه ای که از نظر امنیتی قوی تر هست بفرسته.
با احتساب هزینهای که بابت انعطاف پذیری، لودبالانسینگ لایه ۴ نیاز به منابع و زمان کمتری داره نسبت به لایه ۷ ، با این حال کاراییش روی سیستمهای مدرن معمولی میتونه کم اثر باشه.
> Upstream: بالادستی, Downstream: رو به پایین. سروری که ازش دانلود میشه بیشتر, Horizontal Scaling: مقایس کردن افقی, Vertical Scaling: مقایس کردن عمودی
لودبالانسرها میتونن کمکی باشن برای اسکیل کردن افقی و باعث افزایش کارایی و دسترس پذیری بشن. اسکیل کردن با استفاده از سیستمهای عادی تر(تعداد ماشینها رو زیاد کنیم) خیلی از نظر هزینه به صرفه تره و باعث میشه تا دسترس پذیری بیشتری داشته باشیم تا این که بیایم یک سرور رو از نظر سخت افزاری ارتقا بدیم که معمولا گرون میشه، که بهش میگن **مقیاس کردن عمودی**. همینطور کار با یک سیستم عادی خیلی آسونتره واسه آدما تا اینکه بخوان با سیستمهای تخصصی شده برای کارای سطح کلان کار کنن.
* سرورهایی که معمولا ترافیک دانلودشوندگی دارند مثلا کشها یا پایگاهدادهها نیازدارند که تعداد کانکشنهای همزمان بیشتری رو نسب به سرورهای بالادستی هندل کنن
یک پروکسی معکوس، یک وب سروی هست که سرویسها داخلی رو تجمیع میکنه و باعث میشه که از بیرون به یک واسط یکارچه دسترسی داشته باشید. درخواستها از کلاینتها فوروارد میشن به سروری که میتونه درخواست رو جواب بده قبل از اینکه پروکسی معکوس جواب رو به کاربر برگردونه.
* **Increased security** - اطلاعات مربوط به سرورهای بک-اند رو مخفی میکنه، میتونه آی-پی ها رو بلک-لیست کنه و تعداد کانکشنها برای هر کلاینت رو محدود کنه
* **Increased scalability and flexibility** - کلاینتها فقط آی-پی پروکسی معکوس رو میبینن و این اجازه میده که شما سرورها تون رو اسکیل کنید یا تنظیماتش رو تغییر بدید
* **SSL termination** - میتونه درخواستهای ورودی رو رمزگشایی کنه و جوابهایی که سرور میفرسته رو رمز گذاری کنه تا این عملیات محاسباتی سنگین از دوش سرور برداشته بشه.
* نیاز به نصب گواهیهای ایکس.۵۰۹ رو روی هر سرور نداره
* یک دونه پروکسی معکوس میتونه یه شکست نقطهای باشه و با تنظیم کردن چندتا از این پروکسی سرورها(به عنوان مثال به صورت [فِیل-اُوِر](https://en.wikipedia.org/wiki/Failover)) باعث افزایش پیچیدگی میشه.
<i><ahref=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Source: Intro to architecting systems for scale</a></i>
</p>
> Single Responsibility Principle(SRP): اصل تک مسولیتی, Asynchronism: ناهمگامی, Worker: وُرکر
جداسازی لایه وب از لایه برنامه(که بعضا به عنوان لایه پلتفرم هم شناخته میشه) به شما این امکان رو میده که هر دو لایه رو مستقل از هم دیگه اسکیل کنید. اضافه کردن یک اِی-پی-آی جدید به لایهی برنامه مستقل از اینکه به وب سرور بخواید چیزی اضافه کنید انجام میشه.
**اصل تک مسولیتی** به دنبال این هست که سرویسهای کوچک و خودمختاری رو داشته باشه که بتونن باهم کار کنن. تیمهای کوچیک با سرویسهای کوچیک میتونن خیلی سریعتر و قویتر برای رشد برنامه ریزی کنند.
مرتبط با این بحث مبحث [میکروسرویسها](https://en.wikipedia.org/wiki/Microservices) است که میتونیم به عنوان مجموعهای از سرویسهای ماژولار، کوچک و قابل دیپلوی شدن مستقل تعریف کرد. هر سرویس یک پروسس یکتایی رو اجرا میکنه و از طریق یک پروتکل ارتباطی سبک و خوش تعریف با بقیه سرویسها در ارتباطه تا یک هدف تجاری رو به سرانجام برسونه <sup><ahref=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
پینترسنت به عنوان مثال میتونه سرویسهایی نظیر پروفایل کاربر، فید فالورها، فالورها، جستجو، اپلود عکس و ... رو داشته باشه.
سیستم هایی نظیر کنسول، ای-تی-سی-دی و زووکیپر با نگهداشتن اطلاعات در مورد اسمها و آدرسها و پورتهای سرویسها کمک کنن تا سرویسها بتونن همدیگه رو پیدا کنند.
هر دو سرویس کنسول و ای-تی-سی-دی یک ذخیرهساز کلید-مقدار در درون خودشون دارند که برای مواردی مثل ذخیره کردن کانفیگ ها و یا دادههایی که باید به اشتراک باشن، میتونه مفید باشه.
* اضافه کردن لایه برنامهای که کمترین وابستگی رو داشته باشه نیاز داره که در سطح معماری، عملیات و فرآیند، راهکار متفاوتی رو اتخاذ بکنه(در برابر حالت سیستم یکدست(
مستر هم عملیات خواندن و هم نوشتن رو انجام میده، نوشتنها رو برای ۱ یا تعداد بیشتری از اسلیوها تکرار میکنه، اسلیوها فقط عملیات خواندن رو انجام میدن. اسلیوها هم میتونن خودشون به صورت درختی یک سری اسلیو دیگه رو مثل خودشون تکرار کنن. اگر نود مستر خاموش بشه یا کلا از دسترس خارج بشه، سیستم کار خودش رو به صورت حالت فقط-خواندنی ادامه تا زمانی که یکی از این نودهای اسلیو تبدیل بشه به مستر یا یه مستر دیگه اضافه بشه.
* یه مکانیزم منطقی اضافی میخواد که بتونه نود اسلیو رو به نود مستر ارتقا بده
* به قسمت زیر برید چون نکاتش مشترک هست
* > [معایب: replication](#معایب-replication)
#### Master-master replication
هردوی مسترها عملیات خواندن و نوشتن را انجام میدن و زمانی که قصد انجام نوشتن دارند باهم هماهنگ میشن. اگر یکی از این مسترها پایین بیاد، سیستم میتونه با هر دو عملیات خواندن و نوشتن کارش رو ادامه بده.
* بیشتر سیستمهای مستر-مستر به صورت یکپارچه-ضعیف هستند(که مخالف اصل اَسید هست) یا باعث میشه که تاخیر عملیات نوشتن به خاطر نیاز به همگامسازی افزایش پیدا کنه.
* اگر نود مستر، قبل از اینکه عملیات نوشتنی که به تازگی اتفاق افتاده، نتونه رو نودهای دیگه تکرارکنه و در این حین پایین بیاد یا فِیل بشه، امکان این هست که دادهها از بین برن.
* عملیاتهای نوشتن روی نودهای خواندن تکرار میشه. اگر تعداد نوشتنها خیلی زیاد بشه نودهای خواندن به خاطر تکرار عملیات نوشتن هنگ میکنن و نمیتونن تعداد عملیاتهای خواندن زیادی انجام بدن
* هرچه تعداد نودهای اسلیو برای خواندن بیشتر باشه،باید تعداد بیشتری عملیات رو روی این نودها تکرار کنید که این خودش باعث میشه که شما یک لگ برای عملیات تکرار کردن داشته باشید
* روی بعضی سیستم ها نوشتن روی مستر میتونه به صورت ایجاد چند تِرِد برای نوشتن موازی انجام بگیره اما روی نودهای خواندنی فقط یک تِرِد میتونه عملیات نوشتن رو انجام بده که اونم به صورت پشت سرهم انجام میشه.
* ریپلیکیشن باعث میشه تا سخت افزار بیشتری اضافه بشه و پیچیدگی رو افزایش میده.
فِدِرِیشن ( یا تقسیم عملکردی) پایگاه دادهها رو براساس کاری که انجام میدن تکه تکه میکنه. برای مثال به جای یک پایگاهداده یک-تکه، شما میتونید ۳ تا پایگاه داده داشته باشید. **انجمن ها**،**کاربران** و **محصولات** باعث میشه تا تعداد عملیاتهای خواندن و نوشتن کم بشه و در نتیجه لگی که به خاطر عملیات ریپلیکیشن هست کاهش پیدا کنه. پایگاهدادههای کوچکتر باعث میشن تا دادههای بیشتری بتونه توی رم قراربگیره و این باعث میشه تا نتایج بیشتری، به خاطر اصل محلی بودن، در کش پیدابشن . بدون داشتن یک نود مستر مرکزی برای انجام عملیاتهای نوشتن میتونید تعداد نوشتنها رو به صورت موازی انجام بدید که این باعث میشه تا بازدهی بیشتری داشته باشید.
* اگر شِمای شما نیاز به توابع یا جداول بزرگ باشه موثر نیست
* شما باید لایه منطق برنامه تون رو به روز کنید تا برنامه بتونه بفهمه به کدوم پایگاهداده باید عملیات نوشتن یا خوندن رو بفرسته.
* انجام عملیات جوین از دوتا پایگاه داده میتونه خیلی پیچیده باشه. لینک زیر رو ببنید
* > [server link](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers): جوین ۲ تا پایگاه داده
شاردینگ دادهها رو در پایگاه دادههای مختلفی توزیع میکنه. این توزیع به این صورت هست که هر پایگاه داده فقط بخشی از داده اصلی رو در خودش داره. به عنوان مثال پایگاه داده مربوط به کاربران رو در نظر بگیرید، هرچه تعداد کاربران افزایش پیدا کنه تعداد شاردهایی که باید اضافه بشه به کلاستر هم افزایش پیدا میکنه.
مشابه مزیتهایی مربوط [فدریشن](#federation) ، شاردینگ باعث میشه تا تعداد ترافیک خواندن و نوشتن کم بشه و ریپلیکیشن رو هم کم کنه و وجود داده در کش رو هم افزایش میده. سایز ایندکسها هم کم میشه که بهطورکلی باعث میشه تا کارایی رو افزایش بده و سرعت کوئری ها رو زیاد کنه. اگر یک شاردی بیاد پایین، بقیهی شاردها هنوز کار میکنن با این حال شما باید یه فرآیند ریپلیکیشن اضافه کنید که داده از بین نره. شبیه فدریشن، هیچ نودمرکزی برای نوشتن به صورت پشت سرهم وجود نداره و باعث میشه تا نوشتن به صورت موازی صورت بگیره و بازدهی افزایش پیدا کنه.
دی-نرمالایزکردن در ازای افزایش چند عملیات نوشتن، سعی میکنه که باعث افزایش کارایی خواندن بشه . یه سری کپی از دادهها توی جدولهای مختلف نوشته میشه تا از سربار سنگین جوین جلوگیری کنه. بعضی از آر-دی-بی-اِم-اِس ها مثل [پوست-گِرِس](https://en.wikipedia.org/wiki/PostgreSQL) و اوراکل از [ویو-متریالایز](https://en.wikipedia.org/wiki/Materialized_view) پشتیبانی میکنن که کمک میکنه که اطلاعات اضافی رو ذخیره کنید و کپی دادهها رو با هم سازگار نگه دارید.
زمانی که دادهها به روش [فدریشن](#federation) و [شاردینگ](#sharding) توزیع میشن مدیریت جوینها بین دیتا سنترهای باعث میشه که پیچیدگی خیلی زیاد بشه. دی-نرمالایزیشن شاید باعث بشه که این نیاز به این نوع جوین ها رو از ببره.
دربیشتر سیستمها عملیات خوندن میتونه به نسبت ۱۰۰:۱ یا حتی ۱۰۰۰:۱ نسبت به عملیات نوشتن بیشتر باشه. عملیات خوندنی که حاصل یک جوین پیچیده پایگاهداده باشه، میتونه خیلی سنگین باشه و مدت زمان قابل توجی روی عملیاتهای مربوط به دیسک سپری کنه.
تون-کردن اس-کیو-ال یک مبحث خیلی گستردهای است و تعداد [کتابهای](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning) زیادی در این زمینه به عنوان منبع نوشته شده است.
خیلی مهمه که شما **بنچمارک** و **پروفایل** کنید تا بتونید چالشهای دیده نشده رو شبیه سازی کنید و پیداشون کنید
* **Benchmark** - شبیهسازی شرایط لود زیاد با ابزارهایی مثل [اِی-بی](http://httpd.apache.org/docs/2.2/programs/ab.html)
* MySQL dumps to disk in contiguous blocks for fast access.
* Use `CHAR` instead of `VARCHAR` for fixed-length fields.
*`CHAR` effectively allows for fast, random access, whereas with `VARCHAR`, you must find the end of a string before moving onto the next one.
* Use `TEXT` for large blocks of text such as blog posts. `TEXT` also allows for boolean searches. Using a `TEXT` field results in storing a pointer on disk that is used to locate the text block.
* Use `INT` for larger numbers up to 2^32 or 4 billion.
* Use `DECIMAL` for currency to avoid floating point representation errors.
* Avoid storing large `BLOBS`, store the location of where to get the object instead.
*`VARCHAR(255)` is the largest number of characters that can be counted in an 8 bit number, often maximizing the use of a byte in some RDBMS.
* Set the `NOT NULL` constraint where applicable to [improve search performance](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search).
##### Use good indices
* Columns that you are querying (`SELECT`, `GROUP BY`, `ORDER BY`, `JOIN`) could be faster with indices.
* Indices are usually represented as self-balancing [B-tree](https://en.wikipedia.org/wiki/B-tree) that keeps data sorted and allows searches, sequential access, insertions, and deletions in logarithmic time.
* Placing an index can keep the data in memory, requiring more space.
* Writes could also be slower since the index also needs to be updated.
* When loading large amounts of data, it might be faster to disable indices, load the data, then rebuild the indices.
##### Avoid expensive joins
* [Denormalize](#denormalization) where performance demands it.
##### Partition tables
* Break up a table by putting hot spots in a separate table to help keep it in memory.
##### Tune the query cache
* In some cases, the [query cache](http://dev.mysql.com/doc/refman/5.7/en/query-cache) could lead to [performance issues](https://www.percona.com/blog/2014/01/28/10-mysql-performance-tuning-settings-after-installation/).
* [Tips for optimizing MySQL queries](http://20bits.com/article/10-tips-for-optimizing-mysql-queries-that-dont-suck)
* [Is there a good reason i see VARCHAR(255) used so often?](http://stackoverflow.com/questions/1217466/is-there-a-good-reason-i-see-varchar255-used-so-often-as-opposed-to-another-l)
* [How do null values affect performance?](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)
داده ها دی-نرمالایز میشن و جوین های معمولا در لایه ی برنامه انجام میشن. بیشتر نو-اس-کیو-ال ها از اصل **اَسید** برای تراکنش های پشتیبانی نمیکنن و [یکپارچگی موکول](#یکپارچگی-موکول) رو به این اصل ترجیح میدن
علاوه براین که باید انتخاب کنید که [اس-کیو-ال یا نو-اس-کیو-ال](#SQL-یا-NoSQL) بد نیست انواع پایگاه داده های نو-اس-کیو-ال رو بشناسید و اونی که بهترین انتخاب برای کاربردتون هست را انتخاب کنید. ما در ادامه موارد زیر روبررسی میکنیم.
یک ذخیره ساز کلید-مقدار به طور عمومی به شما این امکان رو میده که از عملیات خوندن و نوشتن رو با اُ(۱) انجام بدید و معمولا توسط حافظههای اِس-اِس-دی و رَم پشتیبانی میشن. این ذخیره کنندههای داده میتونن کلیدها رو به [به ترتیب الفبایی](https://en.wikipedia.org/wiki/Lexicographical_order) مرتب نگه دارن که باعث میشه تا بازیابی کلیدها به صورت بازهای، بهینه تر و به صرفهتر بشه.
این ذخیرهکننده ها معمولا با کارایی بالاهستند و برای مدلهای دادهای ساده یا دادههایی که خیلی سریع تغییر میکنند مثل دادههایی که توی کش هستند مورد استفاده قرار میگیرند.
یک ذخیرهساز کلید-مقدار معمولا پایهای اصلی برای سیستمهای پیچیدهای مثل ذخیرهساز های اَسنادی و در بعضی موردها پایگاهدادههای گرافی،مورد استفاده قرار میگیرد.
* [Disadvantages of key-value stores](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
یک ذخیرهساز اسنادی حول ایده اسناد شکل میگیره(مانند ایکس-ام-ال، جِیسان، باینری و ...) که در اینجا یک سند تمام اطلاعات مربوط به یک شی رو در خودش ذخیره میکنه. ذخیرهسازهای اسنادی، اِی-پی-آی ها یا زبانهای کوئری در اختیار قرار میدهند تا بتونیم ساختار داخلی خود سند رو مورد جستجو و کوئری قرار بدیم. به یاد داشته باشید که خیلی از ذخیرهسازهای کلید-مقدار شامل ویژگیهایی هستند که میتونه با متادیتاهای مربوط به مقدارهای یک کلید هم کارکنه، که باعث میشه که مرز بین این ذخیرهسازها از لحاظ نوع محل ذخیرهسازی با یکدیگه کمرنگتر بشه .
براساس پیادهسازی های زیرساختی ، اسناد هم به صورت تگها، کالکشنها، متادیتاها یا پروندهها سازماندهی میشن. باوجوداینکه اسناد میتونن باهم دیگه گروه بشن یا توی یه دسته سازماندهی بشن،با اینحال میتونن هرکدوم فیلدهای مخصوص خودشون رو داشته باشند که در بقیه موجود نباشه.
بعضی از این ذخیرهسازها مثل [مونگو-دی-بی](https://www.mongodb.com/mongodb-architecture#) و [کوچ-دی-بی](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/#) زبانهایی شبیه اس-کیو-ال برای انجام کوئریهای پیچیده فراهم کردند. [داینامو-دی-بی](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf#) هر دو نوع کلید-مقدار و اسنادی رو پشتیبانی میکنه.
المان اصلی و پایهای برای ذخیرهساز واید-کالِم، ستون(یک جفت اسم/مقدار) است. یه ستون میتونه توی ستونهای-خانوادگی (مثل همون جدول توی اس-کیو-ال) دسته بندی بشه. اَبَر-ستونهای-خانوادگی به صورت دستهای از ستونهای-خانوادگی هستند. شما میتونید به هر ستونی که میخواید، با استفاده از کلید اون سطر، به صورت مستقل دسترسی داشته باشید. ستونها با یک کلید سطر مشابه، یه سطر رو تشکلی میدن. هر مقدار شامل یک استمپ-زمانی برای ورژنگذاری و رفع تداخل است.
گوگل [بیگ-تیبل](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) رو به عنوان اولین ذخیرهساز ستونی معرفی کرد که در [اچ-بیس](https://www.mapr.com/blog/in-depth-look-hbase-architecture)، که متن باز است و در اکوسیستم هدوپ استفاده میشه، و یا [کاساندرا](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html)، که برای فیسبوک است، مورد استفاده قرار گرفته. ذخیرهسازهایی مثل بیگ-تیبل،اچ-بیس و کاساندرا کلیدها رو بهصورت الفبایی-مرتب نگهداری میکنن که باعث میشه که بازیابی براساس یک رنج از کلیدها به صورت موثر تر و بهینه تر باشه
در یک پایگاه داده گرافی هر نود یک رکورد است و هر یال یک رابطه بین دو نود. پایگاهدادههای گرافی برای نمایش رابطههای پیچیده مورد استفاده قرار میگیرند که معمولا تعداد کلید خارجی زیاد یا رابطههای چند-به-چند زیادی دارند.
پایگاهداده های گرافی دارای کارایی بالا هستند و برای مدلهای دادهای که روابط پیچیده دارند مورد استفاده قرار میگیرند مانند شبکههای اجتماعی. این دسته از پایگاهدادهها تقریبا جدید هستند و خیلی مورد استفاده قرار نگرفته اند،معمولا پیدا کردن منابع و یا ابزار برای این دست از پایگاهداده ها دشواره. خیلی از پایگاه داده های گرافی معمولا از طریق [رِست ای-پی-آی](#representational-state-transfer-rest) قابل دسترسی هستند.
* [Explanation of base terminology](http://stackoverflow.com/questions/3342497/explanation-of-base-terminology)
* [NoSQL databases a survey and decision guidance](https://medium.com/baqend-blog/nosql-databases-a-survey-and-decision-guidance-ea7823a822d#.wskogqenq)
کش کردن باعث میشه تا زمان لود صفحه بهبود پیدا کنه و میتونه لود روی سرور شما و یا پایگاه داده رو کم کنه. در این مدل دیسپچر اول داخل کش رو نگاه میکنه اگر که درخواست قبلا داده شده بود و نتیجش بود اونجا، برمیگردونه به کاربر که باعث میشه زمان واقعی اجرا رو صرفه جویی کنه.
پایگاه دادهها معمولا از یک توزیع یکنواختی از خواندن ها یا نوشتنها توی پارتیشن بهره میگرن. آیتمهایی که خیلی مورد استفاده هستند میتونن این توزیع رو دچار چلگی کنن که باعث میشه که ما باتِلنِک داشته باشیم. استفاده از کش در جلوی پایگاه داده میتونه کمک کنه که این توزیع غیر یکنواخت و پیکهای ترافیک رو جلوشو بگیره.
کشها میتونن که در بخش کلاینت (مثل مرورگر یا سیستم عامل) قرار بگیرند یا در [سمت سرور](#وب-سرور-پروکسی-معکوس) باشن یا کلا یک لایه کش جدا وجود دارشته باشه
[سی-دی-ان ها](#شبکه-توزیع-محتوا-CDN) به عنوان یک نوع از کش درنظر گرفته میشن
### Web server caching
[پروکسی ها معکوس](#وب-سرور-پروکسی-معکوس) و کشها مثل [وارنیش](https://www.varnish-cache.org/) میتونن محتوای ایستا و داینامیک رو به صورت مستقیم جوابگو باشن. وب سرورهای هم میتونن درخواستها رو کش کنن و جوابها رو بدون اینکه به لایه برنامه بدن برگردونن
پایگاهداده شما معمولا شامل یک سری لایه کش به صورت پیشفرض در تنظیماتش هست که برای کاربرادهای عمومیتر مورد استفاده فرار میگیره. تغییر این تنظیمات برای یک کاربرد خاص میتونه این افزایش کارایی رو حتی بیشتر هم بکنه.
کشهای داخل-حافظه مثل مِمکش و رِدیس ذخیرهسازهای کلید-مقداری هستند که بین برنامه شما و منبع نگه داری داده شما قرار میگیرن. از اونجایی که داده ها داخل رم نگه داری میشه، سرعت بیشتری نسبت به پایگاه داده های معمولی داره چرا که توی پایگاهداده، داده روی دیسک ذخیره میشه. رم نسبت به دیسک محدودتره بنابراین الگوریتمهای [غیر معتبر کردن کش](https://en.wikipedia.org/wiki/Cache_algorithms) مثل [آخرین نزدیکترین استفاده - اِل-آر-یو](https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used) میتونه کمک کنه که آیتمهای سرد رو غیر معتبر کنه و دادهها داغتر رو توی رم نگه داره.(منظور از داغ، بیشتر مورد استفاده است و منظور از سرد، برعکس داغ)
به طورکلی، شما بهتره که از کش کردن به صورت فایلی دوری کنین چرا که اسکیل-کردن خودکار و کلون کردن رو خیلی سخت میکنه.
### کش در سطح کوئری پایگاه داده
هرزمانی که شما کوئری به پایگاه داده میزنید،کوئری رو به صورت هش شده به عنوان کلید درنظر بگیرید و جوابش رو به عنوان مقدار توی کش ذخیره کنید. این روش از مشکلاتی که مربوط به انقضا میشه رنج میبره:
* پاک کردن نتایجی که حاضل کوئری های پیچیدس سخت میشه
* اگر یک قسمت از داده مثل یک سلول از یک جدول تغییر کنه، شما باید هرچی که کش کردید که شامل اون سلول میشه رو پاک کنید
### کش در سطح آبجکت
داده تون رو به عنوان یک شی نگاه کنید، مثل همون کاری که توی برنام میکنید. مجموعه دادههاتون رو از توی پایگاهداده دربیارید و توی یک کلاس یا یه ساختمان داده ذخیره کنید
* اگر داده تغییر کرد، اون شی رو پاک کنید از کش
* امکان پردازش ناهمگام رو هم فراهم میکنه: وُرکرها آخرین اشیا کش شده رو جمع میکنن
پیشنهاداتی برای اینکه چیا رو کش کنید:
* سِشِن کاربر
* صفحات کاملا رندرشده
* Activity streams
* User graph data
### چه زمانی کش را آپدیت کنیم
از اونجایی که شما فقط میتونید یه بخش محدودی از دادهها رو بزارید توی کش، لازم دارید بدونید که چه استراتژی برای اپدیت کردن کشتون برای کاربرد شما بهتره
#### Cache-aside
<palign="center">
<imgsrc="http://i.imgur.com/ONjORqk.png">
<br/>
<i><ahref=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>Source: From cache to in-memory data grid</a></i>
عملیاتهای خواندن که بعد از این میاد، و مربوط به همون داده ای هست که توی کش نوشته شده، سریعتر انجام میشه. کش-اِساید به تحت عنوان بارگذاری تنبل هم گفته میشه. فقط دادهای که درخواست داده میشه، کش میشه که این باعث میشه تا کش با دادههایی که درخواست داده نشدن پر نشه.
* هر نبودن در کش باعث میشه تا ۳ مسیر طی بشه که این خودش باعث میشه که تاخیر قابل توجهی ایجاد بشه.
* داده میتونه غیرمعتبر بشه اگر که داخل پایگاه داده تغییر کرده باشه. این مشکل با ست کردن یک تام-تو-لیو برطرف میشه به اینصورت که کش مجبوره بعد این مدت اپدیت بشه. یا با استفاده از روش رایت-ثُرو میشه این مشکل رو برطرف کرد.
* اگر نودی فِیل بشه، اون با یک نود جدید جایگزین میشه و نود خالی باعث میشه تا تاخیر افزایش پیدا کنه
برنامه کش رو به عنوان استور اصلی دادهها استفاده میکنه یعنی نوشتن و خوندن داده رو در اون انجام میده در حالی که کش مسول نوشتن و خوندن توی پایگاهداده هست:
* برنامه یک آیتم رو به کش اضافه میکنه یا آپدیتش میکنه
* کش به صورت همگام عملیاتهای نوشتن رو توی پایگاه داده انجام میشده
این روش با توجه به عملیات نوشتنی که داره، به طور کلی کُند هست اما عملیاتهای خوندنی که در ادامه اتفاق میوفته خیلی سریع هستند. کاربران معمولا زمانی که میخوان به روز رسانی دادههاشون رو انجام بدن خیلی نسبت تاخیر واکنش نشون نمیدن نسبت به زمانی که قصد دارن دادهها رو بخونن. دادهها داخل کش غیرمعتبر نمیشن
* وقتی نود جدید درست میشه به خاطر اسکیل کردن یا فِیل شدن، نود جدید آیتمها رو کش نمیکنه تا زمانیکه در پایگاه داده به روز رسانی بشن. استفاده از روش کش-اِساید با این روش میتونه این مشکل رو برطرف کنه.
* بیشتر دادههایی که نوشته میشن تو کش ممکنه خونده نشن که البته میتونه با استفاده از تای-تو-لیو این تاثیر رو کم کرد..
* اگر قبل از اینکه محتوای داخل کش مورد استفاده قرار بگیره، کش پایین بیاد ممکنه که دادهها رو از دست بدیم.
* پیاده سازی این روش نسبت به روش های کش-اساید و یا رایت-ثُرو پیچیدهتر هست.
#### Refresh-ahead
<palign="center">
<imgsrc="http://i.imgur.com/kxtjqgE.png">
<br/>
<i><ahref=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>Source: From cache to in-memory data grid</a></i>
</p>
شما میتونید کش رو طوری تنظیم کنید که به صورت خودکار هر آیتم داخل کش که اخیر مورد استفاده قرار گرفته رو قبل از زمان انقضاش رِفرِش کنید
* اگر پیشبینی اینکه کدوم آیتم در آینده مورد نیاز خواهد بود به خوبی انجام نشه باعث میشه تا کارایی کاهش پیدا کنه نسبت به حالتی که از این مود استفاده نشه.
* نیاز داره سازگاری بین کشها و منابع درستیشون، مثل پایگاه دادهها، به وسیلهی [غیرمعتبرسازی کش](https://en.wikipedia.org/wiki/Cache_algorithms) تامین بشه.
* نیاز داره که تغییراتی در برنامه ایجاد بشه، مثل اضافه کردن رِدیس یا مِم-کش-دی
<i><ahref=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Source: Intro to architecting systems for scale</a></i>
</p>
جریان کاری ناهمگام باعث میشه تا زمان درخواست برای عملیاتهای سنگین کاهش پیدا کنه که اگر معمولی به صورت همگام بود زمان بیشتری میگرفت. همینطور باعث میشه تا کارهای زمانبر مثل اگریگیت کردن دادهها از قبل انجام بشن.
صفهای پیام، پیامها را میگیرند،نگه میدارن و بعد میرسونن. اگر یه عملیاتی برای اجرای همگام خیلی کُند باشه میتونید از یه صف با جریان کاری زیر استفاده کنید:
روند اجرایی کاربر بلاک نمیشه و کار در پسزمینه در حال انجامه. در این مدت کلاینت میتونه یه پردازش خیلی کمی انجام بده و نشون بده که اون کار تموم شده(به کاربر). برای مثال، اگر پستی توییت میشه، پست میتونه همون لحظه به تامیلاینتون اضافه بشه اما ممکنه یکم زمان ببره تا قبل از اینکه به تمام فالورهای شما برسه.
صف تسکها، تسکها و دادههای مربوط به اون رو میگیره، اجراشون میکنه بعد نتایجش رو برمیگردونه. تسکها میتونن زمانبندی رو پشتیبانی کنن و میتونه به برای کارهایی که از نظر محاسباتی خیلی سنگینه استفاده بشه و در پسزمینه اجراشون بکنه.
اگر صفها شروع به رشد زیادی بکنه، سایز صف میتونه از میزان حافظه بیشتر بشه، باعث بشه که دادهها توی کش پیدا نشن، باعث بشه خواندن از دیسک زیاد بشه و حتی کارایی رو کمتر میکنه. [بک-پِرِشِر](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html) میتونه با محدودیت گذاشتن روی سایز صف، نرخ بازدهی بالا و زمان پاسخگویی مناسبی برای کارهایی که در داخل صف هستند رو باعث بشه. زمانی که صف پر میشه، کلاینت های جوابی مبنی بر این که سرور مشغوله یا کد اچ-تی-تی-پی ۵۰۳ میگیرن تا بعدا دوباره درخواست رو بفرستن و امتحان کنن. کلاینت ها میتونن درخواست رو بعدا تکرار کنن، شاید با یک [بک-آف نمایی](https://en.wikipedia.org/wiki/Exponential_backoff) .
* کاربردهایی که نیاز به محاسبات سنگین و جریان کاری بلادرنگ نداره بهتره تا از مدلهای اجرایی همگام استفاده کنه چون که استفاده از صف باعث میشه که پیچیدگی و تاخیر زیاد بشه.
* [What is the difference between a message queue and a task queue?](https://www.quora.com/What-is-the-difference-between-a-message-queue-and-a-task-queue-Why-would-a-task-queue-require-a-message-broker-like-RabbitMQ-Redis-Celery-or-IronMQ-to-function)
اچ-تی-تی-پی یک روش برای کدگذاری داده برای انتقال داده بین کلاینت و سرور است. این متد یک پروتکل درخواست/پاسخ هست، یعنی: کلاینت ها درخواستشون رو میفرستند و سرورها جوابهاشونو با محتوا و استاتوس، که وضعیت کامل شدن درخواست هست، به اونها میدن. اچ-تی-تی-پی خود-شامل هست یعنی اینکه اجازه میده که درخواستها و پاسخها از روترهای میانی مسیر و سروهای سرراه بگذره درحالی که این لایههای میانی باعث میشن که لودبالانسینگ، کش کردن، رمزنگاری، و فشرده سازی اتفاق بیوفته.
تی-سی-پی یک پروتکل ارتباط-محور روی یک [شبکه آی-پی](https://en.wikipedia.org/wiki/Internet_Protocol) هست. ایجاد و خاتمه یک کانکشن با استفاده از یک [هندشِیک](https://en.wikipedia.org/wiki/Handshaking) انجام میشه. تمام پکتهایی که ارسال میشن تضمین میشن که به ترتیب و بدون اختلال به مقصد برسه و از طریق موارد زیر:
اگر ارسال کننده پاسخ درست دریافت نکند، دوباره پکِتها را میفرستد. اگر تعداد متعددی تایم-اُوت اتفاق بویفته، کانکشن قطع میشه. تی-سی-پی [کنترل جریان](https://en.wikipedia.org/wiki/Flow_control_(data)) و [کنترل ازدحام](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control) رو اجرا میکنه. این تضمینها باعث میشه تا تاخیر به وجود بیاد و به طور کلی باعث بشه تا نسبت به انتقال به روش یو-دی-پی، کمتر بهینه باشه.
برای اطمینان از نرخ بازدهی بالا، وب سرورها تعداد زیادی کانکشن تی-سی-پی رو باز نگه میدارن، که این باعث میشه تا میزان مصرف حافظه زیاد بشه. تعداد کانکشن بازِ زیاد بین تِرِدهای یک وب سرور و به عنوان مثال یک سرور [مِم-کش-دی](#memcached) میتونه پرهزینه باشه. [کانکشن پولینگ](https://en.wikipedia.org/wiki/Connection_pool) میتونه زمانیکه امکانش هست به یو-دی-پی سويیچ انجام بده.
تی-سی-پی برای کارهایی که نیاز به اطمینان بالایی هست و از نظر زمانی حساس نیست مناسبه. بعضی مثالهاش شامل وب سرورها، اطلاعات پایگاه داده، اِس-اِم-تی-پی، اِف-تی-پی، و اِس-اِس-اِچ هست.
> Intact: دست نخورده, High Available: اطمینان بالا
### User datagram protocol (UDP)
<palign="center">
<imgsrc="http://i.imgur.com/yzDrJtA.jpg">
<br/>
<i><ahref=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>Source: How to make a multiplayer game</a></i>
</p>
یو-دی-پی کانکشن-لِس هست. دیتاگرامها(مشابه پکِتها) فقط در سطح دیتاگرام تضمین میشن. دیتا گرامها ممکنه که خارج از ترتیبشون به مقصد برسن یا کلا نرسن. یو-دی-پی از کنترل ازدحام پشتیبانی نمیکنه. مستقل از تضمینهایی که تی-سی-پی پشتیبانی میکنه، یو-دی-پی به طور کلی بهینهتر هست.
یو-دی-پی میتونه برادکست کنه، دیتا گرامها رو به تمام دیوایسهای روی سابنت بفرسته. این امکان برای [دی-اِچ-سی-پی]() خوبه چرا که کلاینت هنوز آدرس آی-پی نگرفته، بنابراین یک راه برای جلوگیری کردن از اینه که تی-سی-پی بدون آدرس آی-پی شروع به ارسال کنه.
<i><ahref=http://www.puncsky.com/blog/2016/02/14/crack-the-system-design-interview/>Source: Crack the system design interview</a></i>
</p>
در یک آر-پی-سی کلاینت باعث اجرای یک رویه در فضای آدرس متفاوت،که معمولا یک سرور ریموت هست، میشه. این رویه طوری کد شده که انگار به صورت محلی فراخوانیش انجام میشه، جزییات اینکه چهطور ارتباط با سرور صورت میگیره رو از برنامه کلاینت پنهان میکنه. فراخوانیهای راهدور معمولا کندتر هستند و کمتر قابل اطمینانن نسبت به فراخوانیهای محلی بنابراین بهتره که فراخوانیهای راهدور رو از فراخوانیهای محلی متمایز کنیم. چارچوبهای شناخته شده آر-پی -سی شامل [پروتو-باف](https://developers.google.com/protocol-buffers/)، [ثریفت](https://thrift.apache.org/) , [آو-رو](https://avro.apache.org/docs/current/) هستند.
> Protobuf: پروتو-باف, Thrift: ثریفت, Avro: آو-رو
آر-پی-سی یک پروتکل درخواست-جواب هست:
* **Client program** - رویهی کلاینت-اِستاب رو فراخوانی میکنه. پارامترها شبیه به فراخوانی محلی داخل یک پشته نوشته میشن.
* **Client stub procedure** - آی-دی رویه و آرگومانهای اون رو مارشال میکنه(جمع میکنه) داخل درخواست.
* **Client communication module** - سیستم عامل پیام رو از کلاینت به سرور میفرسته.
* **Server communication module** - سیستم عامل پکتهای ورودی رو به رویه استاب سرور میده
* **Server stub procedure** - نتایج بازمیشن(آن-مارشال)، رویهای از سرور که با آی-دی رویه مطابقت داشته باشه با آرگومانهای دادهشده اجرا میشه.
* سرور در پاسخ مراحل بالا رو به صورت معکوس انجام میده
تمرکز آر-پی-سی روی بیان رفتارهاست. آر-پی-سیها معمولا برای دلایلی مثل کارایی برای ارتباطات داخلی استفاده میشن، همینطور شما میتونید از فراخوانیهای نِیتیو که انجام میدید و مناسب کاربردتون هست استفاده کنید.
* ممکنه شما نتونید از تکنولوژیهایی که درحال حاضر هستند استفاده کنید. برای مثال، ممکنه نیاز باشه تا تلاش بیشتری بکنید تا مطمئن بشید که [فراخوانیهای آر-پی-سی به درستی کش شدن](http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/) روی سرورهای کش، مثل [اِس-کویید](http://www.squid-cache.org/)
رِست یک نوع استایل معماری هست که در جایی که کلاینتها روی یک سری ریسورس که سرور مدیرتش میکنه قراره کاری انجام بدن، مدل کلاینت/سرور رو ایجاب میکنه . سرور یک نمایشی از ریسورسها رو ارائه میکنه و همچنین عملکردهایی که میتونه هم تغییر ایجاد کنه یا یک نمایش جدیدی از ریسورس رو بده. تمام ارتباطات باید بدون حالت و قابل کش کردن باشه.
رِست تمرکزش روی نمایش داده است. این معماری وابستگی بین کلاینت/سرور رو کم میکنه و معمولا برای اِی-پی-آیهای اچ-تی-تی-پی عمومی مورد استفاده قرار میگیره. رِست یه روش کلیتری و یکدستتری برای به نمایش گذاشتن ریسورسها استفاده میکنه، که از طریق یو-آر-آی، [نمایش از طریق هِدِرها](https://github.com/for-GET/know-your-http-well/blob/master/headers.md) ، و اکشنها که به واسطه فعلهایی مثل گِت، پُست، پوت، دیلیت و پَچ است. با توجه به این که فاقد حالته، رِست برای اسکیل کردن افقی و پاتیشنبندی خیلی مناسبه.
* باتوحه به این که تمرکز رِست روی به نمایش گذاشتن دادههاس، برای ریسورسهایی که به صورت معمولی و سلسله مراتبی مدیرت میشن مناسب نیست. برای مثال، برگردوندن لیست آپدیتهای رکوردها توی رنج ۱ ساعت پیش که با یک سری رخدادهای خاص مَچ شده باشه چیزی نیست که بشه به صورت مسیر، توی یو-آر-اِل اچ-تی-تی-پی، اونو به راحتی نشون داد. در صورت استفاده از رِست،باید این کار به وسیله ترکیبی از یو-آر-آیها، کوئری پارامترها و احتمالا با یک ریکوست بادی پیاده سازی بشه.
* رِست معمولا روی چندتا فعل محدود(گِت، پُست، پوت، دیلیت و پَچ) تمرکز داره که بعضی وقتا برای کاربرد شما مناسب نیست. برای مثال، انتقال مستنداتی که دیگه منتقضی شدن به فولدر آرشیو ممکنه که خیلی تر و تمیز با این فعلها نشه بیانش کرد.
* گرفتن ریسورس های پیچیده با ساختار سلسله مراتبی تودرتو احتیاج داره که تعداد رفت و برگشت زیاده رو بین کلاینت و سرور شاهد باشیم تا سرور فقط یک صفحه رو نمایش بده به عنوان مثال، گرفتن محتوای یک پست از بلاگ و کامنت هایی که روی اونه. برای برنامه های موبایل در شرایطی که باید بین شبکههای مختلفی کار کنند، این رفت و برگشت ها خیلی مورد علاقه نیست.
* به مرورزمان، تعداد فیلدهای بیشتری ممکنه که به پاسخ اِی-پی-آی اضافه بشه و کلاینتهای قدیمی فیلدهای جدید رو هم میگیرن حتی اون دسته از فیلدهایی که بدردشون نمیخوره که این باعث میشه سایز بدنه ارسالی زیاد بشه و این خودش یعنی افزایش تاخیر.
امنیت یک مبحث گستردهای هست. احتمالا نیازی ندارید که بیشتر از مسايل پایهای رو در مورد امنیت بدونید مگر اینکه تجربهی خوبی در این زمینه یا پیشزمینه امنیت داشته باشید و یا قصد دارید که برای پوزیشنی که نیاز به دانش امینت داره برید:
* Sanitize all user inputs or any input parameters exposed to user to prevent [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) and [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
* Use parameterized queries to prevent SQL injection.
* Use the principle of [least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
ممکنه از شما بخوان که یه سری محاسبات سریعی رو انجام بدید. برای مثال ممکنه نیاز داشته داشته بدونید که چقدر زمان نیازه تا ۱۰۰ تصویر ثامب-نِیل از روی دیسک تولید بشه یا اینکه چقدر حافظه یک ساختمان داده خاص نیاز داره. **جدول اعداد توان ۲** و **اعداد تاخیری که هر برنامه نویسی باید بدونه** یه منبع مناسب هست برای این کار.
* [Latency numbers every programmer should know - 1](https://gist.github.com/jboner/2841832)
* [Latency numbers every programmer should know - 2](https://gist.github.com/hellerbarde/2843375)
* [Designs, lessons, and advice from building large distributed systems](http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf)
* [Software Engineering Advice from Building Large-Scale Distributed Systems](https://static.googleusercontent.com/media/research.google.com/en//people/jeff/stanford-295-talk.pdf)
| Design a file sync service like Dropbox | [youtube.com](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| Design a search engine like Google | [queue.acm.org](http://queue.acm.org/detail.cfm?id=988407)<br/>[stackexchange.com](http://programmers.stackexchange.com/questions/38324/interview-question-how-would-you-implement-google-search)<br/>[ardendertat.com](http://www.ardendertat.com/2012/01/11/implementing-search-engines/)<br>[stanford.edu](http://infolab.stanford.edu/~backrub/google.html) |
| Design a scalable web crawler like Google | [quora.com](https://www.quora.com/How-can-I-build-a-web-crawler-from-scratch) |
| Design Google docs | [code.google.com](https://code.google.com/p/google-mobwrite/)<br/>[neil.fraser.name](https://neil.fraser.name/writing/sync/) |
| Design a key-value store like Redis | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| Design a cache system like Memcached | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| Design a recommendation system like Amazon's | [hulu.com](http://tech.hulu.com/blog/2011/09/19/recommendation-system.html)<br/>[ijcai13.org](http://ijcai13.org/files/tutorial_slides/td3.pdf) |
| Design a tinyurl system like Bitly | [n00tc0d3r.blogspot.com](http://n00tc0d3r.blogspot.com/) |
| Design a chat app like WhatsApp | [highscalability.com](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html)
| Design a picture sharing system like Instagram | [highscalability.com](http://highscalability.com/flickr-architecture)<br/>[highscalability.com](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html) |
| Design the Facebook news feed function | [quora.com](http://www.quora.com/What-are-best-practices-for-building-something-like-a-News-Feed)<br/>[quora.com](http://www.quora.com/Activity-Streams/What-are-the-scaling-issues-to-keep-in-mind-while-developing-a-social-network-feed)<br/>[slideshare.net](http://www.slideshare.net/danmckinley/etsy-activity-feeds-architecture) |
| Design the Facebook timeline function | [facebook.com](https://www.facebook.com/note.php?note_id=10150468255628920)<br/>[highscalability.com](http://highscalability.com/blog/2012/1/23/facebook-timeline-brought-to-you-by-the-power-of-denormaliza.html) |
| Design the Facebook chat function | [erlang-factory.com](http://www.erlang-factory.com/upload/presentations/31/EugeneLetuchy-ErlangatFacebook.pdf)<br/>[facebook.com](https://www.facebook.com/note.php?note_id=14218138919&id=9445547199&index=0) |
| Design a graph search function like Facebook's | [facebook.com](https://www.facebook.com/notes/facebook-engineering/under-the-hood-building-out-the-infrastructure-for-graph-search/10151347573598920)<br/>[facebook.com](https://www.facebook.com/notes/facebook-engineering/under-the-hood-indexing-and-ranking-in-graph-search/10151361720763920)<br/>[facebook.com](https://www.facebook.com/notes/facebook-engineering/under-the-hood-the-natural-language-interface-of-graph-search/10151432733048920) |
| Design a content delivery network like CloudFlare | [cmu.edu](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci) |
| Design a trending topic system like Twitter's | [michael-noll.com](http://www.michael-noll.com/blog/2013/01/18/implementing-real-time-trending-topics-in-storm/)<br/>[snikolov .wordpress.com](http://snikolov.wordpress.com/2012/11/14/early-detection-of-twitter-trends/) |
| Design a random ID generation system | [blog.twitter.com](https://blog.twitter.com/2010/announcing-snowflake)<br/>[github.com](https://github.com/twitter/snowflake/) |
| Return the top k requests during a time interval | [ucsb.edu](https://icmi.cs.ucsb.edu/research/tech_reports/reports/2005-23.pdf)<br/>[wpi.edu](http://davis.wpi.edu/xmdv/docs/EDBT11-diyang.pdf) |
| Design a system that serves data from multiple data centers | [highscalability.com](http://highscalability.com/blog/2009/8/24/how-google-serves-data-from-multiple-datacenters.html) |
| Design an online multiplayer card game | [indieflashblog.com](http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)<br/>[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| Design a garbage collection system | [stuffwithstuff.com](http://journal.stuffwithstuff.com/2013/12/08/babys-first-garbage-collector/)<br/>[washington.edu](http://courses.cs.washington.edu/courses/csep521/07wi/prj/rick.pdf) |
| Design an API rate limiter | [https://stripe.com/blog/](https://stripe.com/blog/rate-limiters) |
| Add a system design question | [Contribute](#contributing) |
| Data processing | **MapReduce** - Distributed data processing from Google | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/mapreduce-osdi04.pdf) |
| Data processing | **Spark** - Distributed data processing from Databricks | [slideshare.net](http://www.slideshare.net/AGrishchenko/apache-spark-architecture) |
| Data processing | **Storm** - Distributed data processing from Twitter | [slideshare.net](http://www.slideshare.net/previa/storm-16094009) |
| | | |
| Data store | **Bigtable** - Distributed column-oriented database from Google | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) |
| Data store | **HBase** - Open source implementation of Bigtable | [slideshare.net](http://www.slideshare.net/alexbaranau/intro-to-hbase) |
| Data store | **Cassandra** - Distributed column-oriented database from Facebook | [slideshare.net](http://www.slideshare.net/planetcassandra/cassandra-introduction-features-30103666)
| Data store | **DynamoDB** - Document-oriented database from Amazon | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) |
| Data store | **MongoDB** - Document-oriented database | [slideshare.net](http://www.slideshare.net/mdirolf/introduction-to-mongodb) |
| Data store | **Spanner** - Globally-distributed database from Google | [research.google.com](http://research.google.com/archive/spanner-osdi2012.pdf) |
| Data store | **Memcached** - Distributed memory caching system | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| Data store | **Redis** - Distributed memory caching system with persistence and value types | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| | | |
| File system | **Google File System (GFS)** - Distributed file system | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/gfs-sosp2003.pdf) |
| File system | **Hadoop File System (HDFS)** - Open source implementation of GFS | [apache.org](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html) |
| | | |
| Misc | **Chubby** - Lock service for loosely-coupled distributed systems from Google | [research.google.com](http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/archive/chubby-osdi06.pdf) |
| ESPN | [Operating At 100,000 duh nuh nuhs per second](http://highscalability.com/blog/2013/11/4/espns-architecture-at-scale-operating-at-100000-duh-nuh-nuhs.html) |
| Google | [Google architecture](http://highscalability.com/google-architecture) |
| Instagram | [14 million users, terabytes of photos](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html)<br/>[What powers Instagram](http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances) |
| Justin.tv | [Justin.Tv's live video broadcasting architecture](http://highscalability.com/blog/2010/3/16/justintvs-live-video-broadcasting-architecture.html) |
| Facebook | [Scaling memcached at Facebook](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/key-value/fb-memcached-nsdi-2013.pdf)<br/>[TAO: Facebook’s distributed data store for the social graph](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/data-store/tao-facebook-distributed-datastore-atc-2013.pdf)<br/>[Facebook’s photo storage](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf) |
| Mailbox | [From 0 to one million users in 6 weeks](http://highscalability.com/blog/2013/6/18/scaling-mailbox-from-0-to-one-million-users-in-6-weeks-and-1.html) |
| Pinterest | [From 0 To 10s of billions of page views a month](http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html)<br/>[18 million visitors, 10x growth, 12 employees](http://highscalability.com/blog/2012/5/21/pinterest-architecture-update-18-million-visitors-10x-growth.html) |
| Playfish | [50 million monthly users and growing](http://highscalability.com/blog/2010/9/21/playfishs-social-gaming-architecture-50-million-monthly-user.html) |
| Tumblr | [15 billion page views a month](http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html) |
| Twitter | [Making Twitter 10000 percent faster](http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster)<br/>[Storing 250 million tweets a day using MySQL](http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html)<br/>[150M active users, 300K QPS, a 22 MB/S firehose](http://highscalability.com/blog/2013/7/8/the-architecture-twitter-uses-to-deal-with-150m-active-users.html)<br/>[Timelines at scale](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)<br/>[Big and small data at Twitter](https://www.youtube.com/watch?v=5cKTP36HVgI)<br/>[Operations at Twitter: scaling beyond 100 million users](https://www.youtube.com/watch?v=z8LU0Cj6BOU) |
لیست وبلاگها در اینجا نسبتا کوتاهتر نگه داشته میشه و ریپازیتوری زیر شامل لیست بلندی از این وبلاگهاست که برای جلوگیری از دوباره نویسی در اینجا، فقط همین بخش کم آورده شده. وبلاگ مهندسی کمپانیتون روبه ریپازیتوری زیر اضافه کنید
*I am providing code and resources in this repository to you under an open source license. Because this is my personal repository, the license you receive to my code and resources is from me and not my employer (Facebook).*
Copyright 2017 Donne Martin
Creative Commons Attribution 4.0 International License (CC BY 4.0)