Move the main file and translations to docs

This commit is contained in:
Ido777
2025-04-30 08:45:26 +03:00
committed by Ido Ophir
parent ed98dc6097
commit 43f849b8c6
6 changed files with 0 additions and 0 deletions

1781
docs/README-ar.md Normal file
View File

@@ -0,0 +1,1781 @@
*[English](README.md) ∙ [日本語](README-ja.md) ∙ [简体中文](README-zh-Hans.md) ∙ [繁體中文](README-zh-TW.md) ∙ [العَرَبِيَّة‎](README-ar.md) ∙ [বাংলা](https://github.com/donnemartin/system-design-primer/issues/220) ∙ [Português do Brasil](https://github.com/donnemartin/system-design-primer/issues/40) ∙ [Deutsch](https://github.com/donnemartin/system-design-primer/issues/186) ∙ [ελληνικά](https://github.com/donnemartin/system-design-primer/issues/130) ∙ [עברית](https://github.com/donnemartin/system-design-primer/issues/272) ∙ [Italiano](https://github.com/donnemartin/system-design-primer/issues/104) ∙ [한국어](https://github.com/donnemartin/system-design-primer/issues/102) ∙ [فارسی](https://github.com/donnemartin/system-design-primer/issues/110) ∙ [Polski](https://github.com/donnemartin/system-design-primer/issues/68) ∙ [русский язык](https://github.com/donnemartin/system-design-primer/issues/87) ∙ [Español](https://github.com/donnemartin/system-design-primer/issues/136) ∙ [ภาษาไทย](https://github.com/donnemartin/system-design-primer/issues/187) ∙ [Türkçe](https://github.com/donnemartin/system-design-primer/issues/39) ∙ [tiếng Việt](https://github.com/donnemartin/system-design-primer/issues/127) ∙ [Français](https://github.com/donnemartin/system-design-primer/issues/250) | [إضافة ترجمة](https://github.com/donnemartin/system-design-primer/issues/28)*
**ساعد في [ترجمة](TRANSLATIONS.md) هذا المستند!**
# دليل تصميم النظم (System Design Primer)
<p align="center">
<img src="images/jj3A5N8.png">
<br/>
</p>
## الهدف
> تعلم أساسيات تصميم الأنظمة عالية المستوى (large-scale systems).
>
> التحضير لمقابلات تصميم النظم (system design interviews).
### تعلم كيفية تصميم الأنظمة واسعة النطاق
إن تعلم كيفية تصميم الأنظمة القابلة للتطوير (scalable systems) سيساعدك في تطوير مهاراتك كمهندس برمجيات.
تصميم النظم (system design) هو مجال واسع النطاق. هناك **كم هائل من المصادر المتوفرة على الإنترنت** حول مبادئ تصميم النظم.
هذا الـ repository عبارة عن **مجموعة منظمة** من المصادر لمساعدتك في تعلم كيفية بناء أنظمة على نطاق واسع (large-scale systems).
### تعلم من مجتمع المصادر المفتوحة (Open Source)
هذا مشروع open source يتم تحديثه بشكل مستمر.
نرحب بـ [المساهمات](#contributing)!
### التحضير لمقابلة تصميم النظم (System Design Interview)
بالإضافة إلى مقابلات البرمجة (coding interviews)، يُعد تصميم النظم **عنصراً أساسياً** في **عملية المقابلة التقنية** لدى العديد من شركات التقنية.
**تدرب على الأسئلة الشائعة في مقابلات تصميم النظم** و**قارن** إجاباتك مع **الحلول المرجعية** التي تشمل: المناقشات التقنية والكود والمخططات التوضيحية.
مواضيع تكميلية للتحضير للمقابلة:
* [دليل الدراسة](#study-guide)
* [كيفية التعامل مع أسئلة مقابلة تصميم النظم](#how-to-approach-a-system-design-interview-question)
* [أسئلة مقابلة تصميم النظم **مع الحلول**](#system-design-interview-questions-with-solutions)
* [أسئلة مقابلة التصميم كائني التوجه (Object-Oriented Design) **مع الحلول**](#object-oriented-design-interview-questions-with-solutions)
* [أسئلة إضافية في مقابلات تصميم النظم](#additional-system-design-interview-questions)
## بطاقات Anki التعليمية
<p align="center">
<img src="images/zdCAkB3.png">
<br/>
</p>
تستخدم [بطاقات Anki](https://apps.ankiweb.net/) التكرار المتباعد (spaced repetition) لمساعدتك في حفظ المفاهيم الأساسية لتصميم النظم.
* [مجموعة System Design](https://github.com/donnemartin/system-design-primer/tree/master/resources/flash_cards/System%20Design.apkg)
* [مجموعة System Design Exercises](https://github.com/donnemartin/system-design-primer/tree/master/resources/flash_cards/System%20Design%20Exercises.apkg)
* [مجموعة Object-Oriented Design](https://github.com/donnemartin/system-design-primer/tree/master/resources/flash_cards/OO%20Design.apkg)
مثالية للمراجعة أثناء التنقل.
### مورد للبرمجة: Interactive Coding Challenges
هل تبحث عن موارد للمساعدة في التحضير لـ [**مقابلات البرمجة**](https://github.com/donnemartin/interactive-coding-challenges
<p align="center">
<img src="images/b4YtAEN.png">
<br/>
</p>
تفقد المستودع المرافق [**Interactive Coding Challenges**](https://github.com/donnemartin/interactive-coding-challenges)، والذي يتضمن مجموعة Anki إضافية:
* [مجموعة Coding](https://github.com/donnemartin/interactive-coding-challenges/tree/master/anki_cards/Coding.apkg)
## المساهمة
> تعلم من المجتمع.
نرحب بتقديم pull requests للمساعدة في:
* تصحيح الأخطاء
* تحسين المحتوى
* إضافة أقسام جديدة
* [الترجمة](https://github.com/donnemartin/system-design-primer/issues/28)
المحتوى الذي يحتاج إلى تحسين سيتم تمييزه [تحت التطوير](#under-development).
يرجى مراجعة [دليل المساهمة](CONTRIBUTING.md).
## فهرس موضوعات تصميم النظم
> ملخصات موضوعات تصميم النظم المختلفة، متضمنة المزايا والعيوب. **كل شيء عبارة عن trade-off**.
>
> كل قسم يحتوي على روابط لمصادر أكثر تفصيلاً.
<p align="center">
<img src="images/jrUBAF7.png">
<br/>
</p>
* [موضوعات تصميم النظم: ابدأ من هنا](#system-design-topics-start-here)
* [الخطوة 1: مراجعة محاضرة scalability](#step-1-review-the-scalability-video-lecture)
* [الخطوة 2: مراجعة مقالة scalability](#step-2-review-the-scalability-article)
* [الخطوات التالية](#next-steps)
* [Performance مقابل Scalability](#performance-vs-scalability)
* [Latency مقابل Throughput](#latency-vs-throughput)
* [Availability مقابل Consistency](#availability-vs-consistency)
* [نظرية CAP](#cap-theorem)
* [CP - Consistency و Partition Tolerance](#cp---consistency-and-partition-tolerance)
* [AP - Availability و Partition Tolerance](#ap---availability-and-partition-tolerance)
* [أنماط Consistency](#consistency-patterns)
* [Weak Consistency](#weak-consistency)
* [Eventual Consistency](#eventual-consistency)
* [Strong Consistency](#strong-consistency)
* [أنماط Availability](#availability-patterns)
* [Failover](#fail-over)
* [Replication](#replication)
* [Availability بالأرقام](#availability-in-numbers)
* [Domain Name System](#domain-name-system)
* [Content Delivery Network](#content-delivery-network)
* [Push CDNs](#push-cdns)
* [Pull CDNs](#pull-cdns)
* [Load Balancer](#load-balancer)
* [Active-passive](#active-passive)
* [Active-active](#active-active)
* [Layer 4 load balancing](#layer-4-load-balancing)
* [Layer 7 load balancing](#layer-7-load-balancing)
* [Horizontal scaling](#horizontal-scaling)
* [Reverse Proxy (Web Server)](#reverse-proxy-web-server)
* [Load Balancer مقابل Reverse Proxy](#load-balancer-vs-reverse-proxy)
* [طبقة التطبيق](#application-layer)
* [Microservices](#microservices)
* [Service Discovery](#service-discovery)
* [قواعد البيانات](#database)
* [Relational Database Management System (RDBMS)](#relational-database-management-system-rdbms)
* [Master-slave replication](#master-slave-replication)
* [Master-master replication](#master-master-replication)
* [Federation](#federation)
## دليل الدراسة
> المواضيع المقترحة للمراجعة بناءً على الجدول الزمني لمقابلتك (قصير، متوسط، طويل).
![Imgur](images/OfVllex.png)
**س: هل يجب أن أعرف كل شيء هنا للمقابلة؟**
**ج: لا، لست بحاجة لمعرفة كل شيء هنا للتحضير للمقابلة**.
ما يُسأل عنه في المقابلة يعتمد على متغيرات مثل:
* مقدار خبرتك
* خلفيتك التقنية
* المناصب التي تتقدم لها
* الشركات التي تجري معها المقابلات
* الحظ
عادةً ما يُتوقع من المرشحين ذوي الخبرة معرفة المزيد عن تصميم النظم. قد يُتوقع من المهندسين المعماريين أو قادة الفرق معرفة أكثر من المساهمين الفرديين. من المحتمل أن تجري شركات التقنية الكبرى جولة أو أكثر من مقابلات التصميم.
ابدأ بشكل واسع ثم تعمق في بعض المجالات. من المفيد معرفة القليل عن مواضيع تصميم النظم المختلفة. عدّل الدليل التالي بناءً على جدولك الزمني، وخبرتك، والمناصب التي تتقدم لها، والشركات التي تجري معها المقابلات.
* **جدول زمني قصير** - اهدف إلى **الاتساع** في مواضيع تصميم النظم. تدرب عن طريق حل **بعض** أسئلة المقابلات.
* **جدول زمني متوسط** - اهدف إلى **الاتساع** و**بعض العمق** في مواضيع تصميم النظم. تدرب عن طريق حل **العديد** من أسئلة المقابلات.
* **جدول زمني طويل** - اهدف إلى **الاتساع** و**مزيد من العمق** في مواضيع تصميم النظم. تدرب عن طريق حل **معظم** أسئلة المقابلات.
| | قصير | متوسط | طويل |
|---|---|---|---|
| اقرأ [مواضيع تصميم النظم](#index-of-system-design-topics) للحصول على فهم واسع لكيفية عمل النظم | :+1: | :+1: | :+1: |
| اقرأ بعض المقالات في [مدونات هندسة الشركات](#company-engineering-blogs) للشركات التي تجري معها المقابلات | :+1: | :+1: | :+1: |
| اقرأ بعض [البنى الحقيقية للأنظمة](#real-world-architectures) | :+1: | :+1: | :+1: |
| راجع [كيفية مقاربة سؤال مقابلة تصميم النظم](#how-to-approach-a-system-design-interview-question) | :+1: | :+1: | :+1: |
| اعمل على [أسئلة مقابلة تصميم النظم مع الحلول](#system-design-interview-questions-with-solutions) | بعضها | العديد | معظمها |
| اعمل على [أسئلة مقابلة التصميم الموجه للكائنات مع الحلول](#object-oriented-design-interview-questions-with-solutions) | بعضها | العديد | معظمها |
| راجع [أسئلة إضافية لمقابلة تصميم النظم](#additional-system-design-interview-questions) | بعضها | العديد | معظمها |
## كيفية مقاربة سؤال مقابلة تصميم النظم
> كيفية معالجة سؤال مقابلة تصميم النظم.
مقابلة تصميم النظم هي **محادثة مفتوحة**. يُتوقع منك قيادتها.
يمكنك استخدام الخطوات التالية لتوجيه المناقشة. للمساعدة في ترسيخ هذه العملية، اعمل على قسم [أسئلة مقابلة تصميم النظم مع الحلول](#system-design-interview-questions-with-solutions) باستخدام الخطوات التالية.
### الخطوة 1: حدد حالات الاستخدام والقيود والافتراضات
اجمع المتطلبات وحدد نطاق المشكلة. اطرح أسئلة لتوضيح حالات الاستخدام والقيود. ناقش الافتراضات.
* من سيستخدمه؟
* كيف سيستخدمونه؟
* كم عدد المستخدمين؟
* ما الذي يفعله النظام؟
* ما هي مدخلات ومخرجات النظام؟
* كم حجم البيانات التي نتوقع التعامل معها؟
* كم عدد الطلبات في الثانية التي نتوقعها؟
* ما هي النسبة المتوقعة للقراءة مقابل الكتابة؟
### الخطوة 2: إنشاء تصميم عالي المستوى
حدد تصميماً عالي المستوى مع جميع المكونات المهمة.
* ارسم المكونات الرئيسية والروابط
* برر أفكارك
### الخطوة 3: تصميم المكونات الأساسية
تعمق في تفاصيل كل مكون أساسي. على سبيل المثال، إذا طُلب منك [تصميم خدمة تقصير الروابط](solutions/system_design/pastebin/README.md)، ناقش:
* توليد وتخزين hash للرابط الكامل
* [MD5](solutions/system_design/pastebin/README.md) و [Base62](solutions/system_design/pastebin/README.md)
* تصادمات الـ hash
* SQL أو NoSQL
* مخطط قاعدة البيانات
* ترجمة الرابط المختصر إلى الرابط الكامل
* البحث في قاعدة البيانات
* تصميم API والتصميم الموجه للكائنات
### الخطوة 4: تطوير التصميم
حدد وعالج نقاط الاختناق، مع مراعاة القيود. على سبيل المثال، هل تحتاج إلى ما يلي لمعالجة مشاكل قابلية التطوير؟
* موازن التحميل
* التطوير الأفقي
* التخزين المؤقت
* تجزئة قاعدة البيانات
ناقش الحلول المحتملة والمقايضات. كل شيء هو مقايضة. عالج نقاط الاختناق باستخدام [مبادئ تصميم النظم القابلة للتطوير](#index-of-system-design-topics).
### حسابات تقريبية
قد يُطلب منك إجراء بعض التقديرات يدوياً. راجع [الملحق](#appendix) للموارد التالية:
* [استخدام الحسابات التقريبية](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
* [جدول قوى الاثنين](#powers-of-two-table)
* [أرقام زمن الاستجابة التي يجب أن يعرفها كل مبرمج](#latency-numbers-every-programmer-should-know)
### المصادر وقراءات إضافية
راجع الروابط التالية للحصول على فكرة أفضل عما يمكن توقعه:
* [كيفية التفوق في مقابلة تصميم النظم](https://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)
* [مقابلة تصميم النظام](http://www.hiredintech.com/system-design)
* [مقدمة لمقابلات البنية والنظم](https://www.youtube.com/watch?v=ZgdS0EUmn70)
* [قالب تصميم النظام](https://leetcode.com/discuss/career/229177/My-System-Design-Template)
## أسئلة مقابلة تصميم النظم مع الحلول
> أسئلة شائعة لمقابلات تصميم النظم مع مناقشات نموذجية وشيفرة ومخططات.
>
> الحلول مرتبطة بالمحتوى في مجلد `solutions/`.
| السؤال | |
|---|---|
| تصميم Pastebin.com (أو Bit.ly) | [الحل](solutions/system_design/pastebin/README.md) |
| تصميم الجدول الزمني والبحث في Twitter (أو خلاصة Facebook والبحث) | [الحل](solutions/system_design/twitter/README.md) |
| تصميم متصفح ويب | [الحل](solutions/system_design/web_crawler/README.md) |
| تصميم Mint.com | [الحل](solutions/system_design/mint/README.md) |
| تصميم هياكل البيانات لشبكة اجتماعية | [الحل](solutions/system_design/social_graph/README.md) |
| تصميم مخزن key-value لمحرك بحث | [الحل](solutions/system_design/query_cache/README.md) |
| تصميم ميزة تصنيف المبيعات حسب الفئة في Amazon | [الحل](solutions/system_design/sales_rank/README.md) |
| تصميم نظام يتطور لملايين المستخدمين على AWS | [الحل](solutions/system_design/scaling_aws/README.md) |
| أضف سؤال تصميم نظام | [ساهم](#contributing) |
### تصميم Pastebin.com (أو Bit.ly)
[عرض التمرين والحل](solutions/system_design/pastebin/README.md)
![Imgur](images/4edXG0T.png)
### تصميم الجدول الزمني والبحث في Twitter (أو خلاصة Facebook والبحث)
[عرض التمرين والحل](solutions/system_design/twitter/README.md)
![Imgur](images/jrUBAF7.png)
### تصميم متصفح ويب
[عرض التمرين والحل](solutions/system_design/web_crawler/README.md)
![Imgur](images/bWxPtQA.png)
### تصميم Mint.com
[عرض التمرين والحل](solutions/system_design/mint/README.md)
![Imgur](images/V5q57vU.png)
### تصميم هياكل البيانات لشبكة اجتماعية
[عرض التمرين والحل](solutions/system_design/social_graph/README.md)
![Imgur](images/cdCv5g7.png)
### تصميم مخزن key-value لمحرك بحث
[عرض التمرين والحل](solutions/system_design/query_cache/README.md)
![Imgur](images/4j99mhe.png)
### تصميم ميزة تصنيف المبيعات حسب الفئة في Amazon
[عرض التمرين والحل](solutions/system_design/sales_rank/README.md)
![Imgur](images/MzExP06.png)
### تصميم نظام يتطور لملايين المستخدمين على AWS
[عرض التمرين والحل](solutions/system_design/scaling_aws/README.md)
![Imgur](images/jj3A5N8.png)
## أسئلة مقابلة التصميم الموجه للكائنات مع الحلول
> أسئلة شائعة لمقابلات التصميم الموجه للكائنات مع مناقشات نموذجية وشيفرة ومخططات.
>
> الحلول مرتبطة بالمحتوى في مجلد `solutions/`.
>**ملاحظة: هذا القسم تحت التطوير**
| السؤال | |
|---|---|
| تصميم hash map | [الحل](solutions/object_oriented_design/hash_table/hash_map.ipynb) |
| تصميم ذاكرة التخزين المؤقت الأقل استخداماً مؤخراً | [الحل](solutions/object_oriented_design/lru_cache/lru_cache.ipynb) |
| تصميم مركز اتصال | [الحل](solutions/object_oriented_design/call_center/call_center.ipynb) |
| تصميم مجموعة بطاقات | [الحل](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| تصميم موقف سيارات | [الحل](solutions/object_oriented_design/parking_lot/parking_lot.ipynb) |
| تصميم خادم دردشة | [الحل](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| تصميم مصفوفة دائرية | [ساهم](#contributing) |
| أضف سؤال تصميم موجه للكائنات | [ساهم](#contributing) |
## مواضيع تصميم النظم: ابدأ هنا
هل أنت جديد في تصميم النظم؟
أولاً، ستحتاج إلى فهم أساسي للمبادئ الشائعة، والتعرف على ماهيتها، وكيفية استخدامها، ومزاياها وعيوبها.
### الخطوة 1: مراجعة محاضرة قابلية التطوير
[محاضرة قابلية التطوير في هارفارد](https://www.youtube.com/watch?v=-W9F__D3oY4)
* المواضيع المغطاة:
* التطوير العمودي
* التطوير الأفقي
* التخزين المؤقت
* موازنة التحميل
* النسخ المتماثل لقاعدة البيانات
* تجزئة قاعدة البيانات
### الخطوة 2: مراجعة مقالة قابلية التطوير
[قابلية التطوير](https://web.archive.org/web/20221030091841/http://www.lecloud.net/tagged/scalability/chrono)
* المواضيع المغطاة:
* [النسخ المتماثلة](https://web.archive.org/web/20220530193911/https://www.lecloud.net/post/7295452622/scalability-for-dummies-part-1-clones)
* [قواعد البيانات](https://web.archive.org/web/20220602114024/https://www.lecloud.net/post/7994751381/scalability-for-dummies-part-2-database)
* [ذاكرة التخزين المؤقت](https://web.archive.org/web/20230126233752/https://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
* [اللاتزامن](https://web.archive.org/web/20220926171507/https://www.lecloud.net/post/9699762917/scalability-for-dummies-part-4-asynchronism)
### الخطوات التالية
بعد ذلك، سننظر في المقايضات عالية المستوى:
* **الأداء** مقابل **قابلية التطوير**
* **زمن الاستجابة** مقابل **الإنتاجية**
* **التوافر** مقابل **الاتساق**
ضع في اعتبارك أن **كل شيء هو مقايضة**.
ثم سنتعمق في مواضيع أكثر تحديداً مثل DNS وشبكات CDN وموازنات التحميل.
## الأداء مقابل قابلية التطوير
تكون الخدمة **قابلة للتطوير** إذا أدت إلى زيادة في **الأداء** بشكل يتناسب مع الموارد المضافة. بشكل عام، تعني زيادة الأداء خدمة المزيد من وحدات العمل، ولكن يمكن أن تكون أيضاً للتعامل مع وحدات عمل أكبر، مثل عندما تنمو مجموعات البيانات.<sup><a href=http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html>1</a></sup>
طريقة أخرى للنظر إلى الأداء مقابل قابلية التطوير:
* إذا كان لديك مشكلة في **الأداء**، فإن نظامك بطيء لمستخدم واحد.
* إذا كان لديك مشكلة في **قابلية التطوير**، فإن نظامك سريع لمستخدم واحد ولكنه بطيء تحت الحمل الثقيل.
### المصادر وقراءات إضافية
* [كلمة عن قابلية التطوير](http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)
* [أنماط قابلية التطوير والتوافر والاستقرار](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
## زمن الاستجابة مقابل الإنتاجية
**زمن الاستجابة** هو الوقت المستغرق لتنفيذ إجراء ما أو إنتاج نتيجة ما.
**الإنتاجية** هي عدد هذه الإجراءات أو النتائج في وحدة الزمن.
بشكل عام، يجب أن تهدف إلى **أقصى إنتاجية** مع **زمن استجابة مقبول**.
### المصادر وقراءات إضافية
* [فهم زمن الاستجابة مقابل الإنتاجية](https://community.cadence.com/cadence_blogs_8/b/fv/posts/understanding-latency-vs-throughput)
## التوافر مقابل الاتساق
### نظرية CAP
<p align="center">
<img src="images/bgLMI2u.png">
<br/>
<i><a href=http://robertgreiner.com/2014/08/cap-theorem-revisited>المصدر: مراجعة نظرية CAP</a></i>
</p>
في نظام الحوسبة الموزع، يمكنك فقط دعم اثنين من الضمانات التالية:
* **الاتساق** - كل عملية قراءة تستقبل أحدث عملية كتابة أو خطأ
* **التوافر** - كل طلب يتلقى استجابة، دون ضمان أنها تحتوي على أحدث نسخة من المعلومات
* **تحمل التجزئة** - يستمر النظام في العمل رغم التجزئة العشوائية بسبب أعطال الشبكة
*الشبكات ليست موثوقة، لذا ستحتاج إلى دعم تحمل التجزئة. ستحتاج إلى المفاضلة بين الاتساق والتوافر.*
#### CP - الاتساق وتحمل التجزئة
قد يؤدي انتظار استجابة من العقدة المجزأة إلى خطأ انتهاء المهلة. CP هو خيار جيد إذا كانت متطلبات عملك تتطلب عمليات قراءة وكتابة ذرية.
#### AP - التوافر وتحمل التجزئة
تقوم الاستجابات بإرجاع النسخة المتاحة بشكل أسرع من البيانات المتوفرة على أي عقدة، والتي قد لا تكون الأحدث. قد تستغرق عمليات الكتابة بعض الوقت للانتشار عند حل التجزئة.
AP هو خيار جيد إذا كانت متطلبات العمل تسمح بـ [الاتساق النهائي](#eventual-consistency) أو عندما يحتاج النظام إلى مواصلة العمل رغم الأخطاء الخارجية.
### المصادر وقراءات إضافية
* [مراجعة نظرية CAP](http://robertgreiner.com/2014/08/cap-theorem-revisited/)
* [مقدمة مبسطة لنظرية CAP](http://ksat.me/a-plain-english-introduction-to-cap-theorem)
* [الأسئلة الشائعة حول CAP](https://github.com/henryr/cap-faq)
* [نظرية CAP](https://www.youtube.com/watch?v=k-Yaq8AHlFA)
## أنماط الاتساق
مع وجود نسخ متعددة من نفس البيانات، نواجه خيارات حول كيفية مزامنتها حتى يكون لدى العملاء رؤية متسقة للبيانات. تذكر تعريف الاتساق من [نظرية CAP](#cap-theorem) - كل عملية قراءة تستقبل أحدث عملية كتابة أو خطأ.
### الاتساق الضعيف
بعد الكتابة، قد ترى عمليات القراءة التغيير أو لا تراه. يتم اتباع نهج أفضل جهد.
يظهر هذا النهج في أنظمة مثل memcached. يعمل الاتساق الضعيف بشكل جيد في حالات الاستخدام في الوقت الفعلي مثل VoIP ودردشة الفيديو والألعاب متعددة اللاعبين في الوقت الفعلي. على سبيل المثال، إذا كنت في مكالمة هاتفية وفقدت الاتصال لبضع ثوانٍ، عندما تستعيد الاتصال لن تسمع ما قيل أثناء فقدان الاتصال.
### الاتساق النهائي
بعد الكتابة، سترى عمليات القراءة التغيير في النهاية (عادةً خلال مللي ثانية). يتم نسخ البيانات بشكل غير متزامن.
يظهر هذا النهج في أنظمة مثل DNS والبريد الإلكتروني. يعمل الاتساق النهائي بشكل جيد في الأنظمة عالية التوافر.
### الاتساق القوي
بعد الكتابة، سترى عمليات القراءة التغيير. يتم نسخ البيانات بشكل متزامن.
يظهر هذا النهج في أنظمة الملفات وأنظمة RDBMS. يعمل الاتساق القوي بشكل جيد في الأنظمة التي تحتاج إلى المعاملات.
### المصادر وقراءات إضافية
* [المعاملات عبر مراكز البيانات](http://snarfed.org/transactions_across_datacenters_io.html)
## أنماط التوافر
هناك نمطان متكاملان لدعم التوافر العالي: **التحول عند الفشل** و**النسخ المتماثل**.
### التحول عند الفشل
#### نشط-سلبي
في التحول عند الفشل نشط-سلبي، يتم إرسال نبضات القلب بين الخادم النشط والخادم السلبي في وضع الانتظار. إذا تم قطع نبضات القلب، يتولى الخادم السلبي عنوان IP الخاص بالخادم النشط ويستأنف الخدمة.
يتحدد طول وقت التوقف بما إذا كان الخادم السلبي يعمل بالفعل في وضع الانتظار 'الساخن' أو ما إذا كان يحتاج إلى بدء التشغيل من وضع الانتظار 'البارد'. يتعامل الخادم النشط فقط مع حركة المرور.
يمكن أيضًا الإشارة إلى التحول عند الفشل نشط-سلبي باسم التحول عند الفشل رئيسي-تابع.
#### نشط-نشط
في نشط-نشط، كلا الخادمين يديران حركة المرور، موزعين الحمل بينهما.
إذا كانت الخوادم مواجهة للجمهور، فسيحتاج DNS إلى معرفة عناوين IP العامة لكلا الخادمين. إذا كانت الخوادم داخلية، فسيحتاج منطق التطبيق إلى معرفة كلا الخادمين.
يمكن أيضًا الإشارة إلى التحول عند الفشل نشط-نشط باسم التحول عند الفشل رئيسي-رئيسي.
### عيوب التحول عند الفشل
* يضيف التحول عند الفشل المزيد من الأجهزة وتعقيدات إضافية.
* هناك احتمال لفقدان البيانات إذا فشل النظام النشط قبل أن يتمكن من نسخ أي بيانات مكتوبة حديثًا إلى النظام السلبي.
### النسخ المتماثل
#### رئيسي-تابع ورئيسي-رئيسي
تتم مناقشة هذا الموضوع بشكل أكبر في قسم [قاعدة البيانات](#database):
* [النسخ المتماثل رئيسي-تابع](#master-slave-replication)
* [النسخ المتماثل رئيسي-رئيسي](#master-master-replication)
### التوافر بالأرقام
غالبًا ما يتم قياس التوافر من خلال وقت التشغيل (أو وقت التوقف) كنسبة مئوية من الوقت الذي تكون فيه الخدمة متاحة. يتم قياس التوافر عمومًا بعدد الـ 9 - خدمة بتوافر 99.99% يوصف بأن لديها أربعة 9.
#### توافر 99.9% - ثلاثة 9
| المدة | وقت التوقف المقبول |
|---------------------|--------------------|
| وقت التوقف سنوياً | 8 ساعات 45 دقيقة 57 ثانية |
| وقت التوقف شهرياً | 43 دقيقة 49.7 ثانية |
| وقت التوقف أسبوعياً | 10 دقائق 4.8 ثانية |
| وقت التوقف يومياً | 1 دقيقة 26.4 ثانية |
#### توافر 99.99% - أربعة 9
| المدة | وقت التوقف المقبول |
|---------------------|--------------------|
| وقت التوقف سنوياً | 52 دقيقة 35.7 ثانية |
| وقت التوقف شهرياً | 4 دقائق 23 ثانية |
| وقت التوقف أسبوعياً | 1 دقيقة 5 ثانية |
| وقت التوقف يومياً | 8.6 ثانية |
#### التوافر على التوازي مقابل التوافر على التوالي
إذا كانت الخدمة تتكون من مكونات متعددة قابلة للفشل، فإن التوافر الإجمالي للخدمة يعتمد على ما إذا كانت المكونات مرتبة على التوالي أو على التوازي.
###### على التوالي
ينخفض التوافر الإجمالي عندما يكون هناك مكونان بتوافر أقل من 100% على التوالي:
```
Availability (Total) = Availability (Foo) * Availability (Bar)
```
إذا كان كل من `Foo` و `Bar` لديهما توافر بنسبة 99.9%، فإن توافرهما الإجمالي على التوالي سيكون 99.8%.
###### على التوازي
يزداد التوافر الإجمالي عندما يكون هناك مكونان بتوافر أقل من 100% على التوازي:
```
Availability (Total) = 1 - (1 - Availability (Foo)) * (1 - Availability (Bar))
```
إذا كان كل من `Foo` و `Bar` لديهما توافر بنسبة 99.9%، فإن توافرهما الإجمالي على التوازي سيكون 99.9999%.
## نظام أسماء النطاقات (Domain Name System)
<p align="center">
<img src="images/IOyLj4i.jpg">
<br/>
<i><a href=http://www.slideshare.net/srikrupa5/dns-security-presentation-issa>المصدر: عرض تقديمي عن أمان DNS</a></i>
</p>
يقوم نظام أسماء النطاقات (DNS) بترجمة اسم النطاق مثل www.example.com إلى عنوان IP.
نظام DNS هرمي، مع وجود عدد قليل من الخوادم الموثوقة في المستوى الأعلى. يوفر جهاز التوجيه (router) أو مزود خدمة الإنترنت (ISP) الخاص بك معلومات حول خادم (أو خوادم) DNS التي يجب الاتصال بها عند إجراء عملية البحث. تقوم خوادم DNS في المستويات الأدنى بتخزين التعيينات مؤقتًا، والتي قد تصبح قديمة بسبب تأخيرات انتشار DNS. يمكن أيضًا تخزين نتائج DNS مؤقتًا بواسطة المتصفح أو نظام التشغيل لفترة زمنية معينة، يحددها [وقت الصلاحية (TTL)](https://en.wikipedia.org/wiki/Time_to_live).
* **سجل NS (خادم الأسماء)** - يحدد خوادم DNS للنطاق/النطاق الفرعي الخاص بك.
* **سجل MX (تبادل البريد)** - يحدد خوادم البريد لقبول الرسائل.
* **سجل A (العنوان)** - يوجه اسمًا إلى عنوان IP.
* **سجل CNAME (الاسم القانوني)** - يوجه اسمًا إلى اسم آخر أو `CNAME` (example.com إلى www.example.com) أو إلى سجل `A`.
توفر خدمات مثل [CloudFlare](https://www.cloudflare.com/dns/) و [Route 53](https://aws.amazon.com/route53/) خدمات DNS مُدارة. يمكن لبعض خدمات DNS توجيه حركة المرور من خلال طرق مختلفة:
* [التوزيع الدائري المرجح (Weighted round robin)](https://www.jscape.com/blog/load-balancing-algorithms)
* منع حركة المرور من الذهاب إلى الخوادم قيد الصيانة
* الموازنة بين المجموعات المتفاوتة الحجم
* اختبار A/B
* [التوجيه المبني على زمن الاستجابة (Latency-based)](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-latency.html)
* [التوجيه المبني على الموقع الجغرافي (Geolocation-based)](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-geo.html)
### عيوب نظام DNS
* يؤدي الوصول إلى خادم DNS إلى تأخير طفيف، على الرغم من تخفيف ذلك من خلال التخزين المؤقت الموضح أعلاه.
* يمكن أن تكون إدارة خادم DNS معقدة وتتم إدارتها عموماً من قبل [الحكومات ومزودي خدمة الإنترنت والشركات الكبرى](http://superuser.com/questions/472695/who-controls-the-dns-servers/472729).
* تعرضت خدمات DNS مؤخراً [لهجمات DDoS](http://dyn.com/blog/dyn-analysis-summary-of-friday-october-21-attack/)، مما منع المستخدمين من الوصول إلى مواقع مثل Twitter دون معرفة عنوان (عناوين) IP الخاصة به.
### المصادر وقراءات إضافية
* [بنية DNS](https://technet.microsoft.com/en-us/library/dd197427(v=ws.10).aspx)
* [ويكيبيديا](https://en.wikipedia.org/wiki/Domain_Name_System)
* [مقالات DNS](https://support.dnsimple.com/categories/dns/)
## شبكة توصيل المحتوى (CDN)
<p align="center">
<img src="images/h9TAuGI.jpg">
<br/>
<i><a href=https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/>المصدر: لماذا نستخدم CDN</a></i>
</p>
شبكة توصيل المحتوى (CDN) هي شبكة عالمية موزعة من الخوادم الوسيطة، تقدم المحتوى من مواقع أقرب إلى المستخدم. عادةً، يتم تقديم الملفات الثابتة مثل HTML/CSS/JS والصور ومقاطع الفيديو من CDN، على الرغم من أن بعض شبكات CDN مثل CloudFront من Amazon تدعم المحتوى الديناميكي. سيخبر حل DNS للموقع العملاء بالخادم الذي يجب الاتصال به.
يمكن أن يؤدي تقديم المحتوى من شبكات CDN إلى تحسين الأداء بشكل كبير بطريقتين:
* يتلقى المستخدمون المحتوى من مراكز البيانات القريبة منهم
* لا تحتاج خوادمك إلى خدمة الطلبات التي تلبيها CDN
### شبكات CDN للدفع (Push CDNs)
تتلقى شبكات CDN للدفع محتوى جديداً كلما حدثت تغييرات على خادمك. أنت تتحمل المسؤولية الكاملة عن توفير المحتوى، والرفع مباشرة إلى CDN وإعادة كتابة عناوين URL للإشارة إلى CDN. يمكنك تكوين متى ينتهي المحتوى ومتى يتم تحديثه. يتم رفع المحتوى فقط عندما يكون جديداً أو تم تغييره، مما يقلل حركة المرور، ولكن يزيد التخزين إلى أقصى حد.
المواقع التي لديها قدر قليل من حركة المرور أو المواقع التي لا يتم تحديث محتواها بشكل متكرر تعمل بشكل جيد مع شبكات CDN للدفع. يتم وضع المحتوى على شبكات CDN مرة واحدة، بدلاً من إعادة سحبه على فترات منتظمة.
### شبكات CDN للسحب (Pull CDNs)
تقوم شبكات CDN للسحب بجلب المحتوى الجديد من خادمك عندما يطلب المستخدم الأول هذا المحتوى. تترك المحتوى على خادمك وتقوم بإعادة كتابة عناوين URL للإشارة إلى CDN. يؤدي هذا إلى طلب أبطأ حتى يتم تخزين المحتوى مؤقتًا على CDN.
يحدد [وقت الصلاحية (TTL)](https://en.wikipedia.org/wiki/Time_to_live) المدة التي يتم فيها تخزين المحتوى مؤقتًا. تقلل شبكات CDN للسحب من مساحة التخزين على CDN، ولكنها قد تخلق حركة مرور زائدة إذا انتهت صلاحية الملفات وتم سحبها قبل تغييرها فعلياً.
تعمل المواقع ذات حركة المرور الكثيفة بشكل جيد مع شبكات CDN للسحب، حيث يتم توزيع حركة المرور بشكل أكثر توازناً مع بقاء المحتوى المطلوب مؤخراً فقط على CDN.
### عيوب CDN
* قد تكون تكاليف CDN كبيرة اعتماداً على حركة المرور، على الرغم من أنه يجب موازنة ذلك مع التكاليف الإضافية التي قد تتكبدها عند عدم استخدام CDN.
* قد يصبح المحتوى قديماً إذا تم تحديثه قبل انتهاء صلاحية TTL.
* تتطلب شبكات CDN تغيير عناوين URL للمحتوى الثابت للإشارة إلى CDN.
### المصادر وقراءات إضافية
* [توصيل المحتوى الموزع عالمياً](https://figshare.com/articles/Globally_distributed_content_delivery/6605972)
* [الفروق بين شبكات CDN للدفع والسحب](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)
* [ويكيبيديا](https://en.wikipedia.org/wiki/Content_delivery_network)
## موازن التحميل (Load Balancer)
<p align="center">
<img src="images/h81n9iK.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>المصدر: أنماط تصميم النظم القابلة للتطوير</a></i>
</p>
يقوم موازن التحميل بتوزيع طلبات العملاء الواردة على موارد الحوسبة مثل خوادم التطبيقات وقواعد البيانات. في كل حالة، يقوم موازن التحميل بإرجاع الاستجابة من مورد الحوسبة إلى العميل المناسب. موازنات التحميل فعالة في:
* منع الطلبات من الذهاب إلى الخوادم غير الصحية
* منع التحميل الزائد على الموارد
* المساعدة في القضاء على نقطة الفشل الوحيدة
يمكن تنفيذ موازنات التحميل باستخدام الأجهزة (مكلفة) أو البرمجيات مثل HAProxy.
تشمل المزايا الإضافية:
* **إنهاء SSL** - فك تشفير الطلبات الواردة وتشفير استجابات الخادم بحيث لا تحتاج الخوادم الخلفية إلى تنفيذ هذه العمليات المكلفة محتملاً
* يزيل الحاجة إلى تثبيت [شهادات X.509](https://en.wikipedia.org/wiki/X.509) على كل خادم
* **استمرارية الجلسة** - إصدار ملفات تعريف الارتباط (cookies) وتوجيه طلبات عميل محدد إلى نفس النسخة إذا كانت تطبيقات الويب لا تتتبع الجلسات
للحماية من الأعطال، من الشائع إعداد موازنات تحميل متعددة، إما في وضع [نشط-سلبي](#active-passive) أو [نشط-نشط](#active-active).
يمكن لموازنات التحميل توجيه حركة المرور بناءً على مقاييس مختلفة، بما في ذلك:
* عشوائي
* الأقل تحميلاً
* الجلسات/ملفات تعريف الارتباط
* [التوزيع الدائري أو التوزيع الدائري المرجح](https://www.g33kinfo.com/info/round-robin-vs-weighted-round-robin-lb)
* [موازنة التحميل في الطبقة 4](#layer-4-load-balancing)
* [موازنة التحميل في الطبقة 7](#layer-7-load-balancing)
### موازنة التحميل في الطبقة 4
تنظر موازنات التحميل في الطبقة 4 إلى المعلومات في [طبقة النقل](#communication) لتقرر كيفية توزيع الطلبات. عموماً، يتضمن هذا عناوين IP المصدر والوجهة والمنافذ في الرأس، ولكن ليس محتويات الحزمة. تقوم موازنات التحميل في الطبقة 4 بإعادة توجيه حزم الشبكة من وإلى الخادم الأعلى، مع تنفيذ [ترجمة عناوين الشبكة (NAT)](https://www.nginx.com/resources/glossary/layer-4-load-balancing/).
### موازنة التحميل في الطبقة 7
تنظر موازنات التحميل في الطبقة 7 إلى [طبقة التطبيق](#communication) لتقرر كيفية توزيع الطلبات. يمكن أن يتضمن هذا محتويات الرأس والرسالة وملفات تعريف الارتباط. تقوم موازنات التحميل في الطبقة 7 بإنهاء حركة الشبكة، وقراءة الرسالة، واتخاذ قرار موازنة التحميل، ثم فتح اتصال مع الخادم المحدد. على سبيل المثال، يمكن لموازن التحميل في الطبقة 7 توجيه حركة الفيديو إلى خوادم تستضيف الفيديوهات بينما يوجه حركة فواتير المستخدمين الأكثر حساسية إلى خوادم محصنة أمنياً.
على حساب المرونة، تتطلب موازنة التحميل في الطبقة 4 وقتاً وموارد حوسبة أقل من الطبقة 7، على الرغم من أن تأثير الأداء يمكن أن يكون ضئيلاً على الأجهزة السلعية الحديثة.
### التطوير الأفقي
يمكن أن تساعد موازنات التحميل أيضاً في التطوير الأفقي، مما يحسن الأداء والتوافر. التطوير باستخدام الأجهزة السلعية أكثر فعالية من حيث التكلفة ويؤدي إلى توافر أعلى من تطوير خادم واحد على أجهزة أكثر تكلفة، وهو ما يسمى **التطوير الرأسي**. كما أنه من الأسهل توظيف المواهب التي تعمل على الأجهزة السلعية مقارنة بأنظمة المؤسسات المتخصصة.
#### عيوب التطوير الأفقي
* يقدم التطوير الأفقي تعقيداً ويتضمن استنساخ الخوادم
* يجب أن تكون الخوادم بدون حالة: يجب ألا تحتوي على أي بيانات متعلقة بالمستخدم مثل الجلسات أو صور الملف الشخصي
* يمكن تخزين الجلسات في مخزن بيانات مركزي مثل [قاعدة البيانات](#database) (SQL، NoSQL) أو [ذاكرة التخزين المؤقت](#cache) المستمرة (Redis، Memcached)
* تحتاج الخوادم السفلية مثل ذاكرة التخزين المؤقت وقواعد البيانات إلى التعامل مع المزيد من الاتصالات المتزامنة مع توسع الخوادم العلوية
### عيوب موازن التحميل
* يمكن أن يصبح موازن التحميل نقطة اختناق في الأداء إذا لم يكن لديه موارد كافية أو إذا لم يتم تكوينه بشكل صحيح.
* يؤدي إدخال موازن تحميل للمساعدة في القضاء على نقطة الفشل الوحيدة إلى زيادة التعقيد.
* موازن التحميل الواحد هو نقطة فشل وحيدة، وتكوين موازنات تحميل متعددة يزيد من التعقيد.
### المصادر وقراءات إضافية
* [بنية NGINX](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [دليل بنية HAProxy](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [قابلية التطوير](http://www.lecloud.net/post/7295452622/scalability-for-dummies-part-1-clones)
* [ويكيبيديا](https://en.wikipedia.org/wiki/Load_balancing_(computing))
* [موازنة التحميل في الطبقة 4](https://www.nginx.com/resources/glossary/layer-4-load-balancing/)
* [موازنة التحميل في الطبقة 7](https://www.nginx.com/resources/glossary/layer-7-load-balancing/)
* [تكوين مستمع ELB](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html)
## الوكيل العكسي (خادم الويب)
<p align="center">
<img src="images/n41Azff.png">
<br/>
<i><a href=https://upload.wikimedia.org/wikipedia/commons/6/67/Reverse_proxy_h2g2bob.svg>المصدر: ويكيبيديا</a></i>
<br/>
</p>
الوكيل العكسي هو خادم ويب يقوم بمركزة الخدمات الداخلية وتوفير واجهات موحدة للجمهور. يتم توجيه الطلبات من العملاء إلى خادم يمكنه تلبيتها قبل أن يقوم الوكيل العكسي بإرجاع استجابة الخادم إلى العميل.
تشمل المزايا الإضافية:
* **تحسين الأمان** - إخفاء معلومات عن الخوادم الخلفية، حظر عناوين IP، تحديد عدد الاتصالات لكل عميل
* **زيادة قابلية التطوير والمرونة** - يرى العملاء فقط عنوان IP للوكيل العكسي، مما يتيح لك تطوير الخوادم أو تغيير إعداداتها
* **إنهاء SSL** - فك تشفير الطلبات الواردة وتشفير استجابات الخادم بحيث لا تحتاج الخوادم الخلفية إلى تنفيذ هذه العمليات المكلفة محتملاً
* يزيل الحاجة إلى تثبيت [شهادات X.509](https://en.wikipedia.org/wiki/X.509) على كل خادم
* **الضغط** - ضغط استجابات الخادم
* **التخزين المؤقت** - إرجاع الاستجابة للطلبات المخزنة مؤقتاً
* **المحتوى الثابت** - تقديم المحتوى الثابت مباشرة
* HTML/CSS/JS
* الصور
* الفيديوهات
* إلخ
### موازن التحميل مقابل الوكيل العكسي
* يكون نشر موازن التحميل مفيداً عندما يكون لديك خوادم متعددة. غالباً ما يوجه موازن التحميل حركة المرور إلى مجموعة من الخوادم التي تؤدي نفس الوظيفة.
* يمكن أن يكون الوكيل العكسي مفيداً حتى مع خادم ويب واحد أو خادم تطبيق واحد، مما يتيح المزايا الموضحة في القسم السابق.
* يمكن للحلول مثل NGINX وHAProxy دعم كل من الوكيل العكسي في الطبقة 7 وموازنة التحميل.
### عيوب الوكيل العكسي
* إدخال وكيل عكسي يؤدي إلى زيادة التعقيد.
* الوكيل العكسي الواحد هو نقطة فشل وحيدة، وتكوين وكلاء عكسيين متعددين (مثل [التجاوز عند الفشل](https://en.wikipedia.org/wiki/Failover)) يزيد من التعقيد.
### المصادر وقراءات إضافية
* [الوكيل العكسي مقابل موازن التحميل](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)
* [بنية NGINX](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [دليل بنية HAProxy](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [ويكيبيديا](https://en.wikipedia.org/wiki/Reverse_proxy)
## طبقة التطبيق
<p align="center">
<img src="images/yB5SYwm.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>المصدر: مقدمة في تصميم الأنظمة للتطوير</a></i>
</p>
فصل طبقة الويب عن طبقة التطبيق (المعروفة أيضاً باسم طبقة المنصة) يتيح لك تطوير وتكوين كلا الطبقتين بشكل مستقل. إضافة API جديد يؤدي إلى إضافة خوادم تطبيق دون الحاجة بالضرورة إلى إضافة خوادم ويب إضافية. يدعم **مبدأ المسؤولية الواحدة** الخدمات الصغيرة والمستقلة التي تعمل معاً. يمكن للفرق الصغيرة مع الخدمات الصغيرة التخطيط بشكل أكثر فعالية للنمو السريع.
العاملون في طبقة التطبيق يساعدون أيضاً في تمكين [اللاتزامن](#asynchronism).
### الخدمات المصغرة (Microservices)
ترتبط بهذا النقاش [الخدمات المصغرة](https://en.wikipedia.org/wiki/Microservices)، والتي يمكن وصفها كمجموعة من الخدمات المستقلة القابلة للنشر، الصغيرة والمعيارية. تعمل كل خدمة كعملية فريدة وتتواصل من خلال آلية خفيفة محددة جيداً لخدمة هدف تجاري. <sup><a href=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
على سبيل المثال، يمكن أن يكون لدى Pinterest الخدمات المصغرة التالية: ملف المستخدم، المتابعين، التغذية، البحث، رفع الصور، وغيرها.
### اكتشاف الخدمة (Service Discovery)
يمكن لأنظمة مثل [Consul](https://www.consul.io/docs/index.html) و[Etcd](https://coreos.com/etcd/docs/latest) و[Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) مساعدة الخدمات في العثور على بعضها البعض من خلال تتبع الأسماء والعناوين والمنافذ المسجلة. تساعد [فحوصات الصحة](https://www.consul.io/intro/getting-started/checks.html) في التحقق من سلامة الخدمة وغالباً ما تتم باستخدام نقطة نهاية [HTTP](#hypertext-transfer-protocol-http). يحتوي كل من Consul وEtcd على [مخزن للقيم المفتاحية](#key-value-store) مدمج يمكن أن يكون مفيداً لتخزين قيم التكوين والبيانات المشتركة الأخرى.
### عيوب طبقة التطبيق
* إضافة طبقة تطبيق مع خدمات مقترنة بشكل فضفاض يتطلب نهجاً مختلفاً من وجهة نظر معمارية وتشغيلية وعملية (مقارنة بالنظام المتكامل).
* يمكن أن تضيف الخدمات المصغرة تعقيداً من حيث النشر والعمليات.
### المصادر وقراءات إضافية
* [مقدمة في تصميم الأنظمة للتطوير](http://lethain.com/introduction-to-architecting-systems-for-scale)
* [حل مقابلة تصميم النظام](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [البنية الموجهة للخدمات](https://en.wikipedia.org/wiki/Service-oriented_architecture)
* [مقدمة إلى Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper)
* [إليك ما تحتاج معرفته حول بناء الخدمات المصغرة](https://cloudncode.wordpress.com/2016/07/22/msa-getting-started/)
## قاعدة البيانات (Database)
<p align="center">
<img src="images/Xkm5CXz.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>المصدر: التطوير حتى 10 ملايين مستخدم</a></i>
</p>
### نظام إدارة قواعد البيانات العلائقية (RDBMS)
قاعدة البيانات العلائقية مثل SQL هي مجموعة من عناصر البيانات المنظمة في جداول.
**ACID** هي مجموعة من خصائص [المعاملات](https://en.wikipedia.org/wiki/Database_transaction) في قواعد البيانات العلائقية.
* **الذرية (Atomicity)** - كل معاملة إما تتم بالكامل أو لا تتم مطلقاً
* **الاتساق (Consistency)** - أي معاملة ستنقل قاعدة البيانات من حالة صحيحة إلى أخرى
* **العزل (Isolation)** - تنفيذ المعاملات بالتوازي يؤدي إلى نفس النتائج كما لو تم تنفيذها بشكل متسلسل
* **الديمومة (Durability)** - بمجرد إتمام المعاملة، ستظل كذلك
هناك العديد من التقنيات لتطوير قاعدة بيانات علائقية: **النسخ المتماثل رئيسي-تابع**، **النسخ المتماثل رئيسي-رئيسي**، **الفيدرالية**، **التجزئة**، **إلغاء التطبيع**، و**تحسين SQL**.
#### النسخ المتماثل رئيسي-تابع (Master-slave replication)
يخدم الرئيسي عمليات القراءة والكتابة، مع نسخ عمليات الكتابة إلى تابع واحد أو أكثر، والتي تخدم القراءة فقط. يمكن للتوابع أيضاً النسخ إلى توابع إضافية في شكل شجري. إذا توقف الرئيسي عن العمل، يمكن للنظام الاستمرار في العمل في وضع القراءة فقط حتى يتم ترقية تابع ليصبح رئيسياً أو يتم توفير رئيسي جديد.
<p align="center">
<img src="images/C9ioGtn.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>المصدر: أنماط قابلية التطوير والتوافر والاستقرار</a></i>
</p>
##### عيوب النسخ المتماثل رئيسي-تابع
* هناك حاجة إلى منطق إضافي لترقية تابع إلى رئيسي.
* انظر [عيوب: النسخ المتماثل](#disadvantages-replication) للنقاط المتعلقة **بكل من** النسخ المتماثل رئيسي-تابع ورئيسي-رئيسي.
#### النسخ المتماثل رئيسي-رئيسي (Master-master replication)
كلا الرئيسيين يخدمان القراءة والكتابة وينسقان مع بعضهما البعض في عمليات الكتابة. إذا توقف أي من الرئيسيين عن العمل، يمكن للنظام الاستمرار في العمل مع كل من القراءة والكتابة.
<p align="center">
<img src="images/krAHLGg.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>المصدر: أنماط قابلية التطوير والتوافر والاستقرار</a></i>
</p>
##### عيوب النسخ المتماثل رئيسي-رئيسي
* ستحتاج إلى موازن تحميل أو ستحتاج إلى إجراء تغييرات في منطق تطبيقك لتحديد مكان الكتابة.
* معظم أنظمة رئيسي-رئيسي إما متسقة بشكل فضفاض (مخالفة لـ ACID) أو لديها زمن استجابة متزايد للكتابة بسبب المزامنة.
* يزداد حل التعارض أهمية مع إضافة المزيد من نقاط الكتابة ومع زيادة زمن الاستجابة.
* انظر [عيوب: النسخ المتماثل](#disadvantages-replication) للنقاط المتعلقة **بكل من** النسخ المتماثل رئيسي-تابع ورئيسي-رئيسي.
##### عيوب النسخ المتماثل
* هناك احتمال لفقدان البيانات إذا فشل الرئيسي قبل نسخ أي بيانات جديدة مكتوبة إلى العقد الأخرى.
* يتم إعادة تشغيل عمليات الكتابة على نسخ القراءة. إذا كان هناك الكثير من عمليات الكتابة، يمكن أن تتعثر نسخ القراءة في إعادة تشغيل عمليات الكتابة ولا يمكنها إجراء الكثير من عمليات القراءة.
* كلما زاد عدد توابع القراءة، كلما زاد ما يجب نسخه، مما يؤدي إلى تأخير أكبر في النسخ.
* في بعض الأنظمة، يمكن للكتابة إلى الرئيسي إنشاء مسارات متعددة للكتابة بالتوازي، في حين أن نسخ القراءة تدعم فقط الكتابة بشكل متسلسل مع مسار واحد.
* النسخ المتماثل يضيف المزيد من العتاد والتعقيد.
##### المصادر وقراءات إضافية: النسخ المتماثل
* [أنماط قابلية التطوير والتوافر والاستقرار](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [النسخ المتماثل رئيسي-رئيسي](https://en.wikipedia.org/wiki/Multi-master_replication)
#### الفيدرالية (Federation)
<p align="center">
<img src="images/U3qV33e.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>المصدر: التطوير حتى 10 ملايين مستخدم</a></i>
</p>
الفيدرالية (أو التقسيم الوظيفي) تقسم قواعد البيانات حسب الوظيفة. على سبيل المثال، بدلاً من قاعدة بيانات واحدة متكاملة، يمكن أن يكون لديك ثلاث قواعد بيانات: **المنتديات**، **المستخدمين**، و**المنتجات**، مما يؤدي إلى تقليل حركة القراءة والكتابة لكل قاعدة بيانات وبالتالي تقليل تأخير النسخ. قواعد البيانات الأصغر تؤدي إلى المزيد من البيانات التي يمكن أن تتناسب في الذاكرة، مما يؤدي بدوره إلى المزيد من نجاحات التخزين المؤقت بسبب تحسين موقعية التخزين المؤقت. مع عدم وجود رئيسي مركزي واحد لتسلسل عمليات الكتابة، يمكنك الكتابة بالتوازي، مما يزيد من الإنتاجية.
##### عيوب الفيدرالية
* الفيدرالية ليست فعالة إذا كان مخططك يتطلب وظائف أو جداول ضخمة.
* ستحتاج إلى تحديث منطق تطبيقك لتحديد قاعدة البيانات التي يجب القراءة منها والكتابة إليها.
* دمج البيانات من قاعدتي بيانات أكثر تعقيداً مع [رابط الخادم](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers).
* الفيدرالية تضيف المزيد من العتاد والتعقيد الإضافي.
##### المصادر وقراءات إضافية: الفيدرالية
* [التطوير حتى 10 ملايين مستخدم الأوائل](https://www.youtube.com/watch?v=kKjm4ehYiMs)
#### التجزئة (Sharding)
<p align="center">
<img src="images/wU8x5Id.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>المصدر: أنماط قابلية التطوير والتوافر والاستقرار</a></i>
</p>
التجزئة توزع البيانات عبر قواعد بيانات مختلفة بحيث يمكن لكل قاعدة بيانات إدارة جزء فرعي فقط من البيانات. باستخدام قاعدة بيانات المستخدمين كمثال، مع زيادة عدد المستخدمين، تتم إضافة المزيد من الأجزاء إلى المجموعة.
مشابهة لمزايا [الفيدرالية](#federation)، تؤدي التجزئة إلى تقليل حركة القراءة والكتابة، وتقليل النسخ المتماثل، وزيادة نجاحات التخزين المؤقت. يتم أيضاً تقليل حجم الفهرس، مما يحسن الأداء عموماً مع استعلامات أسرع. إذا تعطل جزء واحد، تظل الأجزاء الأخرى تعمل، على الرغم من أنك ستحتاج إلى إضافة شكل من أشكال النسخ المتماثل لتجنب فقدان البيانات. مثل الفيدرالية، لا يوجد رئيسي مركزي واحد لتسلسل عمليات الكتابة، مما يتيح لك الكتابة بالتوازي مع زيادة الإنتاجية.
الطرق الشائعة لتجزئة جدول المستخدمين إما من خلال الحرف الأول من اسم المستخدم الأخير أو الموقع الجغرافي للمستخدم.
##### عيوب التجزئة
* ستحتاج إلى تحديث منطق تطبيقك للعمل مع الأجزاء، مما قد يؤدي إلى استعلامات SQL معقدة.
* يمكن أن يصبح توزيع البيانات غير متوازن في جزء معين. على سبيل المثال، قد تؤدي مجموعة من المستخدمين النشطين في جزء واحد إلى زيادة الحمل على ذلك الجزء مقارنة بالآخرين.
* إعادة التوازن تضيف تعقيداً إضافياً. يمكن لدالة التجزئة المبنية على [التجزئة المتناسقة](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html) تقليل كمية البيانات المنقولة.
* ربط البيانات من أجزاء متعددة أكثر تعقيداً.
* التجزئة تضيف المزيد من العتاد والتعقيد الإضافي.
##### المصادر وقراءات إضافية: التجزئة
* [قدوم التجزئة](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)
* [بنية قاعدة بيانات التجزئة](https://en.wikipedia.org/wiki/Shard_(database_architecture))
* [التجزئة المتناسقة](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)
#### إلغاء التطبيع (Denormalization)
إلغاء التطبيع يحاول تحسين أداء القراءة على حساب بعض أداء الكتابة. يتم كتابة نسخ متكررة من البيانات في جداول متعددة لتجنب عمليات الربط المكلفة. بعض أنظمة RDBMS مثل [PostgreSQL](https://en.wikipedia.org/wiki/PostgreSQL) و Oracle تدعم [العروض المادية](https://en.wikipedia.org/wiki/Materialized_view) التي تتعامل مع عمل تخزين المعلومات المتكررة والحفاظ على اتساق النسخ المتكررة.
بمجرد أن تصبح البيانات موزعة باستخدام تقنيات مثل [الفيدرالية](#federation) و[التجزئة](#sharding)، تزداد تعقيدات إدارة عمليات الربط عبر مراكز البيانات. قد يتجنب إلغاء التطبيع الحاجة إلى مثل هذه العمليات المعقدة للربط.
في معظم الأنظمة، يمكن أن تفوق عمليات القراءة عمليات الكتابة بنسبة 100:1 أو حتى 1000:1. القراءة التي تؤدي إلى عملية ربط معقدة في قاعدة البيانات يمكن أن تكون مكلفة للغاية، وتقضي وقتاً كبيراً في عمليات القرص.
##### عيوب إلغاء التطبيع
* البيانات مكررة.
* القيود يمكن أن تساعد النسخ المتكررة من المعلومات على البقاء متزامنة، مما يزيد من تعقيد تصميم قاعدة البيانات.
* قاعدة البيانات غير المطبعة تحت حمل كتابة كثيف قد تؤدي أداءً أسوأ من نظيرتها المطبعة.
##### المصادر وقراءات إضافية: إلغاء التطبيع
* [إلغاء التطبيع](https://en.wikipedia.org/wiki/Denormalization)
#### تحسين SQL
تحسين SQL هو موضوع واسع وقد كُتبت العديد من [الكتب](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning) كمرجع.
من المهم إجراء **اختبارات الأداء** و**التنميط** لمحاكاة واكتشاف نقاط الاختناق.
* **اختبارات الأداء** - محاكاة حالات الحمل العالي باستخدام أدوات مثل [ab](http://httpd.apache.org/docs/2.2/programs/ab.html).
* **التنميط** - تمكين أدوات مثل [سجل الاستعلامات البطيئة](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html) للمساعدة في تتبع مشاكل الأداء.
قد تشير اختبارات الأداء والتنميط إلى التحسينات التالية.
##### تحسين المخطط
* يقوم MySQL بتفريغ البيانات على القرص في كتل متجاورة للوصول السريع.
* استخدم `CHAR` بدلاً من `VARCHAR` للحقول ذات الطول الثابت.
* يتيح `CHAR` الوصول العشوائي السريع بشكل فعال، بينما مع `VARCHAR`، يجب عليك العثور على نهاية السلسلة قبل الانتقال إلى التالية.
* استخدم `TEXT` للكتل النصية الكبيرة مثل منشورات المدونة. يسمح `TEXT` أيضاً بعمليات البحث المنطقي. يؤدي استخدام حقل `TEXT` إلى تخزين مؤشر على القرص يُستخدم لتحديد موقع كتلة النص.
* استخدم `INT` للأرقام الكبيرة حتى 2^32 أو 4 مليار.
* استخدم `DECIMAL` للعملات لتجنب أخطاء تمثيل الفاصلة العائمة.
* تجنب تخزين `BLOBS` الكبيرة، وقم بتخزين موقع الحصول على الكائن بدلاً من ذلك.
* `VARCHAR(255)` هو أكبر عدد من الأحرف التي يمكن عدها في رقم 8 بت، مما يؤدي غالباً إلى تعظيم استخدام البايت في بعض أنظمة RDBMS.
* قم بتعيين قيد `NOT NULL` حيثما أمكن [لتحسين أداء البحث](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search).
##### استخدام الفهارس الجيدة
* الأعمدة التي تقوم بالاستعلام عنها (`SELECT`, `GROUP BY`, `ORDER BY`, `JOIN`) يمكن أن تكون أسرع باستخدام الفهارس.
* عادةً ما يتم تمثيل الفهارس كشجرة [B-tree](https://en.wikipedia.org/wiki/B-tree) ذاتية التوازن تحافظ على ترتيب البيانات وتسمح بعمليات البحث والوصول التسلسلي والإدراج والحذف في وقت لوغاريتمي.
* وضع فهرس يمكن أن يحتفظ بالبيانات في الذاكرة، مما يتطلب مساحة أكبر.
* يمكن أن تكون عمليات الكتابة أبطأ أيضاً لأن الفهرس يحتاج إلى التحديث.
* عند تحميل كميات كبيرة من البيانات، قد يكون من الأسرع تعطيل الفهارس، وتحميل البيانات، ثم إعادة بناء الفهارس.
##### تجنب عمليات الربط المكلفة
* قم بـ [إلغاء التطبيع](#denormalization) حيث تتطلب متطلبات الأداء ذلك.
##### تجزئة الجداول
* قم بتقسيم الجدول عن طريق وضع النقاط الساخنة في جدول منفصل للمساعدة في إبقائها في الذاكرة.
##### تحسين ذاكرة التخزين المؤقت للاستعلامات
* في بعض الحالات، قد تؤدي [ذاكرة التخزين المؤقت للاستعلامات](https://dev.mysql.com/doc/refman/5.7/en/query-cache.html) إلى [مشاكل في الأداء](https://www.percona.com/blog/2016/10/12/mysql-5-7-performance-tuning-immediately-after-installation/).
##### المصادر وقراءات إضافية: تحسين SQL
* [نصائح لتحسين استعلامات MySQL](http://aiddroid.com/10-tips-optimizing-mysql-queries-dont-suck/)
* [هل هناك سبب وجيه لرؤية VARCHAR(255) مستخدمة بكثرة؟](http://stackoverflow.com/questions/1217466/is-there-a-good-reason-i-see-varchar255-used-so-often-as-opposed-to-another-l)
* [كيف تؤثر القيم الفارغة على الأداء؟](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)
* [سجل الاستعلامات البطيئة](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)
### NoSQL
NoSQL هي مجموعة من عناصر البيانات ممثلة في **مخزن المفتاح-القيمة**، **مخزن المستندات**، **مخزن الأعمدة العريضة**، أو **قاعدة بيانات الرسوم البيانية**. البيانات غير مطبعة، وعمليات الربط تتم عموماً في كود التطبيق. معظم مخازن NoSQL تفتقر إلى معاملات ACID الحقيقية وتفضل [الاتساق النهائي](#eventual-consistency).
غالباً ما يستخدم **BASE** لوصف خصائص قواعد بيانات NoSQL. بالمقارنة مع [نظرية CAP](#cap-theorem)، يختار BASE التوافر على حساب الاتساق.
* **متوفر أساساً** - يضمن النظام التوافر.
* **حالة مرنة** - قد تتغير حالة النظام مع مرور الوقت، حتى بدون مدخلات.
* **اتساق نهائي** - سيصبح النظام متسقاً خلال فترة من الزمن، بشرط عدم تلقي النظام مدخلات خلال تلك الفترة.
بالإضافة إلى الاختيار بين [SQL أو NoSQL](#sql-or-nosql)، من المفيد فهم أي نوع من قواعد بيانات NoSQL يناسب حالة (حالات) الاستخدام الخاصة بك بشكل أفضل. سنراجع **مخازن المفتاح-القيمة**، **مخازن المستندات**، **مخازن الأعمدة العريضة**، و**قواعد بيانات الرسوم البيانية** في القسم التالي.
#### مخزن المفتاح-القيمة
> التجريد: جدول التجزئة
مخزن المفتاح-القيمة يسمح عموماً بعمليات قراءة وكتابة بتعقيد O(1) وغالباً ما يكون مدعوماً بالذاكرة أو SSD. يمكن لمخازن البيانات الحفاظ على المفاتيح في [ترتيب معجمي](https://en.wikipedia.org/wiki/Lexicographical_order)، مما يسمح باسترجاع نطاقات المفاتيح بكفاءة. مخازن المفتاح-القيمة يمكن أن تسمح بتخزين البيانات الوصفية مع القيمة.
توفر مخازن المفتاح-القيمة أداءً عالياً وغالباً ما تستخدم لنماذج البيانات البسيطة أو للبيانات سريعة التغير، مثل طبقة التخزين المؤقت في الذاكرة. نظراً لأنها تقدم مجموعة محدودة من العمليات، يتم نقل التعقيد إلى طبقة التطبيق إذا كانت هناك حاجة لعمليات إضافية.
مخزن المفتاح-القيمة هو الأساس لأنظمة أكثر تعقيداً مثل مخزن المستندات، وفي بعض الحالات، قاعدة بيانات الرسوم البيانية.
##### المصادر وقراءات إضافية: مخزن المفتاح-القيمة
* [قاعدة بيانات المفتاح-القيمة](https://en.wikipedia.org/wiki/Key-value_database)
* [عيوب مخازن المفتاح-القيمة](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
* [بنية Redis](http://qnimate.com/overview-of-redis-architecture/)
* [بنية Memcached](https://adayinthelifeof.nl/2011/02/06/memcache-internals/)
#### مخزن المستندات
> التجريد: مخزن مفتاح-قيمة مع تخزين المستندات كقيم
يتمحور مخزن المستندات حول المستندات (XML، JSON، ثنائي، إلخ)، حيث يخزن المستند جميع المعلومات لكائن معين. توفر مخازن المستندات واجهات برمجة التطبيقات (APIs) أو لغة استعلام للبحث بناءً على البنية الداخلية للمستند نفسه. *ملاحظة: العديد من مخازن المفتاح-القيمة تتضمن ميزات للعمل مع البيانات الوصفية للقيمة، مما يجعل الحدود غير واضحة بين هذين النوعين من التخزين.*
بناءً على التنفيذ الأساسي، يتم تنظيم المستندات حسب المجموعات، العلامات، البيانات الوصفية، أو المجلدات. على الرغم من أنه يمكن تنظيم المستندات أو تجميعها معاً، قد تحتوي المستندات على حقول مختلفة تماماً عن بعضها البعض.
بعض مخازن المستندات مثل [MongoDB](https://www.mongodb.com/mongodb-architecture) و[CouchDB](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/) توفر أيضاً لغة شبيهة بـ SQL لتنفيذ استعلامات معقدة. [DynamoDB](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) يدعم كلاً من المفتاح-القيمة والمستندات.
توفر مخازن المستندات مرونة عالية وغالباً ما تستخدم للعمل مع البيانات التي تتغير بشكل متقطع.
##### المصادر وقراءات إضافية: مخزن المستندات
* [قاعدة البيانات الموجهة للمستندات](https://en.wikipedia.org/wiki/Document-oriented_database)
* [بنية MongoDB](https://www.mongodb.com/mongodb-architecture)
* [بنية CouchDB](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/)
* [بنية Elasticsearch](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)
#### مخزن الأعمدة العريضة
<p align="center">
<img src="images/n16iOGk.png">
<br/>
<i><a href=http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html>المصدر: SQL & NoSQL، تاريخ موجز</a></i>
</p>
> التجريد: خريطة متداخلة `ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>`
الوحدة الأساسية للبيانات في مخزن الأعمدة العريضة هي العمود (زوج اسم/قيمة). يمكن تجميع العمود في عائلات الأعمدة (مماثلة لجدول SQL). عائلات الأعمدة الفائقة تجمع عائلات الأعمدة بشكل أكبر. يمكنك الوصول إلى كل عمود بشكل مستقل باستخدام مفتاح الصف، والأعمدة ذات نفس مفتاح الصف تشكل صفاً. تحتوي كل قيمة على طابع زمني للإصدار وحل التعارضات.
قدمت Google [Bigtable](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) كأول مخزن للأعمدة العريضة، والذي أثر على [HBase](https://www.edureka.co/blog/hbase-architecture/) مفتوح المصدر المستخدم غالباً في نظام Hadoop، و[Cassandra](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html) من Facebook. تحتفظ المخازن مثل BigTable وHBase وCassandra بالمفاتيح في ترتيب معجمي، مما يسمح باسترجاع نطاقات المفاتيح المحددة بكفاءة.
توفر مخازن الأعمدة العريضة توافر عالٍ وقابلية توسع عالية. غالباً ما تستخدم لمجموعات البيانات الكبيرة جداً.
##### المصادر وقراءات إضافية: مخزن الأعمدة العريضة
* [SQL و NoSQL، تاريخ موجز](http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html)
* [بنية Bigtable](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)
* [بنية HBase](https://www.edureka.co/blog/hbase-architecture/)
* [بنية Cassandra](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html)
#### قاعدة بيانات الرسوم البيانية
<p align="center">
<img src="images/fNcl65g.png">
<br/>
<i><a href=https://en.wikipedia.org/wiki/File:GraphDatabase_PropertyGraph.png>المصدر: قاعدة بيانات الرسوم البيانية</a></i>
</p>
> التجريد: رسم بياني
في قاعدة بيانات الرسوم البيانية، كل عقدة هي سجل وكل قوس هو علاقة بين عقدتين. قواعد بيانات الرسوم البيانية مُحسّنة لتمثيل العلاقات المعقدة مع العديد من المفاتيح الخارجية أو علاقات متعددة-إلى-متعددة.
توفر قواعد بيانات الرسوم البيانية أداءً عالياً لنماذج البيانات ذات العلاقات المعقدة، مثل الشبكات الاجتماعية. وهي حديثة نسبياً ولم تنتشر بعد على نطاق واسع؛ قد يكون من الصعب العثور على أدوات وموارد تطوير. العديد من الرسوم البيانية لا يمكن الوصول إليها إلا من خلال [REST APIs](#representational-state-transfer-rest).
##### المصادر وقراءات إضافية: الرسوم البيانية
* [قاعدة بيانات الرسوم البيانية](https://en.wikipedia.org/wiki/Graph_database)
* [Neo4j](https://neo4j.com/)
* [FlockDB](https://blog.twitter.com/2010/introducing-flockdb)
#### المصادر وقراءات إضافية: NoSQL
* [شرح المصطلحات الأساسية](http://stackoverflow.com/questions/3342497/explanation-of-base-terminology)
* [قواعد بيانات NoSQL: مسح وتوجيه القرار](https://medium.com/baqend-blog/nosql-databases-a-survey-and-decision-guidance-ea7823a822d#.wskogqenq)
* [قابلية التوسع](http://www.lecloud.net/post/7994751381/scalability-for-dummies-part-2-database)
* [مقدمة إلى NoSQL](https://www.youtube.com/watch?v=qI_g07C_Q5I)
* [أنماط NoSQL](http://horicky.blogspot.com/2009/11/nosql-patterns.html)
### SQL أم NoSQL
<p align="center">
<img src="images/wXGqG5f.png">
<br/>
<i><a href=https://www.infoq.com/articles/Transition-RDBMS-NoSQL/>المصدر: الانتقال من RDBMS إلى NoSQL</a></i>
</p>
أسباب اختيار **SQL**:
* البيانات المنظمة
* المخطط الصارم
* البيانات العلائقية
* الحاجة إلى عمليات ربط معقدة
* المعاملات
* أنماط واضحة للتوسع
* أكثر نضجاً: المطورون، المجتمع، الكود، الأدوات، إلخ
* عمليات البحث باستخدام الفهرس سريعة جداً
أسباب اختيار **NoSQL**:
* البيانات شبه المنظمة
* المخطط الديناميكي أو المرن
* البيانات غير العلائقية
* لا حاجة لعمليات ربط معقدة
* تخزين العديد من التيرابايت (أو البيتابايت) من البيانات
* حمل كثيف جداً للبيانات
* معدل إنتاجية عالٍ جداً للعمليات في الثانية
أمثلة على البيانات المناسبة لـ NoSQL:
* الاستيعاب السريع لبيانات تدفق النقرات والسجلات
* بيانات لوحة المتصدرين أو النقاط
* البيانات المؤقتة، مثل سلة التسوق
* الجداول التي يتم الوصول إليها بشكل متكرر ('الساخنة')
* جداول البيانات الوصفية/البحث
##### المصادر وقراءات إضافية: SQL أم NoSQL
* [التوسع حتى أول 10 ملايين مستخدم](https://www.youtube.com/watch?v=kKjm4ehYiMs)
* [الفروق بين SQL و NoSQL](https://www.sitepoint.com/sql-vs-nosql-differences/)
## التخزين المؤقت
<p align="center">
<img src="images/Q6z24La.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>المصدر: أنماط تصميم النظام القابل للتوسع</a></i>
</p>
يحسن التخزين المؤقت أوقات تحميل الصفحات ويمكن أن يقلل الحمل على خوادمك وقواعد البيانات. في هذا النموذج، سيقوم الموزع أولاً بالبحث عما إذا كان الطلب قد تم من قبل ومحاولة العثور على النتيجة السابقة لإرجاعها، لتوفير التنفيذ الفعلي.
غالباً ما تستفيد قواعد البيانات من التوزيع المتساوي للقراءات والكتابات عبر أقسامها. العناصر الشائعة يمكن أن تؤدي إلى انحراف التوزيع، مما يسبب اختناقات. وضع ذاكرة تخزين مؤقت أمام قاعدة البيانات يمكن أن يساعد في امتصاص الأحمال غير المتساوية وارتفاعات حركة المرور.
### التخزين المؤقت على جانب العميل
يمكن أن يتواجد التخزين المؤقت على جانب العميل (نظام التشغيل أو المتصفح)، [جانب الخادم](#reverse-proxy-web-server)، أو في طبقة تخزين مؤقت منفصلة.
### التخزين المؤقت CDN
تعتبر [CDNs](#content-delivery-network) نوعاً من التخزين المؤقت.
### التخزين المؤقت لخادم الويب
يمكن [للوكلاء العكسيين](#reverse-proxy-web-server) والتخزين المؤقت مثل [Varnish](https://www.varnish-cache.org/) تقديم المحتوى الثابت والديناميكي مباشرة. يمكن لخوادم الويب أيضاً تخزين الطلبات مؤقتاً، وإرجاع الردود دون الحاجة للاتصال بخوادم التطبيقات.
### التخزين المؤقت لقاعدة البيانات
عادةً ما تتضمن قاعدة البياناتك مستوى معين من التخزين المؤقت في التكوين الافتراضي، مُحسّن لحالة استخدام عامة. تعديل هذه الإعدادات لأنماط استخدام محددة يمكن أن يعزز الأداء بشكل أكبر.
### التخزين المؤقت للتطبيق
تعتبر أنظمة التخزين المؤقت في الذاكرة مثل Memcached و Redis بمثابة مخازن للقيم المفتاحية بين تطبيقك وتخزين البيانات. نظراً لأن البيانات محفوظة في ذاكرة الوصول العشوائي (RAM)، فهي أسرع بكثير من قواعد البيانات النموذجية حيث يتم تخزين البيانات على القرص. الذاكرة العشوائية محدودة مقارنة بالقرص، لذا يمكن لخوارزميات إبطال التخزين المؤقت [cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms) مثل [least recently used (LRU)](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) المساعدة في إبطال الإدخالات "الباردة" والحفاظ على البيانات "الساخنة" في الذاكرة العشوائية.
يتميز Redis بالمزايا الإضافية التالية:
* خيار الاستمرارية
* هياكل بيانات مدمجة مثل المجموعات المرتبة والقوائم
هناك مستويات متعددة يمكنك تخزينها مؤقتاً تندرج تحت فئتين عامتين: **استعلامات قاعدة البيانات** و **الكائنات**:
* مستوى الصف
* مستوى الاستعلام
* كائنات قابلة للتسلسل مكتملة التكوين
* HTML مكتمل التقديم
بشكل عام، يجب أن تحاول تجنب التخزين المؤقت القائم على الملفات، لأنه يجعل الاستنساخ والتوسع التلقائي أكثر صعوبة.
### التخزين المؤقت على مستوى استعلام قاعدة البيانات
عندما تستعلم من قاعدة البيانات، قم بتجزئة الاستعلام كمفتاح وتخزين النتيجة في ذاكرة التخزين المؤقت. يعاني هذا النهج من مشاكل انتهاء الصلاحية:
* صعوبة حذف نتيجة مخزنة مؤقتاً مع الاستعلامات المعقدة
* إذا تغير جزء واحد من البيانات مثل خلية جدول، فأنت بحاجة إلى حذف جميع الاستعلامات المخزنة مؤقتاً التي قد تتضمن الخلية المتغيرة
### التخزين المؤقت على مستوى الكائن
انظر إلى بياناتك ككائن، مشابه لما تفعله مع كود تطبيقك. اجعل تطبيقك يجمع مجموعة البيانات من قاعدة البيانات في نسخة من الفئة أو هيكل (هياكل) البيانات:
* إزالة الكائن من التخزين المؤقت إذا تغيرت بياناته الأساسية
* يسمح بالمعالجة غير المتزامنة: العمال يجمعون الكائنات باستهلاك أحدث كائن مخزن مؤقتاً
اقتراحات لما يمكن تخزينه مؤقتاً:
* جلسات المستخدم
* صفحات الويب المقدمة بالكامل
* تدفقات النشاط
* بيانات الرسم البياني للمستخدم
### متى يتم تحديث التخزين المؤقت
نظراً لأنه يمكنك تخزين كمية محدودة فقط من البيانات في التخزين المؤقت، ستحتاج إلى تحديد استراتيجية تحديث التخزين المؤقت التي تعمل بشكل أفضل لحالة الاستخدام الخاصة بك.
#### التخزين المؤقت الجانبي (Cache-aside)
<p align="center">
<img src="images/ONjORqk.png">
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>المصدر: من التخزين المؤقت إلى شبكة بيانات في الذاكرة</a></i>
</p>
التطبيق مسؤول عن القراءة والكتابة من التخزين. لا يتفاعل التخزين المؤقت مع التخزين مباشرة. يقوم التطبيق بما يلي:
* البحث عن الإدخال في التخزين المؤقت، مما يؤدي إلى فشل في العثور عليه
* تحميل الإدخال من قاعدة البيانات
* إضافة الإدخال إلى التخزين المؤقت
* إرجاع الإدخال
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
يتم استخدام [Memcached](https://memcached.org/) بشكل عام بهذه الطريقة.
عمليات القراءة اللاحقة للبيانات المضافة إلى التخزين المؤقت تكون سريعة. يشار إلى التخزين المؤقت الجانبي أيضاً باسم التحميل الكسول (lazy loading). يتم تخزين البيانات المطلوبة فقط مؤقتاً، مما يتجنب ملء ذاكرة التخزين المؤقت ببيانات غير مطلوبة.
##### عيوب التخزين المؤقت الجانبي
* كل فشل في العثور على البيانات في التخزين المؤقت يؤدي إلى ثلاث رحلات، مما قد يسبب تأخيراً ملحوظاً.
* قد تصبح البيانات قديمة إذا تم تحديثها في قاعدة البيانات. يمكن تخفيف هذه المشكلة عن طريق تعيين وقت انتهاء الصلاحية (TTL) الذي يفرض تحديث إدخال التخزين المؤقت، أو باستخدام الكتابة المباشرة (write-through).
* عند فشل العقدة، يتم استبدالها بعقدة جديدة فارغة، مما يزيد زمن الاستجابة.
#### الكتابة المباشرة (Write-through)
<p align="center">
<img src="images/0vBc0hN.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>المصدر: أنماط قابلية التوسع والتوافر والاستقرار</a></i>
</p>
يستخدم التطبيق التخزين المؤقت كمخزن البيانات الرئيسي، حيث يقرأ ويكتب البيانات إليه، بينما يكون التخزين المؤقت مسؤولاً عن القراءة والكتابة في قاعدة البيانات:
* يضيف/يحدث التطبيق الإدخال في التخزين المؤقت
* يكتب التخزين المؤقت الإدخال بشكل متزامن في مخزن البيانات
* العودة
كود التطبيق:
```python
set_user(12345, {"foo":"bar"})
```
كود التخزين المؤقت:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
تعتبر الكتابة المباشرة عملية بطيئة بشكل عام بسبب عملية الكتابة، لكن عمليات القراءة اللاحقة للبيانات المكتوبة حديثاً تكون سريعة. يميل المستخدمون عموماً إلى تحمل التأخير عند تحديث البيانات أكثر من تحملهم له عند قراءتها. البيانات في التخزين المؤقت لا تكون قديمة.
##### عيوب الكتابة المباشرة
* عند إنشاء عقدة جديدة بسبب الفشل أو التوسع، لن تقوم العقدة الجديدة بتخزين الإدخالات مؤقتاً حتى يتم تحديث الإدخال في قاعدة البيانات. يمكن تخفيف هذه المشكلة باستخدام التخزين المؤقت الجانبي مع الكتابة المباشرة.
* معظم البيانات المكتوبة قد لا تتم قراءتها أبداً، ويمكن تقليل هذا باستخدام وقت انتهاء الصلاحية (TTL).
#### الكتابة المؤجلة (write-back)
<p align="center">
<img src="images/rgSrvjG.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>المصدر: أنماط قابلية التوسع والتوافر والاستقرار</a></i>
</p>
في الكتابة المؤجلة، يقوم التطبيق بما يلي:
* إضافة/تحديث الإدخال في التخزين المؤقت
* كتابة الإدخال بشكل غير متزامن في مخزن البيانات، مما يحسن أداء الكتابة
##### عيوب الكتابة المؤجلة
* قد يحدث فقدان للبيانات إذا تعطل التخزين المؤقت قبل وصول محتوياته إلى مخزن البيانات.
* تنفيذ الكتابة المؤجلة أكثر تعقيداً من تنفيذ التخزين المؤقت الجانبي أو الكتابة المباشرة.
#### التحديث المسبق (Refresh-ahead)
<p align="center">
<img src="images/kxtjqgE.png">
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>المصدر: من التخزين المؤقت إلى شبكة البيانات في الذاكرة</a></i>
</p>
يمكنك تكوين التخزين المؤقت لتحديث أي إدخال تم الوصول إليه مؤخراً تلقائياً قبل انتهاء صلاحيته.
يمكن أن يؤدي التحديث المسبق إلى تقليل زمن الاستجابة مقارنة بالقراءة المباشرة إذا كان التخزين المؤقت قادراً على التنبؤ بدقة بالعناصر التي من المحتمل أن تكون مطلوبة في المستقبل.
##### عيوب التحديث المسبق
* عدم التنبؤ بدقة بالعناصر التي من المحتمل أن تكون مطلوبة في المستقبل قد يؤدي إلى انخفاض الأداء مقارنة بعدم استخدام التحديث المسبق.
### عيوب التخزين المؤقت
* الحاجة إلى الحفاظ على التناسق بين التخزين المؤقت ومصدر الحقيقة مثل قاعدة البيانات من خلال [إبطال التخزين المؤقت](https://en.wikipedia.org/wiki/Cache_algorithms).
* إبطال التخزين المؤقت مشكلة صعبة، وهناك تعقيد إضافي مرتبط بتوقيت تحديث التخزين المؤقت.
* الحاجة إلى إجراء تغييرات في التطبيق مثل إضافة Redis أو memcached.
### المصادر وقراءات إضافية
* [من التخزين المؤقت إلى شبكة البيانات في الذاكرة](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
* [أنماط تصميم النظم القابلة للتوسع](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
* [مقدمة في تصميم الأنظمة للتوسع](http://lethain.com/introduction-to-architecting-systems-for-scale/)
* [أنماط قابلية التوسع والتوافر والاستقرار](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [قابلية التوسع](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
* [استراتيجيات AWS ElastiCache](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
* [ويكيبيديا](https://en.wikipedia.org/wiki/Cache_(computing))
## اللاتزامن (Asynchronism)
<p align="center">
<img src="images/54GYsSx.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>المصدر: مقدمة في تصميم الأنظمة للتوسع</a></i>
</p>
تساعد سير العمل اللاتزامنية في تقليل أوقات الطلب للعمليات المكلفة التي قد تتم بشكل مباشر. كما يمكن أن تساعد في تنفيذ العمل المستهلك للوقت مسبقاً، مثل التجميع الدوري للبيانات.
### قوائم الرسائل
تستقبل قوائم الرسائل وتحتفظ وتسلم الرسائل. إذا كانت العملية بطيئة جداً للتنفيذ المباشر، يمكنك استخدام قائمة رسائل مع سير العمل التالي:
* ينشر التطبيق مهمة في القائمة، ثم يخطر المستخدم بحالة المهمة
* يلتقط العامل المهمة من القائمة، يعالجها، ثم يشير إلى اكتمال المهمة
لا يتم حظر المستخدم ويتم معالجة المهمة في الخلفية. خلال هذا الوقت، قد يقوم العميل اختيارياً بمعالجة صغيرة لجعل المهمة تبدو وكأنها اكتملت. على سبيل المثال، عند نشر تغريدة، يمكن نشر التغريدة فوراً في جدولك الزمني، لكن قد يستغرق الأمر بعض الوقت قبل أن يتم تسليم تغريدتك فعلياً لجميع متابعيك.
يعد **[Redis](https://redis.io/)** مفيداً كوسيط رسائل بسيط ولكن يمكن فقدان الرسائل.
**[RabbitMQ](https://www.rabbitmq.com/)** شائع ولكنه يتطلب منك التكيف مع بروتوكول 'AMQP' وإدارة العقد الخاصة بك.
**[Amazon SQS](https://aws.amazon.com/sqs/)** مستضاف ولكن يمكن أن يكون له زمن استجابة عالٍ مع احتمال تسليم الرسائل مرتين.
### قوائم المهام
تستقبل قوائم المهام المهام وبياناتها المرتبطة، تنفذها، ثم تسلم نتائجها. يمكنها دعم الجدولة ويمكن استخدامها لتشغيل المهام كثيفة الحساب في الخلفية.
**[Celery](https://docs.celeryproject.org/en/stable/)** يدعم الجدولة وبشكل أساسي لديه دعم لـ Python.
### الضغط العكسي
إذا بدأت القوائم في النمو بشكل كبير، يمكن أن يصبح حجم القائمة أكبر من الذاكرة، مما يؤدي إلى فشل في التخزين المؤقت، وقراءات القرص، وحتى أداء أبطأ. يمكن أن يساعد [الضغط العكسي](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html) من خلال تحديد حجم القائمة، وبالتالي الحفاظ على معدل إنتاجية عالٍ وأوقات استجابة جيدة للمهام الموجودة بالفعل في القائمة. بمجرد امتلاء القائمة، يحصل العملاء على رمز حالة مشغول أو HTTP 503 للمحاولة لاحقاً. يمكن للعملاء إعادة المحاولة في وقت لاحق، ربما مع [التراجع الأسي](https://en.wikipedia.org/wiki/Exponential_backoff).
### عيوب اللاتزامن
* حالات الاستخدام مثل العمليات الحسابية غير المكلفة وسير العمل في الوقت الفعلي قد تكون أكثر ملاءمة للعمليات المتزامنة، حيث أن إدخال القوائم يمكن أن يضيف تأخيرات وتعقيدات.
### المصادر وقراءات إضافية
* [إنها كلها لعبة أرقام](https://www.youtube.com/watch?v=1KRYH75wgy4)
* [تطبيق الضغط العكسي عند التحميل الزائد](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
* [قانون ليتل](https://en.wikipedia.org/wiki/Little%27s_law)
* [ما هو الفرق بين قائمة الرسائل وقائمة المهام؟](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)
## الاتصال
<p align="center">
<img src="images/5KeocQs.jpg">
<br/>
<i><a href=http://www.escotal.com/osilayer.html>المصدر: نموذج OSI ذو الطبقات السبع</a></i>
</p>
### بروتوكول نقل النص التشعبي (HTTP)
HTTP هو طريقة لترميز ونقل البيانات بين العميل والخادم. إنه بروتوكول طلب/استجابة: يصدر العملاء طلبات ويصدر الخوادم استجابات مع المحتوى ذي الصلة ومعلومات حالة الإكمال حول الطلب. HTTP مستقل بذاته، مما يسمح للطلبات والاستجابات بالتدفق عبر العديد من أجهزة التوجيه والخوادم الوسيطة التي تقوم بموازنة التحميل والتخزين المؤقت والتشفير والضغط.
يتكون طلب HTTP الأساسي من فعل (طريقة) ومورد (نقطة نهاية). فيما يلي أفعال HTTP الشائعة:
| الفعل | الوصف | متكافئ* | آمن | قابل للتخزين المؤقت |
|---|---|---|---|---|
| GET | يقرأ مورداً | نعم | نعم | نعم |
| POST | ينشئ مورداً أو يطلق عملية تتعامل مع البيانات | لا | لا | نعم إذا كانت الاستجابة تحتوي على معلومات الحداثة |
| PUT | ينشئ أو يستبدل مورداً | نعم | لا | لا |
| PATCH | يحدث مورداً جزئياً | لا | لا | نعم إذا كانت الاستجابة تحتوي على معلومات الحداثة |
| DELETE | يحذف مورداً | نعم | لا | لا |
*يمكن استدعاؤه عدة مرات دون نتائج مختلفة.
HTTP هو بروتوكول طبقة التطبيق يعتمد على بروتوكولات المستوى الأدنى مثل **TCP** و **UDP**.
#### المصادر وقراءات إضافية: HTTP
* [ما هو HTTP؟](https://www.nginx.com/resources/glossary/http/)
* [الفرق بين بروتوكول HTTP وبروتوكول TCP](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)
* [الفرق بين PUT و PATCH](https://laracasts.com/discuss/channels/general-discussion/whats-the-differences-between-put-and-patch?page=1)
### بروتوكول التحكم بالإرسال (TCP)
<p align="center">
<img src="images/JdAsdvG.jpg">
<br/>
<i><a href=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>المصدر: كيفية صنع لعبة متعددة اللاعبين</a></i>
</p>
TCP هو بروتوكول موجه للاتصال عبر [شبكة IP](https://en.wikipedia.org/wiki/Internet_Protocol). يتم إنشاء الاتصال وإنهاؤه باستخدام [المصافحة](https://en.wikipedia.org/wiki/Handshaking). جميع الحزم المرسلة مضمونة الوصول إلى الوجهة بالترتيب الأصلي وبدون تلف من خلال:
* أرقام التسلسل و[حقول المجموع الاختباري](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation) لكل حزمة
* حزم [التأكيد](https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)) وإعادة الإرسال التلقائي
إذا لم يتلق المرسل استجابة صحيحة، سيقوم بإعادة إرسال الحزم. في حالة حدوث مهلات متعددة، يتم إسقاط الاتصال. كما ينفذ TCP [التحكم بالتدفق](https://en.wikipedia.org/wiki/Flow_control_(data)) و[التحكم بالازدحام](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control). تتسبب هذه الضمانات في تأخيرات وتؤدي عموماً إلى نقل أقل كفاءة من UDP.
لضمان إنتاجية عالية، يمكن لخوادم الويب الاحتفاظ بعدد كبير من اتصالات TCP مفتوحة، مما يؤدي إلى استخدام ذاكرة عالٍ. قد يكون من المكلف وجود عدد كبير من الاتصالات المفتوحة بين مؤشرات خادم الويب وخادم [memcached](https://memcached.org/). يمكن أن يساعد [تجميع الاتصالات](https://en.wikipedia.org/wiki/Connection_pool) بالإضافة إلى التحول إلى UDP حيثما أمكن.
TCP مفيد للتطبيقات التي تتطلب موثوقية عالية ولكنها أقل حساسية للوقت. تشمل بعض الأمثلة خوادم الويب، ومعلومات قواعد البيانات، وSMTP، وFTP، وSSH.
استخدم TCP بدلاً من UDP عندما:
* تحتاج إلى وصول جميع البيانات سليمة
* تريد تقديراً تلقائياً لأفضل استخدام لسعة الشبكة
### بروتوكول حزم المستخدم (UDP)
<p align="center">
<img src="images/yzDrJtA.jpg">
<br/>
<i><a href=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>المصدر: كيفية صنع لعبة متعددة اللاعبين</a></i>
</p>
UDP لا يعتمد على الاتصال. وحدات البيانات (المماثلة للحزم) مضمونة فقط على مستوى وحدة البيانات. قد تصل وحدات البيانات إلى وجهتها خارج الترتيب أو لا تصل على الإطلاق. لا يدعم UDP التحكم بالازدحام. بدون الضمانات التي يدعمها TCP، يكون UDP عموماً أكثر كفاءة.
يمكن لـ UDP البث، وإرسال وحدات البيانات إلى جميع الأجهزة في الشبكة الفرعية. هذا مفيد مع [DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) لأن العميل لم يتلق بعد عنوان IP، مما يمنع طريقة لـ TCP للتدفق بدون عنوان IP.
UDP أقل موثوقية ولكنه يعمل بشكل جيد في حالات الاستخدام في الوقت الفعلي مثل VoIP، ودردشة الفيديو، والبث المباشر، والألعاب متعددة اللاعبين في الوقت الفعلي.
استخدم UDP بدلاً من TCP عندما:
* تحتاج إلى أقل زمن وصول
* البيانات المتأخرة أسوأ من فقدان البيانات
* تريد تنفيذ تصحيح الأخطاء الخاص بك
#### المصادر وقراءات إضافية: TCP و UDP
* [البرمجة الشبكية لمبرمجي الألعاب](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)
* [الاختلافات الرئيسية بين بروتوكولي TCP و UDP](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)
* [الفرق بين TCP و UDP](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
* [بروتوكول التحكم بالإرسال](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)
* [بروتوكول حزم المستخدم](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [تحجيم memcache في Facebook](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)
### استدعاء الإجراء عن بعد (RPC)
<p align="center">
<img src="images/iF4Mkb5.png">
<br/>
<i><a href=http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview>المصدر: حل مقابلة تصميم النظام</a></i>
</p>
في RPC، يتسبب العميل في تنفيذ إجراء في مساحة عنوان مختلفة، عادةً على خادم بعيد. تتم برمجة الإجراء كما لو كان استدعاء إجراء محلي، مع تجريد تفاصيل كيفية التواصل مع الخادم من برنامج العميل. المكالمات البعيدة عادةً أبطأ وأقل موثوقية من المكالمات المحلية لذلك من المفيد التمييز بين مكالمات RPC والمكالمات المحلية. تشمل أطر عمل RPC الشائعة [Protobuf](https://developers.google.com/protocol-buffers/) و[Thrift](https://thrift.apache.org/) و[Avro](https://avro.apache.org/docs/current/).
RPC هو بروتوكول طلب-استجابة:
* **برنامج العميل (Client program)** - يستدعي إجراء stub العميل. يتم دفع المعاملات إلى المكدس كما في استدعاء الإجراء المحلي.
* **إجراء stub العميل (Client stub procedure)** - يقوم بتنظيم (تعبئة) معرف الإجراء والوسائط في رسالة طلب.
* **وحدة اتصال العميل (Client communication module)** - يقوم نظام التشغيل بإرسال الرسالة من العميل إلى الخادم.
* **وحدة اتصال الخادم (Server communication module)** - يمرر نظام التشغيل الحزم الواردة إلى إجراء stub الخادم.
* **إجراء stub الخادم (Server stub procedure)** - يفك تنظيم النتائج، ويستدعي إجراء الخادم المطابق لمعرف الإجراء ويمرر الوسائط المعطاة.
* استجابة الخادم تكرر الخطوات أعلاه بترتيب عكسي.
أمثلة على استدعاءات RPC:
```
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
```
يركز RPC على كشف السلوكيات. غالباً ما يتم استخدام RPCs لأسباب تتعلق بالأداء مع الاتصالات الداخلية، حيث يمكنك صياغة الاستدعاءات الأصلية يدوياً لتناسب حالات الاستخدام الخاصة بك بشكل أفضل.
اختر مكتبة أصلية (المعروفة أيضاً باسم SDK) عندما:
* تعرف منصتك المستهدفة.
* تريد التحكم في كيفية الوصول إلى "المنطق" الخاص بك.
* تريد التحكم في كيفية حدوث التحكم في الأخطاء خارج مكتبتك.
* يكون الأداء وتجربة المستخدم النهائي هو اهتمامك الرئيسي.
تميل واجهات برمجة التطبيقات HTTP التي تتبع **REST** إلى استخدامها بشكل أكثر تكراراً للواجهات العامة.
#### عيوب RPC
* عملاء RPC يصبحون مرتبطين بشكل وثيق بتنفيذ الخدمة.
* يجب تحديد واجهة برمجة تطبيقات جديدة لكل عملية أو حالة استخدام جديدة.
* يمكن أن يكون تصحيح أخطاء RPC صعباً.
* قد لا تتمكن من الاستفادة من التقنيات الموجودة مباشرةً. على سبيل المثال، قد يتطلب الأمر جهداً إضافياً لضمان [تخزين استدعاءات RPC بشكل صحيح في ذاكرة التخزين المؤقت](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/) على خوادم التخزين المؤقت مثل [Squid](http://www.squid-cache.org/).
### نقل الحالة التمثيلي (REST)
REST هو نمط معماري يفرض نموذج العميل/الخادم حيث يعمل العميل على مجموعة من الموارد التي يديرها الخادم. يوفر الخادم تمثيلاً للموارد والإجراءات التي يمكن إما معالجتها أو الحصول على تمثيل جديد للموارد. يجب أن تكون جميع الاتصالات خالية من الحالة وقابلة للتخزين المؤقت.
هناك أربع خصائص لواجهة RESTful:
* **تحديد الموارد (URI في HTTP)** - استخدم نفس URI بغض النظر عن أي عملية.
* **التغيير مع التمثيلات (الأفعال في HTTP)** - استخدم الأفعال والترويسات والنص.
* **رسالة خطأ ذاتية الوصف (استجابة الحالة في HTTP)** - استخدم رموز الحالة، لا تعد اختراع العجلة.
* **[HATEOAS](http://restcookbook.com/Basics/hateoas/) (واجهة HTML لـ HTTP)** - يجب أن تكون خدمة الويب الخاصة بك قابلة للوصول بالكامل في المتصفح.
أمثلة على استدعاءات REST:
```
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
```
يركز REST على عرض البيانات. وهو يقلل من الترابط بين العميل/الخادم ويستخدم غالباً لواجهات برمجة التطبيقات HTTP العامة. يستخدم REST طريقة أكثر عمومية وموحدة لعرض الموارد من خلال URIs، و[التمثيل من خلال الترويسات](https://github.com/for-GET/know-your-http-well/blob/master/headers.md)، والإجراءات من خلال الأفعال مثل GET وPOST وPUT وDELETE وPATCH. كونه خالٍ من الحالة، فإن REST مثالي للتوسع الأفقي والتقسيم.
#### عيوب REST
* نظراً لتركيز REST على عرض البيانات، قد لا يكون مناسباً إذا لم تكن الموارد منظمة بشكل طبيعي أو يتم الوصول إليها في تسلسل هرمي بسيط. على سبيل المثال، إرجاع جميع السجلات المحدثة من الساعة الماضية التي تطابق مجموعة معينة من الأحداث لا يمكن التعبير عنها بسهولة كمسار. مع REST، من المحتمل أن يتم تنفيذها بمزيج من مسار URI ومعلمات الاستعلام، وربما نص الطلب.
* يعتمد REST عادةً على عدد قليل من الأفعال (GET وPOST وPUT وDELETE وPATCH) والتي قد لا تناسب حالة الاستخدام الخاصة بك في بعض الأحيان. على سبيل المثال، نقل المستندات منتهية الصلاحية إلى مجلد الأرشيف قد لا يتناسب بشكل واضح مع هذه الأفعال.
* يتطلب جلب الموارد المعقدة ذات التسلسلات الهرمية المتداخلة رحلات متعددة بين العميل والخادم لعرض واجهات فردية، مثل جلب محتوى مقال المدونة والتعليقات على ذلك المقال. بالنسبة للتطبيقات المحمولة التي تعمل في ظروف شبكة متغيرة، تعتبر هذه الرحلات المتعددة غير مرغوب فيها للغاية.
* مع مرور الوقت، قد تتم إضافة المزيد من الحقول إلى استجابة API وستتلقى العملاء القديمة جميع حقول البيانات الجديدة، حتى تلك التي لا تحتاجها، مما يؤدي إلى تضخم حجم البيانات المنقولة ويؤدي إلى زمن استجابة أطول.
### مقارنة استدعاءات RPC وREST
| العملية | RPC | REST |
|---|---|---|
| التسجيل | **POST** /signup | **POST** /persons |
| الاستقالة | **POST** /resign<br/>{<br/>"personid": "1234"<br/>} | **DELETE** /persons/1234 |
| قراءة شخص | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| قراءة قائمة عناصر شخص | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| إضافة عنصر إلى قائمة عناصر شخص | **POST** /addItemToUsersItemsList<br/>{<br/>"personid": "1234";<br/>"itemid": "456"<br/>} | **POST** /persons/1234/items<br/>{<br/>"itemid": "456"<br/>} |
| تحديث عنصر | **POST** /modifyItem<br/>{<br/>"itemid": "456";<br/>"key": "value"<br/>} | **PUT** /items/456<br/>{<br/>"key": "value"<br/>} |
| حذف عنصر | **POST** /removeItem<br/>{<br/>"itemid": "456"<br/>} | **DELETE** /items/456 |
<p align="center">
<i><a href=https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/>المصدر: هل تعرف حقاً لماذا تفضل REST على RPC</a></i>
</p>
#### المصادر وقراءات إضافية: REST وRPC
* [هل تعرف حقاً لماذا تفضل REST على RPC](https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/)
* [متى تكون مناهج RPC أكثر ملاءمة من REST؟](http://programmers.stackexchange.com/a/181186)
* [REST مقابل JSON-RPC](http://stackoverflow.com/questions/15056878/rest-vs-json-rpc)
* [دحض خرافات RPC وREST](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)
* [ما هي عيوب استخدام REST](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)
* [حل مقابلة تصميم النظام](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Thrift](https://code.facebook.com/posts/1468950976659943/)
* [لماذا REST للاستخدام الداخلي وليس RPC](http://arstechnica.com/civis/viewtopic.php?t=1190508)
## الأمان
هذا القسم يحتاج إلى بعض التحديثات. نرحب [بمساهمتك](#contributing)!
الأمان موضوع واسع. ما لم يكن لديك خبرة كبيرة، أو خلفية في الأمان، أو كنت تتقدم لوظيفة تتطلب معرفة بالأمان، فربما لن تحتاج إلى معرفة أكثر من الأساسيات:
* التشفير أثناء النقل والتخزين.
* تنقية جميع مدخلات المستخدم أو أي معلمات إدخال معرضة للمستخدم لمنع [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) و [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
* استخدام الاستعلامات المعلمة لمنع SQL injection.
* استخدام مبدأ [الامتيازات الأدنى](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
### المصادر وقراءات إضافية
* [قائمة التحقق من أمان API](https://github.com/shieldfy/API-Security-Checklist)
* [دليل الأمان للمطورين](https://github.com/FallibleInc/security-guide-for-developers)
* [أهم عشرة مخاطر OWASP](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
## الملحق
قد يُطلب منك أحياناً إجراء تقديرات تقريبية. على سبيل المثال، قد تحتاج إلى تحديد الوقت اللازم لإنشاء 100 صورة مصغرة من القرص أو مقدار الذاكرة التي ستستهلكها بنية البيانات. يعد **جدول قوى الاثنين** و **أرقام زمن الاستجابة التي يجب أن يعرفها كل مبرمج** مراجع مفيدة.
### جدول قوى الاثنين
```
Power Exact Value Approx Value Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
```
#### المصادر وقراءات إضافية
* [قوى الاثنين](https://en.wikipedia.org/wiki/Power_of_two)
### أرقام زمن الاستجابة التي يجب أن يعرفها كل مبرمج
```
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
HDD seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from HDD 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
```
مقاييس مفيدة مبنية على الأرقام أعلاه:
* القراءة التسلسلية من القرص الصلب HDD بسرعة 30 ميجابايت/ثانية
* القراءة التسلسلية من شبكة إيثرنت 1 جيجابت/ثانية بسرعة 100 ميجابايت/ثانية
* القراءة التسلسلية من القرص الصلب SSD بسرعة 1 جيجابايت/ثانية
* القراءة التسلسلية من الذاكرة الرئيسية بسرعة 4 جيجابايت/ثانية
* 6-7 رحلات ذهاب وإياب حول العالم في الثانية
* 2,000 رحلة ذهاب وإياب في الثانية داخل مركز البيانات
#### تصور أرقام زمن الاستجابة
![](https://camo.githubusercontent.com/77f72259e1eb58596b564d1ad823af1853bc60a3/687474703a2f2f692e696d6775722e636f6d2f6b307431652e706e67)
#### المصادر وقراءات إضافية
* [أرقام زمن الاستجابة التي يجب أن يعرفها كل مبرمج - 1](https://gist.github.com/jboner/2841832)
* [أرقام زمن الاستجابة التي يجب أن يعرفها كل مبرمج - 2](https://gist.github.com/hellerbarde/2843375)
* [تصميمات ودروس ونصائح من بناء أنظمة موزعة كبيرة](http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf)
* [نصائح هندسة البرمجيات من بناء أنظمة موزعة واسعة النطاق](https://static.googleusercontent.com/media/research.google.com/en//people/jeff/stanford-295-talk.pdf)
### أسئلة إضافية في مقابلات تصميم النظم
> أسئلة شائعة في مقابلات تصميم النظم، مع روابط لمصادر حول كيفية حل كل منها.
| السؤال | المرجع/المراجع |
|---|---|
| تصميم خدمة مزامنة ملفات مثل Dropbox | [youtube.com](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| تصميم محرك بحث مثل 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) |
| تصميم متصفح ويب قابل للتطوير مثل Google | [quora.com](https://www.quora.com/How-can-I-build-a-web-crawler-from-scratch) |
| تصميم Google Docs | [code.google.com](https://code.google.com/p/google-mobwrite/)<br/>[neil.fraser.name](https://neil.fraser.name/writing/sync/) |
| تصميم مخزن key-value مثل Redis | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| تصميم نظام تخزين مؤقت مثل Memcached | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| تصميم نظام توصيات مثل نظام Amazon | [hulu.com](https://web.archive.org/web/20170406065247/http://tech.hulu.com/blog/2011/09/19/recommendation-system.html)<br/>[ijcai13.org](http://ijcai13.org/files/tutorial_slides/td3.pdf) |
| تصميم نظام URL مختصر مثل Bitly | [n00tc0d3r.blogspot.com](http://n00tc0d3r.blogspot.com/) |
| تصميم تطبيق دردشة مثل WhatsApp | [highscalability.com](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| تصميم نظام مشاركة صور مثل 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) |
| تصميم وظيفة الأخبار في Facebook | [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) |
| تصميم وظيفة الجدول الزمني في Facebook | [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) |
| تصميم وظيفة الدردشة في Facebook | [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) |
| تصميم وظيفة البحث في الرسوم البيانية مثل Facebook | [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) |
| تصميم شبكة توصيل محتوى مثل CloudFlare | [figshare.com](https://figshare.com/articles/Globally_distributed_content_delivery/6605972) |
| تصميم نظام المواضيع الرائجة مثل Twitter | [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/) |
| تصميم نظام توليد معرّف عشوائي | [blog.twitter.com](https://blog.twitter.com/2010/announcing-snowflake)<br/>[github.com](https://github.com/twitter/snowflake/) |
| إرجاع أعلى k طلب خلال فترة زمنية | [cs.ucsb.edu](https://www.cs.ucsb.edu/sites/default/files/documents/2005-23.pdf)<br/>[wpi.edu](http://davis.wpi.edu/xmdv/docs/EDBT11-diyang.pdf) |
| تصميم نظام يقدم البيانات من مراكز بيانات متعددة | [highscalability.com](http://highscalability.com/blog/2009/8/24/how-google-serves-data-from-multiple-datacenters.html) |
| تصميم لعبة ورق متعددة اللاعبين عبر الإنترنت | [indieflashblog.com](https://web.archive.org/web/20180929181117/http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)<br/>[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| تصميم نظام جمع النفايات | [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) |
| تصميم محدد معدل API | [stripe.com/blog/](https://stripe.com/blog/rate-limiters) |
| تصميم بورصة (مثل NASDAQ أو Binance) | [Jane Street](https://youtu.be/b1e4t2k2KJY)<br/>[تطبيق Golang](https://around25.com/blog/building-a-trading-engine-for-a-crypto-exchange/)<br/>[تطبيق Go](http://bhomnick.net/building-a-simple-limit-order-in-go/) |
| إضافة سؤال تصميم نظام | [المساهمة](#contributing) |
### تصميمات الأنظمة في العالم الحقيقي
> مقالات حول كيفية تصميم الأنظمة في العالم الحقيقي.
<p align="center">
<img src="images/TcUo2fw.png">
<br/>
<i><a href=https://www.infoq.com/presentations/Twitter-Timeline-Scalability>المصدر: الجداول الزمنية في Twitter على نطاق واسع</a></i>
</p>
**لا تركز على التفاصيل الدقيقة في المقالات التالية، بدلاً من ذلك:**
* حدد المبادئ المشتركة والتقنيات الشائعة والأنماط داخل هذه المقالات
* ادرس المشكلات التي يحلها كل مكون، وأين يعمل بشكل جيد، وأين لا يعمل
* راجع الدروس المستفادة
|النوع | النظام | المرجع/المراجع |
|---|---|---|
| معالجة البيانات | **MapReduce** - معالجة البيانات الموزعة من Google | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/mapreduce-osdi04.pdf) |
| معالجة البيانات | **Spark** - معالجة البيانات الموزعة من Databricks | [slideshare.net](http://www.slideshare.net/AGrishchenko/apache-spark-architecture) |
| معالجة البيانات | **Storm** - معالجة البيانات الموزعة من Twitter | [slideshare.net](http://www.slideshare.net/previa/storm-16094009) |
| | | |
| مخزن البيانات | **Bigtable** - قاعدة بيانات موزعة موجهة للأعمدة من Google | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) |
| مخزن البيانات | **HBase** - تطبيق مفتوح المصدر لـ Bigtable | [slideshare.net](http://www.slideshare.net/alexbaranau/intro-to-hbase) |
| مخزن البيانات | **Cassandra** - قاعدة بيانات موزعة موجهة للأعمدة من Facebook | [slideshare.net](http://www.slideshare.net/planetcassandra/cassandra-introduction-features-30103666)
| مخزن البيانات | **DynamoDB** - قاعدة بيانات موجهة للمستندات من Amazon | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) |
| مخزن البيانات | **MongoDB** - قاعدة بيانات موجهة للمستندات | [slideshare.net](http://www.slideshare.net/mdirolf/introduction-to-mongodb) |
| مخزن البيانات | **Spanner** - قاعدة بيانات موزعة عالمياً من Google | [research.google.com](http://research.google.com/archive/spanner-osdi2012.pdf) |
| مخزن البيانات | **Memcached** - نظام تخزين مؤقت موزع في الذاكرة | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| مخزن البيانات | **Redis** - نظام تخزين مؤقت موزع في الذاكرة مع الاستمرارية وأنواع القيم | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| | | |
| نظام الملفات | **Google File System (GFS)** - نظام ملفات موزع | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/gfs-sosp2003.pdf) |
| نظام الملفات | **Hadoop File System (HDFS)** - تطبيق مفتوح المصدر لـ GFS | [apache.org](http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html) |
| | | |
| متنوع | **Chubby** - خدمة قفل للأنظمة الموزعة المترابطة بشكل فضفاض من Google | [research.google.com](http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/archive/chubby-osdi06.pdf) |
| متنوع | **Dapper** - بنية تحتية لتتبع الأنظمة الموزعة | [research.google.com](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf)
| متنوع | **Kafka** - نظام رسائل publish/subscribe من LinkedIn | [slideshare.net](http://www.slideshare.net/mumrah/kafka-talk-tri-hug) |
| متنوع | **Zookeeper** - بنية تحتية وخدمات مركزية تمكن المزامنة | [slideshare.net](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) |
| | إضافة تصميم معماري | [المساهمة](#contributing) |
### تصميمات معمارية للشركات
| الشركة | المرجع/المراجع |
|---|---|
| Amazon | [بنية Amazon](http://highscalability.com/amazon-architecture) |
| Cinchcast | [إنتاج 1,500 ساعة من الصوت يومياً](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html) |
| DataSift | [تحليل البيانات في الوقت الفعلي بمعدل 120,000 تغريدة في الثانية](http://highscalability.com/blog/2011/11/29/datasift-architecture-realtime-datamining-at-120000-tweets-p.html) |
| Dropbox | [كيف قمنا بتوسيع نطاق Dropbox](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| ESPN | [التشغيل بمعدل 100,000 عملية في الثانية](http://highscalability.com/blog/2013/11/4/espns-architecture-at-scale-operating-at-100000-duh-nuh-nuhs.html) |
| Google | [بنية Google](http://highscalability.com/google-architecture) |
| Instagram | [14 مليون مستخدم، تيرابايتات من الصور](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html)<br/>[ما الذي يشغل Instagram](http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances) |
| Justin.tv | [بنية بث الفيديو المباشر لـ Justin.Tv](http://highscalability.com/blog/2010/3/16/justintvs-live-video-broadcasting-architecture.html) |
| Facebook | [توسيع نطاق memcached في Facebook](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/key-value/fb-memcached-nsdi-2013.pdf)<br/>[TAO: مخزن البيانات الموزع للرسم البياني الاجتماعي في Facebook](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/data-store/tao-facebook-distributed-datastore-atc-2013.pdf)<br/>[تخزين الصور في Facebook](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf)<br/>[كيف يبث Facebook Live إلى 800,000 مشاهد في وقت واحد](http://highscalability.com/blog/2016/6/27/how-facebook-live-streams-to-800000-simultaneous-viewers.html) |
| Flickr | [بنية Flickr](http://highscalability.com/flickr-architecture) |
| Mailbox | [من 0 إلى مليون مستخدم في 6 أسابيع](http://highscalability.com/blog/2013/6/18/scaling-mailbox-from-0-to-one-million-users-in-6-weeks-and-1.html) |
| Netflix | [نظرة شاملة 360 درجة على كامل بنية Netflix](http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html)<br/>[Netflix: ماذا يحدث عندما تضغط على زر التشغيل؟](http://highscalability.com/blog/2017/12/11/netflix-what-happens-when-you-press-play.html) |
| Pinterest | [من 0 إلى عشرات المليارات من مشاهدات الصفحات شهرياً](http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html)<br/>[18 مليون زائر، نمو 10 أضعاف، 12 موظف](http://highscalability.com/blog/2012/5/21/pinterest-architecture-update-18-million-visitors-10x-growth.html) |
| Playfish | [50 مليون مستخدم شهرياً وفي نمو مستمر](http://highscalability.com/blog/2010/9/21/playfishs-social-gaming-architecture-50-million-monthly-user.html) |
| PlentyOfFish | [بنية PlentyOfFish](http://highscalability.com/plentyoffish-architecture) |
| Salesforce | [كيف يتعاملون مع 1.3 مليار معاملة يومياً](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html) |
| Stack Overflow | [بنية Stack Overflow](http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html) |
| TripAdvisor | [40 مليون زائر، 200 مليون مشاهدة صفحة ديناميكية، 30 تيرابايت من البيانات](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.html) |
| Tumblr | [15 مليار مشاهدة صفحة شهرياً](http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html) |
| Twitter | [جعل Twitter أسرع بنسبة 10000 بالمئة](http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster)<br/>[تخزين 250 مليون تغريدة يومياً باستخدام MySQL](http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html)<br/>[150 مليون مستخدم نشط، 300 ألف استعلام في الثانية، تدفق بيانات بسرعة 22 ميجابايت/ثانية](http://highscalability.com/blog/2013/7/8/the-architecture-twitter-uses-to-deal-with-150m-active-users.html)<br/>[الجداول الزمنية على نطاق واسع](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)<br/>[البيانات الكبيرة والصغيرة في Twitter](https://www.youtube.com/watch?v=5cKTP36HVgI)<br/>[العمليات في Twitter: التوسع لأكثر من 100 مليون مستخدم](https://www.youtube.com/watch?v=z8LU0Cj6BOU)<br/>[كيف يتعامل Twitter مع 3,000 صورة في الثانية](http://highscalability.com/blog/2016/4/20/how-twitter-handles-3000-images-per-second.html) |
| Uber | [كيف توسع Uber منصة السوق في الوقت الفعلي](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html)<br/>[الدروس المستفادة من توسيع Uber إلى 2000 مهندس، 1000 خدمة، و8000 مستودع Git](http://highscalability.com/blog/2016/10/12/lessons-learned-from-scaling-uber-to-2000-engineers-1000-ser.html) |
| WhatsApp | [بنية WhatsApp التي اشتراها Facebook مقابل 19 مليار دولار](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| YouTube | [قابلية توسع YouTube](https://www.youtube.com/watch?v=w5WVu624fY8)<br/>[بنية YouTube](http://highscalability.com/youtube-architecture) |
### مدونات هندسة الشركات
> البنى المعمارية للشركات التي تجري مقابلات معها.
>
> قد تكون الأسئلة التي تواجهها من نفس المجال.
* [Airbnb Engineering](http://nerds.airbnb.com/)
* [Atlassian Developers](https://developer.atlassian.com/blog/)
* [AWS Blog](https://aws.amazon.com/blogs/aws/)
* [Bitly Engineering Blog](http://word.bitly.com/)
* [Box Blogs](https://blog.box.com/blog/category/engineering)
* [Cloudera Developer Blog](http://blog.cloudera.com/)
* [Dropbox Tech Blog](https://tech.dropbox.com/)
* [Engineering at Quora](https://www.quora.com/q/quoraengineering)
* [Ebay Tech Blog](http://www.ebaytechblog.com/)
* [Evernote Tech Blog](https://blog.evernote.com/tech/)
* [Etsy Code as Craft](http://codeascraft.com/)
* [Facebook Engineering](https://www.facebook.com/Engineering)
* [Flickr Code](http://code.flickr.net/)
* [Foursquare Engineering Blog](http://engineering.foursquare.com/)
* [GitHub Engineering Blog](https://github.blog/category/engineering)
* [Google Research Blog](http://googleresearch.blogspot.com/)
* [Groupon Engineering Blog](https://engineering.groupon.com/)
* [Heroku Engineering Blog](https://engineering.heroku.com/)
* [Hubspot Engineering Blog](http://product.hubspot.com/blog/topic/engineering)
* [High Scalability](http://highscalability.com/)
* [Instagram Engineering](http://instagram-engineering.tumblr.com/)
* [Intel Software Blog](https://software.intel.com/en-us/blogs/)
* [Jane Street Tech Blog](https://blogs.janestreet.com/category/ocaml/)
* [LinkedIn Engineering](http://engineering.linkedin.com/blog)
* [Microsoft Engineering](https://engineering.microsoft.com/)
* [Microsoft Python Engineering](https://blogs.msdn.microsoft.com/pythonengineering/)
* [Netflix Tech Blog](http://techblog.netflix.com/)
* [Paypal Developer Blog](https://medium.com/paypal-engineering)
* [Pinterest Engineering Blog](https://medium.com/@Pinterest_Engineering)
* [Reddit Blog](http://www.redditblog.com/)
* [Salesforce Engineering Blog](https://developer.salesforce.com/blogs/engineering/)
* [Slack Engineering Blog](https://slack.engineering/)
* [Spotify Labs](https://labs.spotify.com/)
* [Stripe Engineering Blog](https://stripe.com/blog/engineering)
* [Twilio Engineering Blog](http://www.twilio.com/engineering)
* [Twitter Engineering](https://blog.twitter.com/engineering/)
* [Uber Engineering Blog](http://eng.uber.com/)
* [Yahoo Engineering Blog](http://yahooeng.tumblr.com/)
* [Yelp Engineering Blog](http://engineeringblog.yelp.com/)
* [Zynga Engineering Blog](https://www.zynga.com/blogs/engineering)
#### المصادر وقراءات إضافية
هل ترغب في إضافة مدونة؟ لتجنب تكرار العمل، يمكنك إضافة مدونة شركتك إلى المستودع التالي:
* [kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)
## قيد التطوير
هل أنت مهتم بإضافة قسم جديد أو المساعدة في إكمال قسم قيد التطوير؟ [ساهم معنا](#contributing)!
* الحوسبة الموزعة باستخدام MapReduce
* التجزئة المتناسقة (Consistent hashing)
* التجميع والتوزيع (Scatter gather)
* [ساهم معنا](#contributing)
## شكر وتقدير
تم توفير الشكر والمصادر في جميع أنحاء هذا المستودع (repository).
شكر خاص لـ:
* [Hired in tech](http://www.hiredintech.com/system-design/the-system-design-process/)
* [Cracking the coding interview](https://www.amazon.com/dp/0984782850/)
* [High scalability](http://highscalability.com/)
* [checkcheckzz/system-design-interview](https://github.com/checkcheckzz/system-design-interview)
* [shashank88/system_design](https://github.com/shashank88/system_design)
* [mmcgrana/services-engineering](https://github.com/mmcgrana/services-engineering)
* [System design cheat sheet](https://gist.github.com/vasanthk/485d1c25737e8e72759f)
* [A distributed systems reading list](http://dancres.github.io/Pages/)
* [Cracking the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
## معلومات الاتصال
لا تتردد في التواصل معي لمناقشة أي مشكلات أو أسئلة أو تعليقات.
يمكنك العثور على معلومات الاتصال الخاصة بي على [صفحتي على GitHub](https://github.com/donnemartin).
## الترخيص
*أقدم لك الكود والموارد في هذا الـ repository تحت ترخيص مفتوح المصدر. نظراً لأن هذا repository شخصي، فإن الترخيص الذي تتلقاه للكود والموارد الخاصة بي هو مني وليس من صاحب عملي (Facebook).*
Copyright 2017 Donne Martin
Creative Commons Attribution 4.0 International License (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/

1792
docs/README-ja.md Normal file
View File

@@ -0,0 +1,1792 @@
*[English](README.md) ∙ [日本語](README-ja.md) ∙ [简体中文](README-zh-Hans.md) ∙ [繁體中文](README-zh-TW.md) ∙ [العَرَبِيَّة‎](README-ar.md) ∙ [বাংলা](https://github.com/donnemartin/system-design-primer/issues/220) ∙ [Português do Brasil](https://github.com/donnemartin/system-design-primer/issues/40) ∙ [Deutsch](https://github.com/donnemartin/system-design-primer/issues/186) ∙ [ελληνικά](https://github.com/donnemartin/system-design-primer/issues/130) ∙ [עברית](https://github.com/donnemartin/system-design-primer/issues/272) ∙ [Italiano](https://github.com/donnemartin/system-design-primer/issues/104) ∙ [한국어](https://github.com/donnemartin/system-design-primer/issues/102) ∙ [فارسی](https://github.com/donnemartin/system-design-primer/issues/110) ∙ [Polski](https://github.com/donnemartin/system-design-primer/issues/68) ∙ [русский язык](https://github.com/donnemartin/system-design-primer/issues/87) ∙ [Español](https://github.com/donnemartin/system-design-primer/issues/136) ∙ [ภาษาไทย](https://github.com/donnemartin/system-design-primer/issues/187) ∙ [Türkçe](https://github.com/donnemartin/system-design-primer/issues/39) ∙ [tiếng Việt](https://github.com/donnemartin/system-design-primer/issues/127) ∙ [Français](https://github.com/donnemartin/system-design-primer/issues/250) | [Add Translation](https://github.com/donnemartin/system-design-primer/issues/28)*
# システム設計入門
<p align="center">
<img src="images/jj3A5N8.png">
<br/>
</p>
## 動機・目的
> 大規模システムのシステム設計を学ぶ
>
> システム設計面接課題に備える
### 大規模システムの設計を学ぶ
スケーラブルなシステム設計を学習することは、より良いエンジニアになることに資するでしょう。
システム設計は広範囲なトピックをカバーします。システム設計原理については **インターネット上には膨大な量の文献が散らばっています。**
このリポジトリは大規模システム構築に必要な知識を学ぶことができる **文献リストを一か所にまとめたもの** です。
### オープンソースコミュニティから学ぶ
このプロジェクトは、定期的に更新されていく予定のオープンソースプロジェクトの初期段階にすぎません。
[Contributions](#contributing) は大歓迎です!
### システム設計面接課題に備える
コード技術面接に加えて、システム設計に関する知識は、多くのテック企業における **技術採用面接プロセス****必要不可欠な要素** です。
**システム設計面接での頻出質問に備え**、自分の解答と*模範解答*:ディスカッション、コードそして図表などを*比較*して学びましょう。
面接準備に役立つその他のトピック:
* [学習指針](#学習指針)
* [システム設計面接課題にどのように準備するか](#システム設計面接にどのようにして臨めばいいか)
* [システム設計課題例 **とその解答**](#システム設計課題例とその解答)
* [オブジェクト指向設計課題例、 **とその解答**](#オブジェクト指向設計問題と解答)
* [その他のシステム設計面接課題例](#他のシステム設計面接例題)
## 暗記カード
<p align="center">
<img src="images/zdCAkB3.png">
<br/>
</p>
この[Anki用フラッシュカードデッキ](https://apps.ankiweb.net/) は、間隔反復を活用して、システム設計のキーコンセプトの学習を支援します。
* [システム設計デッキ](resources/flash_cards/System%20Design.apkg)
* [システム設計練習課題デッキ](resources/flash_cards/System%20Design%20Exercises.apkg)
* [オブジェクト指向練習課題デッキ](resources/flash_cards/OO%20Design.apkg)
外出先や移動中の勉強に役立つと幸いです。
### コーディング技術課題用の問題: 練習用インタラクティブアプリケーション
コード技術面接用の問題は[**こちら**](https://github.com/donnemartin/interactive-coding-challenges)
<p align="center">
<img src="images/b4YtAEN.png">
<br/>
</p>
関連リポジトリの [**Interactive Coding Challenges**](https://github.com/donnemartin/interactive-coding-challenges)も是非参照下さい。追加の暗記デッキカードも入っています。
* [Coding deck](https://github.com/donnemartin/interactive-coding-challenges/tree/master/anki_cards/Coding.apkg)
## コントリビュート
> コミュニティから学ぶ
プルリクエスト等の貢献は積極的にお願いします:
* エラー修正
* セクション内容改善
* 新規セクション追加
* [翻訳](https://github.com/donnemartin/system-design-primer/issues/28)
現在、内容の改善が必要な作業中のコンテンツは[こちら](#進行中の作業)です。
コントリビュートの前に[Contributing Guidelines](CONTRIBUTING.md)を読みましょう。
## システム設計目次
> 賛否も含めた様々なシステム設計の各トピックの概要。 **全てはトレードオフの関係にあります。**
>
> それぞれのセクションはより学びを深めるような他の文献へのリンクが貼られています。
<p align="center">
<img src="images/jrUBAF7.png">
<br/>
</p>
* [システム設計トピック: まずはここから](#システム設計トピックス-まずはここから)
* [Step 1: スケーラビリティに関する動画を見る](#ステップ-1-スケーラビリティに関する動画を観て復習する)
* [Step 2: スケーラビリティに関する記事を読む](#ステップ-2-スケーラビリティに関する資料を読んで復習する)
* [次のステップ](#次のステップ)
* [パフォーマンス vs スケーラビリティ](#パフォーマンス-vs-スケーラビリティ)
* [レイテンシー vs スループット](#レイテンシー-vs-スループット)
* [可用性 vs 一貫性](#可用性-vs-一貫性)
* [CAP理論](#cap-理論)
* [CP - 一貫性(consistency)と分割性(partition)耐性](#cp---一貫性と分断耐性consistency-and-partition-tolerance)
* [AP - 可用性(availability)と分割性(partition)耐性](#ap---可用性と分断耐性availability-and-partition-tolerance)
* [一貫性 パターン](#一貫性パターン)
* [弱い一貫性](#弱い一貫性)
* [結果整合性](#結果整合性)
* [強い一貫性](#強い一貫性)
* [可用性 パターン](#可用性パターン)
* [フェイルオーバー](#フェイルオーバー)
* [レプリケーション](#レプリケーション)
* [ドメインネームシステム(DNS)](#ドメインネームシステム)
* [コンテンツデリバリーネットワーク(CDN)](#コンテンツデリバリーネットワークcontent-delivery-network)
* [プッシュCDN](#プッシュcdn)
* [プルCDN](#プルcdn)
* [ロードバランサー](#ロードバランサー)
* [アクティブ/パッシブ構成](#アクティブパッシブ)
* [アクティブ/アクティブ構成](#アクティブアクティブ)
* [Layer 4 ロードバランシング](#layer-4-ロードバランシング)
* [Layer 7 ロードバランシング](#layer-7-ロードバランシング)
* [水平スケーリング](#水平スケーリング)
* [リバースプロキシ (WEBサーバー)](#リバースプロキシwebサーバー)
* [ロードバランサー vs リバースプロキシ](#ロードバランサー-vs-リバースプロキシ)
* [アプリケーションレイヤー](#アプリケーション層)
* [マイクロサービス](#マイクロサービス)
* [サービスディスカバリー](#service-discovery)
* [データベース](#データベース)
* [リレーショナルデータベースマネジメントシステム (RDBMS)](#リレーショナルデータベースマネジメントシステム-rdbms)
* [マスター/スレーブ レプリケーション](#マスタースレーブ-レプリケーション)
* [マスター/マスター レプリケーション](#マスターマスター-レプリケーション)
* [フェデレーション](#federation)
* [シャーディング](#シャーディング)
* [デノーマライゼーション](#非正規化)
* [SQL チューニング](#sqlチューニング)
* [NoSQL](#nosql)
* [キー/バリューストア](#キーバリューストア)
* [ドキュメントストア](#ドキュメントストア)
* [ワイドカラムストア](#ワイドカラムストア)
* [グラフ データベース](#グラフデータベース)
* [SQL or NoSQL](#sqlかnosqlか)
* [キャッシュ](#キャッシュ)
* [クライアントキャッシング](#クライアントキャッシング)
* [CDNキャッシング](#cdnキャッシング)
* [Webサーバーキャッシング](#webサーバーキャッシング)
* [データベースキャッシング](#データベースキャッシング)
* [アプリケーションキャッシング](#アプリケーションキャッシング)
* [データベースクエリレベルでキャッシングする](#データベースクエリレベルでのキャッシング)
* [オブジェクトレベルでキャッシングする](#オブジェクトレベルでのキャッシング)
* [いつキャッシュを更新するのか](#いつキャッシュを更新するか)
* [キャッシュアサイド](#キャッシュアサイド)
* [ライトスルー](#ライトスルー)
* [ライトビハインド (ライトバック)](#ライトビハインド-ライトバック)
* [リフレッシュアヘッド](#リフレッシュアヘッド)
* [非同期処理](#非同期処理)
* [メッセージキュー](#メッセージキュー)
* [タスクキュー](#タスクキュー)
* [バックプレッシャー](#バックプレッシャー)
* [通信](#通信)
* [伝送制御プロトコル (TCP)](#伝送制御プロトコル-tcp)
* [ユーザデータグラムプロトコル (UDP)](#ユーザデータグラムプロトコル-udp)
* [遠隔手続呼出 (RPC)](#遠隔手続呼出-rpc)
* [Representational state transfer (REST)](#representational-state-transfer-rest)
* [セキュリティ](#セキュリティ)
* [補遺](#補遺)
* [2の乗数表](#2の乗数表)
* [全てのプログラマーが知るべきレイテンシー値](#全てのプログラマーが知るべきレイテンシー値)
* [他のシステム設計面接例題](#他のシステム設計面接例題)
* [実世界でのアーキテクチャ](#実世界のアーキテクチャ)
* [各企業のアーキテクチャ](#各企業のアーキテクチャ)
* [企業のエンジニアブログ](#企業のエンジニアブログ)
* [作業中](#進行中の作業)
* [クレジット](#クレジット)
* [連絡情報](#contact-info)
* [ライセンス](#license)
## 学習指針
> 学習スパンに応じてみるべきトピックス (short, medium, long)
![Imgur](images/OfVllex.png)
**Q: 面接のためには、ここにあるものすべてをやらないといけないのでしょうか?**
**A: いいえ、ここにあるすべてをやる必要はありません。**
面接で何を聞かれるかは以下の条件によって変わってきます:
* 面接者の技術経験
* どのポジションのために面接を受けているか
* どの企業の面接を受けているか
*
より経験のある候補者は一般的にシステム設計についてより深い知識を有していることを要求されるでしょう。システムアーキテクトやチームリーダーは各メンバーの持つような知識よりは深い見識を持っているべきでしょう。一流テック企業では複数回の設計面接を課されることが多いです。
まずは広く始めて、そこからいくつかの分野に絞って深めていくのがいいでしょう。様々なシステム設計のトピックについて少しずつ知っておくことはいいことです。以下の学習ガイドを自分の学習に当てられる時間、技術経験、どの職位、どの会社に応募しているかなどを加味して自分用に調整して使うといいでしょう。
* **短期間** - **幅広く** システム設計トピックを学ぶ。**いくつかの** 面接課題を解くことで対策する。
* **中期間** - **幅広く** そして **それなりに深く**システム設計トピックを学ぶ。**多くの** 面接課題を解くことで対策する。
* **長期間** - **幅広く** そして **もっと深く**システム設計トピックを学ぶ。**ほぼ全ての** 面接課題を解くことで対策する。
| | 短期間 | 中期間 | 長期間 |
|---|---|---|---|
| [システム設計トピック](#システム設計目次) を読み、システム動作機序について広く知る | :+1: | :+1: | :+1: |
| 次のリンク先のいくつかのページを読んで [各企業のエンジニアリングブログ](#企業のエンジニアブログ) 応募する会社について知る | :+1: | :+1: | :+1: |
| 次のリンク先のいくつかのページを読む [実世界でのアーキテクチャ](#実世界のアーキテクチャ) | :+1: | :+1: | :+1: |
| 復習する [システム設計面接課題にどのように準備するか](#システム設計面接にどのようにして臨めばいいか) | :+1: | :+1: | :+1: |
| とりあえず一周する [システム設計課題例](#システム設計課題例とその解答) | Some | Many | Most |
| とりあえず一周する [オブジェクト指向設計問題と解答](#オブジェクト指向設計問題と解答) | Some | Many | Most |
| 復習する [その他システム設計面接での質問例](#他のシステム設計面接例題) | Some | Many | Most |
## システム設計面接にどのようにして臨めばいいか
> システム設計面接試験問題にどのように取り組むか
システム設計面接は **open-ended conversation(Yes/Noでは答えられない口頭質問)です**。 自分で会話を組み立てることを求められます。
以下のステップに従って議論を組み立てることができるでしょう。この過程を確かなものにするために、次のセクション[システム設計課題例とその解答](#system-design-interview-questions-with-solutions) を以下の指針に従って読み込むといいでしょう。
### ステップ 1: システム使用例の概要、制約、推計値等を聞き出し、まとめる
システム仕様の要求事項を聞き出し、問題箇所を特定しましょう。使用例と制約を明確にするための質問を投げかけましょう。要求する推計値についても議論しておきましょう。
* 誰がサービスを使うのか?
* どのように使うのか?
* 何人のユーザーがいるのか?
* システムはどのような機能を果たすのか?
* システムへの入力と出力は?
* どれだけの容量のデータを捌く必要があるのか?
* 一秒間に何リクエストの送信が想定されるか?
* 読み書き比率の推定値はどれくらいか?
### ステップ 2: 高レベルのシステム設計を組み立てる
重要なコンポーネントを全て考慮した高レベルのシステム設計概要を組み立てる。
* 主要なコンポーネントと接続をスケッチして書き出す
* 考えの裏付けをまとめる
### ステップ 3: 核となるコンポーネントを設計する
それぞれの主要なコンポーネントについての詳細を学ぶ。例えば、[url短縮サービス](solutions/system_design/pastebin/README.md)の設計を問われた際には次のようにするといいでしょう:
* 元のURLのハッシュ化したものを作り、それを保存する
* [MD5](solutions/system_design/pastebin/README.md) と [Base62](solutions/system_design/pastebin/README.md)
* ハッシュ衝突
* SQL もしくは NoSQL
* データベーススキーマ
* ハッシュ化されたURLを元のURLに再翻訳する
* データベース参照
* API & オブジェクト指向の設計
### ステップ 4: システム設計のスケール
与えられた制約条件からボトルネックとなりそうなところを割り出し、明確化する。 例えば、スケーラビリティの問題解決のために以下の要素を考慮する必要があるだろうか?
* ロードバランサー
* 水平スケーリング
* キャッシング
* データベースシャーディング
取りうる解決策とそのトレードオフについて議論をしよう。全てのことはトレードオフの関係にある。ボトルネックについては[スケーラブルなシステム設計の原理](#システム設計目次)を読むといいでしょう。
### ちょっとした暗算問題
ちょっとした推計値を手計算ですることを求められることもあるかもしれません。[補遺](#補遺)の以下の項目が役に立つでしょう:
* [チラ裏計算でシステム設計する](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
* [2の乗数表](#2の乗数表)
* [全てのプログラマーが知っておくべきレイテンシの参考値](#全てのプログラマーが知るべきレイテンシー値)
### 文献とその他の参考資料
以下のリンク先ページを見てどのような質問を投げかけられるか概要を頭に入れておきましょう:
* [システム設計面接で成功するには?](https://web.archive.org/web/20210505130322/https://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)
* [システム設計面接](http://www.hiredintech.com/system-design)
* [アーキテクチャ、システム設計面接への導入](https://www.youtube.com/watch?v=ZgdS0EUmn70)
* [システム設計テンプレート](https://leetcode.com/discuss/career/229177/My-System-Design-Template)
## システム設計課題例とその解答
> 頻出のシステム設計面接課題と参考解答、コード及びダイアグラム
>
> 解答は `solutions/` フォルダ以下にリンクが貼られている
| 問題 | |
|---|---|
| Pastebin.com (もしくは Bit.ly) を設計する| [解答](solutions/system_design/pastebin/README.md) |
| Twitterタイムライン (もしくはFacebookフィード)を設計する<br/>Twitter検索(もしくはFacebook検索)機能を設計する | [解答](solutions/system_design/twitter/README.md) |
| ウェブクローラーを設計する | [解答](solutions/system_design/web_crawler/README.md) |
| Mint.comを設計する | [解答](solutions/system_design/mint/README.md) |
| SNSサービスのデータ構造を設計する | [解答](solutions/system_design/social_graph/README.md) |
| 検索エンジンのキー/バリュー構造を設計する | [解答](solutions/system_design/query_cache/README.md) |
| Amazonのカテゴリ毎の売り上げランキングを設計する | [解答](solutions/system_design/sales_rank/README.md) |
| AWS上で100万人規模のユーザーを捌くサービスを設計する | [解答](solutions/system_design/scaling_aws/README.md) |
| システム設計問題を追加する | [Contribute](#contributing) |
### Pastebin.com (もしくは Bit.ly) の設計
[問題と解答を見る](solutions/system_design/pastebin/README.md)
![Imgur](images/4edXG0T.png)
### Twitterタイムライン&検索 (もしくはFacebookフィード&検索)の設計
[問題と解答を見る](solutions/system_design/twitter/README.md)
![Imgur](images/jrUBAF7.png)
### ウェブクローラーの設計
[問題と解答を見る](solutions/system_design/web_crawler/README.md)
![Imgur](images/bWxPtQA.png)
### Mint.comの設計
[問題と解答を見る](solutions/system_design/mint/README.md)
![Imgur](images/V5q57vU.png)
### SNSサービスのデータ構造の設計
[問題と解答を見る](solutions/system_design/social_graph/README.md)
![Imgur](images/cdCv5g7.png)
### 検索エンジンのキー/バリュー構造の設計
[問題と解答を見る](solutions/system_design/query_cache/README.md)
![Imgur](images/4j99mhe.png)
### Amazonのカテゴリ毎の売り上げランキングの設計
[問題と解答を見る](solutions/system_design/sales_rank/README.md)
![Imgur](images/MzExP06.png)
### AWS上で100万人規模のユーザーを捌くサービスの設計
[問題と解答を見る](solutions/system_design/scaling_aws/README.md)
![Imgur](images/jj3A5N8.png)
## オブジェクト指向設計問題と解答
> 頻出のオブジェクト指向システム設計面接課題と参考解答、コード及びダイアグラム
>
> 解答は `solutions/` フォルダ以下にリンクが貼られている
>**備考: このセクションは作業中です**
| 問題 | |
|---|---|
| ハッシュマップの設計 | [解答](solutions/object_oriented_design/hash_table/hash_map.ipynb) |
| LRUキャッシュの設計 | [解答](solutions/object_oriented_design/lru_cache/lru_cache.ipynb) |
| コールセンターの設計 | [解答](solutions/object_oriented_design/call_center/call_center.ipynb) |
| カードのデッキの設計 | [解答](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| 駐車場の設計 | [解答](solutions/object_oriented_design/parking_lot/parking_lot.ipynb) |
| チャットサーバーの設計 | [解答](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| 円形配列の設計 | [Contribute](#contributing) |
| オブジェクト指向システム設計問題を追加する | [Contribute](#contributing) |
## システム設計トピックス: まずはここから
システム設計の勉強は初めて?
まず初めに、よく使われる設計原理について、それらが何であるか、どのように用いられるか、長所短所について基本的な知識を得る必要があります
### ステップ 1: スケーラビリティに関する動画を観て復習する
[Harvardでのスケーラビリティの講義](https://www.youtube.com/watch?v=-W9F__D3oY4)
* ここで触れられているトピックス:
* 垂直スケーリング
* 水平スケーリング
* キャッシング
* ロードバランシング
* データベースレプリケーション
* データベースパーティション
### ステップ 2: スケーラビリティに関する資料を読んで復習する
[スケーラビリティ](https://lecloud.tumblr.com/tagged/scalability)
* ここで触れられているトピックス:
* [クローン](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [データベース](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [キャッシュ](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [非同期](https://lecloud.tumblr.com/post/9699762917/scalability-for-dummies-part-4-asynchronism)
### 次のステップ
次に、ハイレベルでのトレードオフについてみていく:
* **パフォーマンス** vs **スケーラビリティ**
* **レイテンシ** vs **スループット**
* **可用性** vs **一貫性**
**全てはトレードオフの関係にある**というのを肝に命じておきましょう。
それから、より深い内容、DNSやCDNそしてロードバランサーなどについて学習を進めていきましょう。
## パフォーマンス vs スケーラビリティ
リソースが追加されるのにつれて **パフォーマンス** が向上する場合、そのサービスは **スケーラブル** であると言えるでしょう。一般的に、パフォーマンスを向上させるというのはすなわち計算処理を増やすことを意味しますが、データセットが増えた時などより大きな処理を捌けるようになることでもあります。<sup><a href=http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html>1</a></sup>
パフォーマンスvsスケーラビリティをとらえる他の考え方:
* **パフォーマンス** での問題を抱えている時、あなたのシステムは一人のユーザーにとって遅いと言えるでしょう。
* **スケーラビリティ** での問題を抱えているとき、一人のユーザーにとっては速いですが、多くのリクエストがある時には遅くなってしまうでしょう。
### その他の参考資料、ページ
* [スケーラビリティについて](http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)
* [スケーラビリティ、可用性、安定性、パターン](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
## レイテンシー vs スループット
**レイテンシー** とはなにがしかの動作を行う、もしくは結果を算出するのに要する時間
**スループット** とはそのような動作や結果算出が単位時間に行われる回数
一般的に、 **最大限のスループット****許容範囲内のレイテンシー** で実現することを目指すのが普通だ。
### その他の参考資料、ページ
* [レイテンシー vs スループットを理解する](https://community.cadence.com/cadence_blogs_8/b/sd/archive/2010/09/13/understanding-latency-vs-throughput)
## 可用性 vs 一貫性
### CAP 理論
<p align="center">
<img src="images/bgLMI2u.png">
<br/>
<i><a href=http://robertgreiner.com/2014/08/cap-theorem-revisited>Source: CAP theorem revisited</a></i>
</p>
分散型コンピュータシステムにおいては下の三つのうち二つまでしか同時に保証することはできない。:
* **一貫性** - 全ての読み込みは最新の書き込みもしくはエラーを受け取る
* **可用性** - 受け取る情報が最新のバージョンだという保証はないが、全てのリクエストはレスポンスを必ず受け取る
* **分断耐性** - ネットワーク問題によって順不同の分断が起きてもシステムが動作を続ける
*ネットワークは信頼できないので、分断耐性は必ず保証しなければなりません。つまりソフトウェアシステムとしてのトレードオフは、一貫性を取るか、可用性を取るかを考えなければなりません。*
#### CP - 一貫性と分断耐性(consistency and partition tolerance)
分断されたードからのレスポンスを待ち続けているとタイムアウトエラーに陥る可能性があります。CPはあなたのサービスがアトミックな読み書き不可分操作を必要とする際にはいい選択肢でしょう。
#### AP - 可用性と分断耐性(availability and partition tolerance)
レスポンスは読み込み可能なデータの中で最も新しいものを返しますが、データが最新であるとは限りません。分断が解消された後も、書き込みが反映されるのには時間がかかります。
[結果整合性](#結果整合性) を求めるサービスの際にはAPを採用するのがいいでしょう。もしくは、外部エラーに関わらずシステムが稼働する必要がある際にも同様です。
### その他の参考資料、ページ
* [CAP 理論を振り返る](http://robertgreiner.com/2014/08/cap-theorem-revisited/)
* [平易な英語でのCAP 理論のイントロ](http://ksat.me/a-plain-english-introduction-to-cap-theorem)
* [CAP FAQ](https://github.com/henryr/cap-faq)
* [CAP 理論](https://www.youtube.com/watch?v=k-Yaq8AHlFA)
## 一貫性パターン
同じデータの複製が複数ある状態では、クライアントが一貫したデータ表示を受け取るために、どのようにそれらを同期すればいいのかという課題があります。 [CAP 理論](#cap-理論) における一貫性の定義を思い出してみましょう。全ての読み取りは最新の書き込みデータもしくはエラーを受け取るはずです。
### 弱い一貫性
書き込み後の読み取りでは、その最新の書き込みを読めたり読めなかったりする。ベストエフォート型のアプローチに基づく。
このアプローチはmemcachedなどのシステムに見られます。弱い一貫性はリアルタイム性が必要なユースケース、例えばVoIP、ビデオチャット、リアルタイムマルチプレイヤーゲームなどと相性がいいでしょう。例えば、電話に出ているときに数秒間音声が受け取れなくなったとしたら、その後に接続が回復してもその接続が切断されていた間に話されていたことは聞き取れないというような感じです。
### 結果整合性
書き込みの後、読み取りは最終的にはその結果を読み取ることができる(ミリ秒ほど遅れてというのが一般的です)。データは非同期的に複製されます。
このアプローチはDNSやメールシステムなどに採用されています。結果整合性は多くのリクエストを捌くサービスと相性がいいでしょう。
### 強い一貫性
書き込みの後、読み取りはそれを必ず読むことができます。データは同期的に複製されます。
このアプローチはファイルシステムやRDBMSなどで採用されています。トランザクションを扱うサービスでは強い一貫性が必要でしょう。
### その他の参考資料、ページ
* [データセンター間でのトランザクション](http://snarfed.org/transactions_across_datacenters_io.html)
## 可用性パターン
高い可用性を担保するには相補的な次の二つのパターンがあります: **フェイルオーバー****レプリケーション** です。
### フェイルオーバー
#### アクティブ・パッシブ
アクティブ・パッシブフェイルオーバーにおいては、周期信号はアクティブもしくはスタンバイ中のパッシブなサーバーに送られます。周期信号が中断された時には、パッシブだったサーバーがアクティブサーバーのIPアドレスを引き継いでサービスを再開します。
起動までのダウンタイムはパッシブサーバーが「ホット」なスタンバイ状態にあるか、「コールド」なスタンバイ状態にあるかで変わります。アクティブなサーバーのみがトラフィックを捌きます。
アクティブ・パッシブフェイルオーバーはマスター・スレーブフェイルオーバーと呼ばれることもあります。
#### アクティブ・アクティブ
アクティブアクティブ構成では両方のサーバーがトラフィックを捌くことで負荷を分散します。
これらのサーバーがパブリックなものの場合、DNSは両方のサーバーのパブリックIPを知っている必要があります。もし、プライベートなものな場合、アプリケーションロジックが両方のサーバーの情報について知っている必要があります。
アクティブ・アクティブなフェイルオーバーはマスター・マスターフェイルオーバーと呼ばれることもあります。
### 短所: フェイルオーバー
* フェイルオーバーではより多くのハードウェアを要し、複雑さが増します。
* 最新の書き込みがパッシブサーバーに複製される前にアクティブが落ちると、データ欠損が起きる潜在可能性があります。
### レプリケーション
#### マスター・スレーブ と マスター・マスター
このトピックは [データベース](#データベース) セクションにおいてより詳細に解説されています:
* [マスター・スレーブ レプリケーション](#マスタースレーブ-レプリケーション)
* [マスター・マスター レプリケーション](#マスターマスター-レプリケーション)
## ドメインネームシステム
<p align="center">
<img src="images/IOyLj4i.jpg">
<br/>
<i><a href=http://www.slideshare.net/srikrupa5/dns-security-presentation-issa>Source: DNS security presentation</a></i>
</p>
ドメインネームシステム (DNS) は www.example.com などのドメインネームをIPアドレスへと翻訳します。
DNSは少数のオーソライズされたサーバーが上位に位置する階層的構造です。あなたのルーターもしくはISPは検索をする際にどのDNSサーバーに接続するかという情報を提供します。低い階層のDNSサーバーはその経路マップをキャッシュします。ただ、この情報は伝搬遅延によって陳腐化する可能性があります。DNSの結果はあなたのブラウザもしくはOSに一定期間[time to live (TTL)](https://en.wikipedia.org/wiki/Time_to_live)に設定された期間)キャッシュされます。
* **NS record (name server)** - あなたのドメイン・サブドメインでのDNSサーバーを特定します。
* **MX record (mail exchange)** - メッセージを受け取るメールサーバーを特定します。
* **A record (address)** - IPアドレスに名前をつけます。
* **CNAME (canonical)** - 他の名前もしくは `CNAME` (example.com を www.example.com) もしくは `A` recordへと名前を指し示す。
[CloudFlare](https://www.cloudflare.com/dns/) や [Route 53](https://aws.amazon.com/route53/) などのサービスはマネージドDNSサービスを提供しています。いくつかのDNSサービスでは様々な手法を使ってトラフィックを捌くことができます:
* [加重ラウンドロビン](https://www.g33kinfo.com/info/round-robin-vs-weighted-round-robin-lb)
* トラフィックがメンテナンス中のサーバーに行くのを防ぎます
* 様々なクラスターサイズに応じて調整します
* A/B テスト
* レイテンシーベース
* 地理ベース
### 欠点: DNS
* 上記で示されているようなキャッシングによって緩和されているとはいえ、DNSサーバーへの接続には少し遅延が生じる。
* DNSサーバーは、[政府、ISP企業,そして大企業](http://superuser.com/questions/472695/who-controls-the-dns-servers/472729)に管理されているが、それらの管理は複雑である。
* DNSサービスは[DDoS attack](http://dyn.com/blog/dyn-analysis-summary-of-friday-october-21-attack/)の例で、IPアドレスなしにユーザーがTwitterなどにアクセスできなくなったように、攻撃を受ける可能性がある。
### その他の参考資料、ページ
* [DNS アーキテクチャ](https://technet.microsoft.com/en-us/library/dd197427(v=ws.10).aspx)
* [Wikipedia](https://en.wikipedia.org/wiki/Domain_Name_System)
* [DNS 記事](https://support.dnsimple.com/categories/dns/)
## コンテンツデリバリーネットワーク(Content delivery network)
<p align="center">
<img src="images/h9TAuGI.jpg">
<br/>
<i><a href=https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/>Source: Why use a CDN</a></i>
</p>
コンテンツデリバリーネットワーク(CDN)は世界中に配置されたプロキシサーバーのネットワークがユーザーに一番地理的に近いサーバーからコンテンツを配信するシステムのことです。AmazonのCloudFrontなどは例外的にダイナミックなコンテンツも配信しますが、一般的に、HTML/CSS/JS、写真、そして動画などの静的ファイルがCDNを通じて配信されます。そのサイトのDNSがクライアントにどのサーバーと交信するかという情報を伝えます。
CDNを用いてコンテンツを配信することで以下の二つの理由でパフォーマンスが劇的に向上します:
* ユーザーは近くにあるデータセンターから受信できる
* バックエンドサーバーはCDNが処理してくれるリクエストに関しては処理する必要がなくなります
### プッシュCDN
プッシュCDNではサーバーデータに更新があった時には必ず、新しいコンテンツを受け取る方式です。コンテンツを用意し、CDNに直接アップロードし、URLをCDNを指すように指定するところまで、全て自分で責任を負う形です。コンテンツがいつ期限切れになるのか更新されるのかを設定することができます。コンテンツは新規作成時、更新時のみアップロードされることでトラフィックは最小化される一方、ストレージは最大限消費されてしまいます。
トラフィックの少ない、もしくは頻繁にはコンテンツが更新されないサイトの場合にはプッシュCDNと相性がいいでしょう。コンテンツは定期的に再びプルされるのではなく、CDNに一度のみ配置されます。
### プルCDN
プルCDNでは一人目のユーザーがリクエストした時に、新しいコンテンツをサービスのサーバーから取得します。コンテンツは自分のサーバーに保存して、CDNを指すURLを書き換えます。結果として、CDNにコンテンツがキャッシュされるまではリクエスト処理が遅くなります。
[time-to-live (TTL)](https://en.wikipedia.org/wiki/Time_to_live) はコンテンツがどれだけの期間キャッシュされるかを規定します。プルCDNはCDN 上でのストレージスペースを最小化しますが、有効期限が切れたファイルが更新前にプルされてしまうことで冗長なトラフィックに繋がってしまう可能性があります。
大規模なトラフィックのあるサイトではプルCDNが相性がいいでしょう。というのも、トラフィックの大部分は最近リクエストされ、CDNに残っているコンテンツにアクセスするものであることが多いからです。
### 欠点: CDN
* CDNのコストはトラフィック量によって変わります。もちろん、CDNを使わない場合のコストと比較するべきでしょう。
* TTLが切れる前にコンテンツが更新されると陳腐化する恐れがあります。
* CDNでは静的コンテンツがCDNを指すようにURLを更新する必要があります。
### その他の参考資料、ページ
* [グローバルに分散されたコンテンツデリバリーネットワーク](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci)
* [プッシュCDNとプルCDNの違い](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)
* [Wikipedia](https://en.wikipedia.org/wiki/Content_delivery_network)
## ロードバランサー
<p align="center">
<img src="images/h81n9iK.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Source: Scalable system design patterns</a></i>
</p>
ロードバランサーは入力されるクライアントのリクエストをアプリケーションサーバーやデータベースへと分散させる。どのケースでもロードバランサーはサーバー等計算リソースからのレスポンスを適切なクライアントに返す。ロードバランサーは以下のことに効果的です:
* リクエストが状態の良くないサーバーに行くのを防ぐ
* リクエストを過剰に送るのを防ぐ
* 特定箇所の欠陥でサービスが落ちることを防ぐ
ロードバランサーは (費用の高い) ハードウェアもしくはHAProxyなどのソフトウェアで実現できる。
他の利点としては:
* **SSL termination** - 入力されるリクエストを解読する、また、サーバーレスポンスを暗号化することでバックエンドのサーバーがこのコストが高くつきがちな処理を請け負わなくていいように肩代わりします。
* [X.509 certificates](https://en.wikipedia.org/wiki/X.509) をそれぞれのサーバーにインストールする必要をなくします
* **セッション管理** - クッキーを取り扱うウェブアプリがセッション情報を保持していない時などに、特定のクライアントのリクエストを同じインスタンスへと流します。
障害に対応するために、[アクティブ・パッシブ](#アクティブパッシブ) もしくは [アクティブ・アクティブ](#アクティブアクティブ) モードのどちらにおいても、複数のロードバランサーを配置するのが一般的です。
ロードバランサーは以下のような種々のメトリックを用いてトラフィックルーティングを行うことができます:
* ランダム
* Least loaded
* セッション/クッキー
* [ラウンドロビンもしくは加重ラウンドロビン](https://www.g33kinfo.com/info/round-robin-vs-weighted-round-robin-lb)
* [Layer 4](#layer-4-ロードバランシング)
* [Layer 7](#layer-7-ロードバランシング)
### Layer 4 ロードバランシング
Layer 4 ロードバランサーは [トランスポートレイヤー](#通信) を参照してどのようにリクエストを配分するか判断します。一般的に、トランスポートレイヤーとしては、ソース、送信先IPアドレス、ヘッダーに記述されたポート番号が含まれますが、パケットの中身のコンテンツは含みません。 Layer 4 ロードバランサーはネットワークパケットを上流サーバーへ届け、上流サーバーから配信することでネットワークアドレス変換 [Network Address Translation (NAT)](https://www.geeksforgeeks.org/network-address-translation-nat/) を実現します。
### Layer 7 ロードバランシング
Layer 7 ロードバランサーは [アプリケーションレイヤー](#通信) を参照してどのようにリクエストを配分するか判断します。ヘッダー、メッセージ、クッキーなどのコンテンツのことです。Layer 7 ロードバランサーはネットワークトラフィックの終端を受け持ち メッセージを読み込み、ロードバランシングの判断をし、選択したサーバーとの接続を繋ぎます。例えば layer 7 ロードバランサーは動画のトラフィックを直接、そのデータをホストしているサーバーにつなぐと同時に、決済処理などのより繊細なトラフィックをセキュリティ強化されたサーバーに流すということもできる。
柔軟性とのトレードオフになりますが、 layer 4 ロードバランサーではLayer 7ロードバランサーよりも所要時間、計算リソースを少なく済ませることができます。ただし、昨今の汎用ハードウェアではパフォーマンスは最小限のみしか発揮できないでしょう。
### 水平スケーリング
ロードバランサーでは水平スケーリングによってパフォーマンスと可用性を向上させることができます。手頃な汎用マシンを追加することによってスケールアウトさせる方が、一つのサーバーをより高価なマシンにスケールアップする(**垂直スケーリング**)より費用対効果も高くなり、結果的に可用性も高くなります。また、汎用ハードウェアを扱える人材を雇う方が、特化型の商用ハードウェアを扱える人材を雇うよりも簡単でしょう。
#### 欠点: 水平スケーリング
* 水平的にスケーリングしていくと、複雑さが増す上に、サーバーのクローニングが必要になる。
* サーバーはステートレスである必要がある: ユーザーに関連するセッションや、プロフィール写真などのデータを持ってはいけない
* セッションは一元的な[データベース](#データベース) (SQL、 NoSQL)などのデータストアにストアされるか [キャッシュ](#キャッシュ) (Redis、 Memcached)に残す必要があります。
* キャッシュやデータベースなどの下流サーバーは上流サーバーがスケールアウトするにつれてより多くの同時接続を保たなければなりません。
### 欠点: ロードバランサー
* ロードバランサーはリソースが不足していたり、設定が適切でない場合、システム全体のボトルネックになる可能性があります。
* 単一障害点を除こうとしてロードバランサーを導入した結果、複雑さが増してしまうことになります。
* ロードバランサーが一つだけだとそこが単一障害点になってしまいます。一方で、ロードバランサーを複数にすると、さらに複雑さが増してしまいます。
### その他の参考資料、ページ
* [NGINX アーキテクチャ](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy アーキテクチャガイド](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [スケーラビリティ](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [Wikipedia](https://en.wikipedia.org/wiki/Load_balancing_(computing))
* [Layer 4 ロードバランシング](https://www.nginx.com/resources/glossary/layer-4-load-balancing/)
* [Layer 7 ロードバランシング](https://www.nginx.com/resources/glossary/layer-7-load-balancing/)
* [ELB listener config](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html)
## リバースプロキシ(webサーバー)
<p align="center">
<img src="images/n41Azff.png">
<br/>
<i><a href=https://upload.wikimedia.org/wikipedia/commons/6/67/Reverse_proxy_h2g2bob.svg>Source: Wikipedia</a></i>
<br/>
</p>
リバースプロキシサーバーは内部サービスをまとめて外部に統一されたインターフェースを提供するウェブサーバーです。クライアントからのリクエストはそれに対応するサーバーに送られて、その後レスポンスをリバースプロキシがクライアントに返します。
他には以下のような利点があります:
* **より堅牢なセキュリティ** - バックエンドサーバーの情報を隠したり、IPアドレスをブラックリスト化したり、クライアントごとの接続数を制限したりできます。
* **スケーラビリティや柔軟性が増します** - クライアントはリバースプロキシのIPしか見ないので、裏でサーバーをスケールしたり、設定を変えやすくなります。
* **SSL termination** - 入力されるリクエストを解読し、サーバーのレスポンスを暗号化することでサーバーがこのコストのかかりうる処理をしなくて済むようになります。
* [X.509 証明書](https://en.wikipedia.org/wiki/X.509) を各サーバーにインストールする必要がなくなります。
* **圧縮** - サーバーレスポンスを圧縮できます
* **キャッシング** - キャッシュされたリクエストに対して、レスポンスを返します
* **静的コンテンツ** - 静的コンテンツを直接送信することができます。
* HTML/CSS/JS
* 写真
* 動画
* などなど
### ロードバランサー vs リバースプロキシ
* 複数のサーバーがある時にはロードバランサーをデプロイすると役に立つでしょう。 しばしば、ロードバランサーは同じ機能を果たすサーバー群へのトラフィックを捌きます。
* リバースプロキシでは、上記に述べたような利点を、単一のウェブサーバーやアプリケーションレイヤーに対しても示すことができます。
* NGINX や HAProxy などの技術はlayer 7 リバースプロキシとロードバランサーの両方をサポートします。
### 欠点: リバースプロキシ
* リバースプロキシを導入するとシステムの複雑性が増します。
* 単一のリバースプロキシは単一障害点になりえます。一方で、複数のリバースプロキシを導入すると(例: [フェイルオーバー](https://en.wikipedia.org/wiki/Failover)) 複雑性はより増します。
### その他の参考資料、ページ
* [リバースプロキシ vs ロードバランサー](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)
* [NGINX アーキテクチャ](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy アーキテクチャ ガイド](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [Wikipedia](https://en.wikipedia.org/wiki/Reverse_proxy)
## アプリケーション層
<p align="center">
<img src="images/yB5SYwm.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Source: Intro to architecting systems for scale</a></i>
</p>
ウェブレイヤーをアプリケーション層 (プラットフォーム層とも言われる) と分離することでそれぞれの層を独立にスケール、設定することができるようになります。新しいAPIをアプリケーション層に追加する際に、不必要にウェブサーバーを追加する必要がなくなります。
**単一責任の原則** では、小さい自律的なサービスが協調して動くように提唱しています。小さいサービスの小さいチームが急成長のためにより積極的な計画を立てられるようにするためです。
アプリケーション層は[非同期処理](#非同期処理)もサポートします。
### マイクロサービス
独立してデプロイできる、小規模なモジュール様式である[マイクロサービス](https://en.wikipedia.org/wiki/Microservices)もこの議論に関係してくる技術でしょう。それぞれのサービスは独自のプロセスを処理し、明確で軽量なメカニズムで通信して、その目的とする機能を実現します。<sup><a href=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
例えばPinterestでは以下のようなマイクロサービスに分かれています。ユーザープロフィール、フォロワー、フィード、検索、写真アップロードなどです。
### サービスディスカバリー
[Consul](https://www.consul.io/docs/index.html)、 [Etcd](https://coreos.com/etcd/docs/latest)、 [Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) などのシステムでは、登録されているサービスの名前、アドレス、ポートの情報を監視することで、サービス同士が互いを見つけやすくしています。サービスの完全性の確認には [Health checks](https://www.consul.io/intro/getting-started/checks.html) が便利で、これには [HTTP](#hypertext-transfer-protocol-http) エンドポイントがよく使われます。 Consul と Etcd のいずれも組み込みの [key-value store](#キーバリューストア) を持っており、設定データや共有データなどのデータを保存しておくことに使われます。
### 欠点: アプリケーション層
* アーキテクチャ、運用、そしてプロセスを考慮すると、緩く結び付けられたアプリケーション層を追加するには、モノリシックなシステムとは異なるアプローチが必要です。
* マイクロサービスはデプロイと運用の点から見ると複雑性が増すことになります。
### その他の参考資料、ページ
* [スケールするシステムアーキテクチャを設計するためのイントロ](http://lethain.com/introduction-to-architecting-systems-for-scale)
* [システム設計インタビューを紐解く](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [サービス指向アーキテクチャ](https://en.wikipedia.org/wiki/Service-oriented_architecture)
* [Zookeeperのイントロダクション](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper)
* [マイクロサービスを作るために知っておきたいこと](https://cloudncode.wordpress.com/2016/07/22/msa-getting-started/)
## データベース
<p align="center">
<img src="images/Xkm5CXz.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>Source: Scaling up to your first 10 million users</a></i>
</p>
### リレーショナルデータベースマネジメントシステム (RDBMS)
SQLなどのリレーショナルデータベースはテーブルに整理されたデータの集合である。
**ACID** はリレーショナルデータベースにおける[トランザクション](https://en.wikipedia.org/wiki/Database_transaction)のプロパティの集合である
* **不可分性** - それぞれのトランザクションはあるかないかのいずれかである
* **一貫性** - どんなトランザクションもデータベースをある確かな状態から次の状態に遷移させる。
* **独立性** - 同時にトランザクションを処理することは、連続的にトランザクションを処理するのと同じ結果をもたらす。
* **永続性** - トランザクションが処理されたら、そのように保存される
リレーショナルデータベースをスケールさせるためにはたくさんの技術がある: **マスター・スレーブ レプリケーション****マスター・マスター レプリケーション****federation****シャーディング****非正規化**、 そして **SQL チューニング**
#### マスタースレーブ レプリケーション
マスターデータベースが読み取りと書き込みを処理し、書き込みを一つ以上のスレーブデータベースに複製します。スレーブデータベースは読み取りのみを処理します。スレーブデータベースは木構造のように追加のスレーブにデータを複製することもできます。マスターデータベースがオフラインになった場合には、いずれかのスレーブがマスターに昇格するか、新しいマスターデータベースが追加されるまでは読み取り専用モードで稼働します。
<p align="center">
<img src="images/C9ioGtn.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
##### 欠点: マスタースレーブ レプリケーション
* スレーブをマスターに昇格させるには追加のロジックが必要になる。
* マスタースレーブ レプリケーション、マスターマスター レプリケーションの **両方** の欠点は[欠点: レプリケーション](#欠点-マスタースレーブ-レプリケーション)を参照
#### マスターマスター レプリケーション
いずれのマスターも読み取り書き込みの両方に対応する。書き込みに関してはそれぞれ協調する。いずれかのマスターが落ちても、システム全体としては読み書き両方に対応したまま運用できる。
<p align="center">
<img src="images/krAHLGg.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
##### 欠点: マスターマスター レプリケーション
* ロードバランサーを導入するか、アプリケーションロジックを変更することでどこに書き込むかを指定しなければならない。
* 大体のマスターマスターシステムは、一貫性が緩いACID原理を守っていないもしくは、同期する時間がかかるために書き込みのレイテンシーが増加してしまっている。
* 書き込みノードが追加され、レイテンシーが増加するにつれ書き込みの衝突の可能性が増える。
* マスタースレーブ レプリケーション、マスターマスター レプリケーションの **両方** の欠点は[欠点: レプリケーション](#欠点-マスタースレーブ-レプリケーション) を参照
##### 欠点: レプリケーション
* 新しいデータ書き込みを複製する前にマスターが落ちた場合にはそのデータが失われてしまう可能性がある。
* 書き込みは読み取りレプリカにおいてリプレイされる。書き込みが多い場合、複製ノードが書き込みの処理のみで行き詰まって、読み取りの処理を満足に行えない可能性がある。
* 読み取りスレーブノードの数が多ければ多いほど、複製しなければならない数も増え、複製時間が伸びてしまいます。
* システムによっては、マスターへの書き込みはマルチスレッドで並列処理できる一方、スレーブへの複製は単一スレッドで連続的に処理しなければならない場合があります。
* レプリケーションでは追加のハードウェアが必要になり、複雑性も増します。
##### その他の参考資料、ページ: レプリケーション
* [スケーラビリティ、 可用性、 スタビリティ パターン](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [マルチマスター レプリケーション](https://en.wikipedia.org/wiki/Multi-master_replication)
#### Federation
<p align="center">
<img src="images/U3qV33e.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>Source: Scaling up to your first 10 million users</a></i>
</p>
フェデレーション (もしくは機能分割化とも言う) はデータベースを機能ごとに分割する。例えば、モノリシックな単一データベースの代わりに、データベースを **フォーラム****ユーザー****プロダクト** のように三つにすることで、データベース一つあたりの書き込み・読み取りのトラフィックが減り、その結果レプリケーションのラグも短くなります。データベースが小さくなることで、メモリーに収まるデータが増えます。キャッシュの局所性が高まるため、キャッシュヒット率も上がります。単一の中央マスターで書き込みを直列化したりしないため、並列で書き込みを処理することができ、スループットの向上が期待できます。
##### 欠点: federation
* 大規模な処理やテーブルを要するスキーマの場合、フェデレーションは効果的とは言えないでしょう。
* どのデータベースに読み書きをするのかを指定するアプリケーションロジックを更新しなければなりません。
* [server link](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers)で二つのデータベースからのデータを連結するのはより複雑になるでしょう。
* フェデレーションでは追加のハードウェアが必要になり、複雑性も増します。
##### その他の参考資料、ページ: federation
* [Scaling up to your first 10 million users](https://www.youtube.com/watch?v=kKjm4ehYiMs)
#### シャーディング
<p align="center">
<img src="images/wU8x5Id.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
シャーディングでは異なるデータベースにそれぞれがデータのサブセット断片のみを持つようにデータを分割します。ユーザーデータベースを例にとると、ユーザー数が増えるにつれてクラスターにはより多くの断片が加えられることになります。
[federation](#federation)の利点に似ていて、シャーディングでは読み書きのトラフィックを減らし、レプリケーションを減らし、キャッシュヒットを増やすことができます。インデックスサイズも減らすことができます。一般的にはインデックスサイズを減らすと、パフォーマンスが向上しクエリ速度が速くなります。なにがしかのデータを複製する機能がなければデータロスにつながりますが、もし、一つのシャードが落ちても、他のシャードが動いていることになります。フェデレーションと同じく、単一の中央マスターが書き込みの処理をしなくても、並列で書き込みを処理することができ、スループットの向上が期待できます。
ユーザーテーブルをシャードする一般的な方法は、ユーザーのラストネームイニシャルでシャードするか、ユーザーの地理的配置でシャードするなどです。
##### 欠点: シャーディング
* シャードに対応するようにアプリケーションロジックを変更しなければなりません。結果としてSQLクエリが複雑になります。
* シャードではデータ配分がいびつになってしまう可能性があります。例えば、標準ユーザーの集合を持つシャードがある場合、そのシャードが他のシャードよりも重い負荷を負うことになります。
* リバランシングをすると複雑性がより増します。[consistent hashing](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html) に基づいたシャーディングでは、通信データを削減することもできます。
* 複数のシャードからのデータを連結するのはより複雑です。
* シャーディングでは追加のハードウェアが必要になり、複雑性も増します。
##### その他の参考資料、ページ: シャーディング
* [シャードの登場](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)
* [シャードデータベースアーキテクチャ](https://en.wikipedia.org/wiki/Shard_(database_architecture))
* [Consistent hashing](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)
#### 非正規化
非正規化では、書き込みのパフォーマンスをいくらか犠牲にして読み込みのパフォーマンスを向上させようとします。計算的に重いテーブルの結合などをせずに、複数のテーブルに冗長なデータのコピーが書き込まれるのを許容します。いくつかのRDBMS例えば、[PostgreSQL](https://en.wikipedia.org/wiki/PostgreSQL) やOracleはこの冗長な情報を取り扱い、一貫性を保つための[materialized views](https://en.wikipedia.org/wiki/Materialized_view) という機能をサポートしています。
[フェデレーション](#federation) や [シャーディング](#シャーディング)などのテクニックによってそれぞれのデータセンターに分配されたデータを合一させることはとても複雑な作業です。非正規化によってそのような複雑な処理をしなくて済むようになります。
多くのシステムで、100対1あるいは1000対1くらいになるくらい読み取りの方が、書き込みのトラフィックよりも多いことでしょう。読み込みを行うために、複雑なデータベースのジョイン処理が含まれるものは計算的に高価につきますし、ディスクの処理時間で膨大な時間を費消してしまうことになります。
##### 欠点: 非正規化
* データが複製される。
* 冗長なデータの複製が同期されるように制約が存在し、そのことでデータベース全体の設計が複雑化する。
* 非正規化されたデータベースは過大な書き込みを処理しなければならない場合、正規化されているそれよりもパフォーマンスにおいて劣る可能性がある。
###### その他の参考資料、ページ: 非正規化
* [Denormalization](https://en.wikipedia.org/wiki/Denormalization)
#### SQLチューニング
SQLチューニングは広範な知識を必要とする分野で多くの [](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning) が書かれています。
ボトルネックを明らかにし、シミュレートする上で、 **ベンチマーク** を定め、 **プロファイル** することはとても重要です。
* **ベンチマーク** - [ab](http://httpd.apache.org/docs/2.2/programs/ab.html)などのツールを用いて、高負荷の状況をシミュレーションしてみましょう。
* **プロファイル** - [slow query log](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html) などのツールを用いて、パフォーマンス状況の確認をしましょう。
ベンチマークとプロファイルをとることで以下のような効率化の選択肢をとることになるでしょう。
##### スキーマを絞る
* MySQLはアクセス速度向上のため、ディスク上の連続したブロックへデータを格納しています。
* 長さの決まったフィールドに対しては `VARCHAR` よりも `CHAR` を使うようにしましょう。
* `CHAR` の方が効率的に速くランダムにデータにアクセスできます。 一方、 `VARCHAR` では次のデータに移る前にデータの末尾を検知しなければならないために速度が犠牲になります。
* ブログの投稿など、大きなテキストには TEXT を使いましょう。 TEXT ではブーリアン型の検索も可能です。 TEXT フィールドには、テキストブロックが配置されている、ディスク上の場所へのポインターが保存されます。
* 2の32乗や40億以下を超えない程度の大きな数には INT を使いましょう。
* 通貨に関しては小数点表示上のエラーを避けるために `DECIMAL` を使いましょう。
* 大きな `BLOBS` を保存するのは避けましょう。どこからそのオブジェクトを取ってくることができるかの情報を保存しましょう。
* `VARCHAR(255)` は8ビットで数えられる最大の文字数です。一部のDBMSでは、1バイトの利用効率を最大化するためにこの文字数がよく使われます。
* [検索性能向上のため](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search) 、可能であれば `NOT NULL` 制約を設定しましょう。
##### インデックスを効果的に用いる
* クエリ(`SELECT``GROUP BY``ORDER BY``JOIN`) の対象となる列にインデックスを使うことで速度を向上できるかもしれません。
* インデックスは通常、平衡探索木である[B木](https://en.wikipedia.org/wiki/B-tree)の形で表されます。B木によりデータは常にソートされた状態になります。また検索、順次アクセス、挿入、削除を対数時間で行えます。
* インデックスを配置することはデータをメモリーに残すことにつながりより容量を必要とします。
* インデックスの更新も必要になるため書き込みも遅くなります。
* 大量のデータをロードする際には、インデックスを切ってからデータをロードして再びインデックスをビルドした方が速いことがあります。
##### 高負荷なジョインを避ける
* パフォーマンス上必要なところには[非正規化](#非正規化)を適用する
##### テーブルのパーティション
* テーブルを分割し、ホットスポットを独立したテーブルに分離してメモリーに乗せられるようにする。
##### クエリキャッシュを調整する
* 場合によっては[クエリキャッシュ](http://dev.mysql.com/doc/refman/5.7/en/query-cache) が[パフォーマンス問題](https://www.percona.com/blog/2014/01/28/10-mysql-performance-tuning-settings-after-installation/) を引き起こす可能性がある
##### その他の参考資料、ページ: SQLチューニング
* [MySQLクエリを最適化するためのTips](http://20bits.com/article/10-tips-for-optimizing-mysql-queries-that-dont-suck)
* [VARCHAR(255)をやたらよく見かけるのはなんで?](http://stackoverflow.com/questions/1217466/is-there-a-good-reason-i-see-varchar255-used-so-often-as-opposed-to-another-l)
* [null値はどのようにパフォーマンスに影響するのか](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)
* [Slow query log](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)
### NoSQL
NoSQL は **key-value store****document-store****wide column store**、 もしくは **graph database**によって表現されるデータアイテムの集合です。データは一般的に正規化されておらず、アプリケーション側でジョインが行われます。大部分のNoSQLは真のACIDトランザクションを持たず、 [結果整合性](#結果整合性) 的な振る舞いの方を好みます。
**BASE** はしばしばNoSQLデータベースのプロパティを説明するために用いられます。[CAP Theorem](#cap-理論) と対照的に、BASEは一貫性よりも可用性を優先します。
* **Basically available** - システムは可用性を保証します。
* **Soft state** - システムの状態は入力がなくても時間経過とともに変化する可能性があります。
* **結果整合性** - システム全体は時間経過とともにその間に入力がないという前提のもと、一貫性が達成されます。
[SQLかNoSQLか](#sqlかnosqlか) を選択するのに加えて、どのタイプのNoSQLがどの使用例に最も適するかを理解するのはとても有益です。このセクションでは **キーバリューストア****ドキュメントストア****ワイドカラムストア**、 と **グラフデータベース** について触れていきます。
#### キーバリューストア
> 概要: ハッシュテーブル
キーバリューストアでは一般的にO(1)の読み書きができ、それらはメモリないしSSDで裏付けられています。データストアはキーを [辞書的順序](https://en.wikipedia.org/wiki/Lexicographical_order) で保持することでキーの効率的な取得を可能にしています。キーバリューストアではメタデータを値とともに保持することが可能です。
キーバリューストアはハイパフォーマンスな挙動が可能で、単純なデータモデルやインメモリーキャッシュレイヤーなどのデータが急速に変わる場合などに使われます。単純な処理のみに機能が制限されているので、追加の処理機能が必要な場合にはその複雑性はアプリケーション層に載せることになります。
キーバリューストアはもっと複雑なドキュメントストアや、グラフデータベースなどの基本です。
##### その他の参考資料、ページ: キーバリューストア
* [キーバリューデータベース](https://en.wikipedia.org/wiki/Key-value_database)
* [キーバリューストアの欠点](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
* [Redisアーキテクチャ](http://qnimate.com/overview-of-redis-architecture/)
* [メムキャッシュアーキテクチャ](https://adayinthelifeof.nl/2011/02/06/memcache-internals/)
#### ドキュメントストア
> 概要: ドキュメントがバリューとして保存されたキーバリューストア
ドキュメントストアはオブジェクトに関する全ての情報を持つドキュメント(XML、 JSON、 binaryなど)を中心に据えたシステムです。ドキュメントストアでは、ドキュメント自身の内部構造に基づいた、APIもしくはクエリ言語を提供します。 *メモ:多くのキーバリューストアでは、値のメタデータを扱う機能を含んでいますが、そのことによって二つドキュメントストアとの境界線が曖昧になってしまっています。*
以上のことを実現するために、ドキュメントはコレクション、タグ、メタデータやディレクトリなどとして整理されています。ドキュメント同士はまとめてグループにできるものの、それぞれで全く異なるフィールドを持つ可能性があります。
[MongoDB](https://www.mongodb.com/mongodb-architecture) や [CouchDB](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/) などのドキュメントストアも、複雑なクエリを処理するためのSQLのような言語を提供しています。[DynamoDB](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) はキーバリューとドキュメントの両方をサポートしています。
ドキュメントストアは高い柔軟性を担保するので、頻繁に変化するデータを扱う時に用いられます。
##### その他の参考資料、ページ: ドキュメントストア
* [ドキュメント指向 データベース](https://en.wikipedia.org/wiki/Document-oriented_database)
* [MongoDB アーキテクチャ](https://www.mongodb.com/mongodb-architecture)
* [CouchDB アーキテクチャ](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/)
* [Elasticsearch アーキテクチャ](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)
#### ワイドカラムストア
<p align="center">
<img src="images/n16iOGk.png">
<br/>
<i><a href=http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html>Source: SQL & NoSQL, a brief history</a></i>
</p>
> 概要: ネストされたマップ `カラムファミリー<行キー、 カラム<ColKey、 Value、 Timestamp>>`
ワイドカラムストアのデータの基本単位はカラムネーム・バリューのペアです。それぞれのカラムはカラムファミリーとしてSQLテーブルのようにグループ化することができます。スーパーカラムファミリーはカラムファミリーの集合です。それぞれのカラムには行キーでアクセスすることができます。同じ行キーを持つカラムは同じ行として認識されます。それぞれの値は、バージョン管理とコンフリクトが起きた時のために、タイムスタンプを含みます。
Googleは[Bigtable](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)を初のワイドカラムストアとして発表しました。それがオープンソースでHadoopなどでよく使われる[HBase](https://www.mapr.com/blog/in-depth-look-hbase-architecture) やFacebookによる[Cassandra](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html) などのプロジェクトに影響を与えました。BigTable、HBaseやCassandraなどのストアはキーを辞書形式で保持することで選択したキーレンジでのデータ取得を効率的にします。
ワイドカラムストアは高い可用性とスケーラビリティを担保します。これらはとても大規模なデータセットを扱うことによく使われます。
##### その他の参考資料、ページ: ワイドカラムストア
* [SQL & NoSQL簡単に歴史をさらう](http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html)
* [Bigtable アーキテクチャ](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)
* [HBase アーキテクチャ](https://www.mapr.com/blog/in-depth-look-hbase-architecture)
* [Cassandra アーキテクチャ](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html)
#### グラフデータベース
<p align="center">
<img src="images/fNcl65g.png">
<br/>
<i><a href=https://en.wikipedia.org/wiki/File:GraphDatabase_PropertyGraph.png>Source: Graph database</a></i>
</p>
> 概要: グラフ
グラフデータベースでは、それぞれのノードがレコードで、それぞれのアークは二つのノードを繋ぐ関係性として定義されます。グラフデータベースは多数の外部キーや多対多などの複雑な関係性を表すのに最適です。
グラフデータベースはSNSなどのサービスの複雑な関係性モデルなどについて高いパフォーマンスを発揮します。比較的新しく、まだ一般的には用いられていないので、開発ツールやリソースを探すのが他の方法に比べて難しいかもしれません。多くのグラフは[REST APIs](#representational-state-transfer-rest)を通じてのみアクセスできます。
##### その他の参考資料、ページ: グラフ
* [Graphデータベース](https://en.wikipedia.org/wiki/Graph_database)
* [Neo4j](https://neo4j.com/)
* [FlockDB](https://blog.twitter.com/2010/introducing-flockdb)
#### その他の参考資料、ページ: NoSQL
* [基本用語の説明](http://stackoverflow.com/questions/3342497/explanation-of-base-terminology)
* [NoSQLデータベースについて調査と選択ガイド](https://medium.com/baqend-blog/nosql-databases-a-survey-and-decision-guidance-ea7823a822d#.wskogqenq)
* [スケーラビリティ](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [NoSQLのイントロダクション](https://www.youtube.com/watch?v=qI_g07C_Q5I)
* [NoSQLパターン](http://horicky.blogspot.com/2009/11/nosql-patterns.html)
### SQLかNoSQLか
<p align="center">
<img src="images/wXGqG5f.png">
<br/>
<i><a href=https://www.infoq.com/articles/Transition-RDBMS-NoSQL/>Source: Transitioning from RDBMS to NoSQL</a></i>
</p>
**SQL** を選ぶ理由:
* 構造化されたデータ
* 厳格なスキーマ
* リレーショナルデータ
* 複雑なジョインをする必要性
* トランザクション
* スケールする際のパターンが明確なとき
* 開発者の数、コミュニティ、コード等がより充実している
* インデックスによるデータ探索はとても速い
**NoSQL** を選ぶ理由:
* 準構造化されたデータ
* ダイナミックないし、フレキシブルなスキーマ
* ノンリレーショナルなデータ
* 複雑なジョインをする必要がない
* データの多くのTB (もしくは PB) を保存する
* 集中的、大規模なデータ負荷に耐えられる
* IOPSについては極めて高いスループットを示す
NoSQLに適するサンプルデータ:
* 急激なクリックストリームやログデータの収集
* リーダーボードやスコアリングデータ
* ショッピングカートなどの一時的情報
* 頻繁にアクセスされる ('ホットな') テーブル
* メタデータやルックアップテーブル
##### その他の参考資料、ページ:  SQLもしくはNoSQL
* [最初の1000万ユーザーにスケールアップするために](https://www.youtube.com/watch?v=kKjm4ehYiMs)
* [SQLとNoSQLの違い](https://www.sitepoint.com/sql-vs-nosql-differences/)
## キャッシュ
<p align="center">
<img src="images/Q6z24La.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Source: Scalable system design patterns</a></i>
</p>
キャッシュはページの読み込み時間を削減し、サーバーやデータベースへの負荷を低減することができます。このモデルでは、実際の処理を保存するために、ディスパッチャーがまず以前にリクエストが送信されたかどうかを確認し、直前の結果を受け取ります。
データベースはそのパーティションに渡って統合された読み取り書き込みの分配を要求しますが、人気アイテムはその分配を歪めてシステム全体のボトルネックになってしまうことがあります。データベースの前にキャッシュを差し込むことでこのように、均一でない負荷やトラフィックの急激な増加を吸収することができます。
### クライアントキャッシング
キャッシュはOSやブラウザーなどのクライアントサイド、[サーバーサイド](#リバースプロキシwebサーバー) もしくは独立のキャッシュレイヤーに設置することができます。
### CDNキャッシング
[CDN](#コンテンツデリバリーネットワークcontent-delivery-network) もキャッシュの一つとして考えることができます。
### Webサーバーキャッシング
[リバースプロキシ](#リバースプロキシwebサーバー) や [Varnish](https://www.varnish-cache.org/) などのキャッシュは静的そして動的なコンテンツを直接配信することができます。 webサーバーもリクエストをキャッシュしてアプリケーションサーバーに接続することなしにレスポンスを返すことができます。
### データベースキャッシング
データベースは普通、一般的な使用状況に適するようなキャッシングの設定を初期状態で持っています。この設定を特定の仕様に合わせて調整することでパフォーマンスを向上させることができます。
### アプリケーションキャッシング
メムキャッシュなどのIn-memoryキャッシュやRedisはアプリケーションとデータストレージの間のキーバリューストアです。データはRAMで保持されるため、データがディスクで保存される一般的なデータベースよりもだいぶ速いです。RAM容量はディスクよりも限られているので、[least recently used (LRU)](https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used)などの[cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms) アルゴリズムが 'コールド' なエントリを弾き、'ホット' なデータをRAMに保存します。
Redisはさらに以下のような機能を備えています:
* パージステンス設定
* ソート済みセット、リストなどの組み込みデータ構造
キャッシュには様々なレベルのものがありますが、いずれも大きく二つのカテゴリーのいずれかに分類することができます: **データベースクエリ****オブジェクト** です:
* 行レベル
* クエリレベル
* Fully-formed serializable objects
* Fully-rendered HTML
一般的に、ファイルベースキャッシングはクローンを作り出してオートスケーリングを難しくしてしまうので避けるべきです。
### データベースクエリレベルでのキャッシング
データベースをクエリする際には必ずクエリをキーとしてハッシュして結果をキャッシュに保存しましょう。この手法はキャッシュ期限切れ問題に悩むことになります:
* 複雑なクエリによりキャッシュされた結果を削除することが困難
* テーブルセルなどのデータ断片が変化した時に、その変化したセルを含むかもしれない全てのキャッシュされたクエリを削除する必要がある。
### オブジェクトレベルでのキャッシング
データをアプリケーションコードでそうするように、オブジェクトとして捉えてみましょう。アプリケーションに、データベースからのデータセットをクラスインスタンスやデータ構造として組み立てさせます。:
* そのデータが変更されたら、オブジェクトをキャッシュから削除すること
* 非同期処理を許容します: ワーカーがキャッシュされたオブジェクトの中で最新のものを集めてきます
何をキャッシュするか:
* ユーザーのセッション
* 完全にレンダーされたウェブページ
* アクテビティストリーム
* ユーザーグラフデータ
### いつキャッシュを更新するか
キャッシュに保存できる容量は限られているため、自分のケースではどのキャッシュ手法が一番いいかは検討する必要があります。
#### キャッシュアサイド
<p align="center">
<img src="images/ONjORqk.png">
<br/>
<i><a href=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>
アプリケーションはストレージへの読み書きの処理をします。キャッシュはストレージとは直接やりとりをしません。アプリケーションは以下のことをします:
* キャッシュの中のエントリを参照しますが、結果としてキャッシュミスになります
* データベースからエントリを取得します
* エントリをキャッシュに追加します
* エントリを返します
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
[Memcached](https://memcached.org/) は通常このように使われる。
その後のキャッシュデータ読み込みは速いです。キャッシュアサイドはレージーローディングであるとも言われます。リクエストされたデータのみがキャッシュされ、リクエストされていないデータでキャッシュが溢れるのを防止します。
##### 欠点: キャッシュアサイド
* 各キャッシュミスは三つのトリップを呼び出すことになり、体感できるほどの遅延が起きてしまいます。
* データベースのデータが更新されるとキャッシュデータは古いものになってしまいます。time-to-live (TTL)を設定することでキャッシュエントリの更新を強制的に行う、もしくはライトスルーを採用することでこの問題は緩和できます。
* ノードが落ちると、新規の空のノードで代替されることでレイテンシーが増加することになります。
#### ライトスルー
<p align="center">
<img src="images/0vBc0hN.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
アプリケーションはキャッシュをメインのデータストアとして使い、そこにデータの読み書きを行います。一方、キャッシュはデータベースへの読み書きを担当します。
* アプリケーションはキャッシュにあるエントリを追加・更新します
* キャッシュは同期的にデータストアに書き込みを行います
* エントリを返します
アプリケーションコード:
```
set_user(12345, {"foo":"bar"})
```
キャッシュコード:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
ライトスルーは書き込み処理のせいで全体としては遅いオペレーションですが、書き込まれたばかりのデータに関する読み込みは速いです。ユーザー側は一般的にデータ更新時の方が読み込み時よりもレイテンシーに許容的です。キャッシュ内のデータは最新版で保たれます。
##### 欠点: ライトスルー
* ノードが落ちたこと、もしくはスケーリングによって新しいノードが作成された時に、新しいノードはデータベース内のエントリーが更新されるまではエントリーをキャッシュしません。キャッシュアサイドとライトスルーを併用することでこの問題を緩和できます。
* 書き込まれたデータの大部分は一度も読み込まれることはありません。このデータはTTLによって圧縮することができます。
#### ライトビハインド (ライトバック)
<p align="center">
<img src="images/rgSrvjG.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
ライトビハインドではアプリケーションは以下のことをします:
* キャッシュのエントリーを追加・更新します
* データストアへの書き込みを非同期的に行うことで、書き込みパフォーマンスを向上させます。
##### 欠点: ライトビハインド
* キャッシュがデータストア内のコンテンツにヒットする前にキャッシュが落ちるとデータ欠損が起きる可能性があります。
* キャッシュアサイドやライトスルーよりも実装が複雑になります。
#### リフレッシュアヘッド
<p align="center">
<img src="images/kxtjqgE.png">
<br/>
<i><a href=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>
期限切れよりも前に、直近でアクセスされた全てのキャッシュエントリを自動的に更新するように設定することができます。
もしどのアイテムが将来必要になるのかを正確に予測することができるのならば、リードスルーよりもレイテンシーを削減することができます。
##### 欠点: リフレッシュアヘッド
* どのアイテムが必要になるかの予測が正確でない場合にはリフレッシュアヘッドがない方がレイテンシーは良いという結果になってしまいます。
### 欠点: キャッシュ
* [cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms)などを用いて、データベースなどの真のデータとキャッシュの間の一貫性を保つ必要があります。
* Redisやmemcachedを追加することでアプリケーション構成を変更する必要があります。
* Cache invalidationも難しいですがそれに加えて、いつキャッシュを更新するかという複雑な問題にも悩まされることになります。
### その他の参考資料、ページ
* [From cache to in-memory data grid](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
* [スケーラブルなシステムデザインパターン](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
* [スケールできるシステムを設計するためのイントロダクション](http://lethain.com/introduction-to-architecting-systems-for-scale/)
* [スケーラビリティ、可用性、安定性、パターン](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [スケーラビリティ](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [AWS ElastiCacheのストラテジー](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
* [Wikipedia](https://en.wikipedia.org/wiki/Cache_(computing))
## 非同期処理
<p align="center">
<img src="images/54GYsSx.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Source: Intro to architecting systems for scale</a></i>
</p>
非同期のワークフローはもし、連続的に行われるとリクエスト時間を圧迫してしまうような重い処理を別で処理する手法です。また、定期的にデータを集合させるなどの時間がかかるような処理を前もって処理しておくことにも役立ちます。
### メッセージキュー
メッセージキューはメッセージを受け取り、保存し、配信します。もし、処理がインラインで行うには遅すぎる場合、以下のようなワークフローでメッセージキューを用いるといいでしょう:
* アプリケーションはジョブをキューに配信し、ユーザーにジョブステータスを伝えます。
* ワーカーがジョブキューから受け取って、処理を行い、終了したらそのシグナルを返します。
ユーザーの処理が止まることはなく、ジョブはバックグラウンドで処理されます。この間に、クライアントはオプションとして、タスクが完了したかのように見せるために小規模の処理を行います。例えば、ツイートを投稿するときに、ツイートはすぐにあなたのタイムラインに反映されたように見えますが、そのツイートが実際に全てのフォロワーに配信されるまでにはもう少し時間がかかっているでしょう。
**Redis** はシンプルなメッセージ仲介としてはいいですが、メッセージが失われてしまう可能性があります。
**RabbitMQ** はよく使われていますが、'AMQP'プロトコルに対応して、自前のノードを立てる必要があります。
**Amazon SQS** という選択肢もありますが、レイテンシーが高く、メッセージが重複して配信されてしまう可能性があります。
### タスクキュー
タスクキューはタスクとその関連するデータを受け取り、処理した上でその結果を返します。スケジュール管理をできるほか、バックグラウンドでとても重いジョブをこなすこともできます。
**Celery** はスケジューリングとpythonのサポートがあります。
### バックプレッシャー
もし、キューが拡大しすぎると、メモリーよりもキューの方が大きくなりキャッシュミスが起こり、ディスク読み出しにつながり、パフォーマンスが低下することにつながります。[バックプレッシャー](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)はキューサイズを制限することで回避することができ、高いスループットを確保しキューにすでにあるジョブについてのレスポンス時間を短縮できます。キューがいっぱいになると、クライアントはサーバービジーもしくはHTTP 503をレスポンスとして受け取りまた後で時間をおいてアクセスするようにメッセージを受け取ります。クライアントは[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff)などによって後ほど再度時間を置いてリクエストすることができます。
### 欠点: 非同期処理
* キューを用いることで遅延が起こり、複雑さも増すため、あまり重くない計算処理やリアルタイムワークフローにおいては同期処理の方がいいでしょう。
### その他の参考資料、ページ
* [It's all a numbers game](https://www.youtube.com/watch?v=1KRYH75wgy4)
* [オーバーロードした時にバックプレッシャーを適用する](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
* [Little's law](https://en.wikipedia.org/wiki/Little%27s_law)
* [メッセージキューとタスクキューの違いとは?](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)
## 通信
<p align="center">
<img src="images/5KeocQs.jpg">
<br/>
<i><a href=http://www.escotal.com/osilayer.html>Source: OSI 7 layer model</a></i>
</p>
### Hypertext transfer protocol (HTTP)
HTTP はクライアントとサーバー間でのデータをエンコードして転送するための手法です。リクエスト・レスポンスに関わるプロトコルです。クライアントがリクエストをサーバーに投げ、サーバーがリクエストに関係するコンテンツと完了ステータス情報をレスポンスとして返します。HTTPは自己完結するので、間にロードバランサー、キャッシュ、エンクリプション、圧縮などのどんな中間ルーターが入っても動くようにできています。
基本的なHTTPリクエストはHTTP動詞(メソッド)とリソース(エンドポイント)で成り立っています。以下がよくあるHTTP動詞です。:
| 動詞 | 詳細 | 冪等性* | セーフ | キャッシュできるか |
|---|---|---|---|---|
| GET | リソースを読み取る | Yes | Yes | Yes |
| POST | リソースを作成するもしくはデータを処理するトリガー | No | No | Yes レスポンスが新しい情報を含む場合 |
| PUT | リソースを作成もしくは入れ替える | Yes | No | No |
| PATCH | リソースを部分的に更新する | No | No | Yes レスポンスが新しい情報を含む場合 |
| DELETE | リソースを削除する | Yes | No | No |
*何度呼んでも同じ結果が返ってくること*
HTTPは**TCP** や **UDP** などの低級プロトコルに依存しているアプリケーションレイヤーのプロトコルである。
#### その他の参考資料、ページ: HTTP
* [HTTPってなに?](https://www.nginx.com/resources/glossary/http/)
* [HTTP と TCPの違い](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)
* [PUT と PATCHの違い](https://laracasts.com/discuss/channels/general-discussion/whats-the-differences-between-put-and-patch?page=1)
### 伝送制御プロトコル (TCP)
<p align="center">
<img src="images/JdAsdvG.jpg">
<br/>
<i><a href=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>
TCPは[IP network](https://en.wikipedia.org/wiki/Internet_Protocol)の上で成り立つ接続プロトコルです。接続は[handshake](https://en.wikipedia.org/wiki/Handshaking)によって開始、解除されます。全ての送信されたパケットは欠損なしで送信先に送信された順番で到達するように以下の方法で保証されています:
* シーケンス番号と[checksum fields](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation)が全てのパケットに用意されている
* [Acknowledgement](https://en.wikipedia.org/wiki/Acknowledgement_(data_networks))パケットと自動再送信
もし送信者が正しいレスポンスを受け取らなかったとき、パケットを再送信します。複数のタイムアウトがあったとき、接続は解除されます。TCP は[フロー制御](https://en.wikipedia.org/wiki/Flow_control_(data)) と [輻輳制御](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control)も実装しています。これらの機能によって速度は低下し、一般的にUDPよりも非効率な転送手段になっています。
ハイスループットを実現するために、ウェブサーバーはかなり大きな数のTCP接続を開いておくことがあり、そのことでメモリー使用が圧迫されます。ウェブサーバスレッドと例えば[memcached](#memcached) サーバーの間で多数のコネクションを保っておくことは高くつくかもしれません。可能なところではUDPに切り替えるだけでなく[コネクションプーリング](https://en.wikipedia.org/wiki/Connection_pool)なども役立つかもしれません。
TCPは高い依存性を要し、時間制約が厳しくないものに適しているでしょう。ウェブサーバー、データベース情報、SMTP、FTPやSSHなどの例に適用されます。
以下の時にUDPよりもTCPを使うといいでしょう:
* 全てのデータが欠損することなしに届いてほしい
* ネットワークスループットの最適な自動推測をしてオペレーションしたい
### ユーザデータグラムプロトコル (UDP)
<p align="center">
<img src="images/yzDrJtA.jpg">
<br/>
<i><a href=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>
UDPはコネクションレスです。データグラムパケットのようなものはデータグラムレベルでの保証しかされません。データグラムは順不同で受け取り先に到着したりそもそも着かなかったりします。UDPは輻輳制御をサポートしません。TCPにおいてはサポートされているこれらの保証がないため、UDPは一般的に、TCPよりも効率的です。
UDPはサブネット上のすべての機器にデータグラムを送信することができます。これは[DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) において役に立ちます。というのも、クライアントはまだIPアドレスを取得していないので、IPアドレスを必要とするTCPによるストリームができないからです。
UDPは信頼性の面では劣りますが、VoIP、ビデオチャット、ストリーミングや同時通信マルチプレイヤーゲームなどのリアルタイム性が重視される時にはとても効果的です。
TCPよりもUDPを使うのは:
* レイテンシーを最低限に抑えたい時
* データ欠損よりも、データ遅延を重視するとき
* エラー修正を自前で実装したいとき
#### その他の参考資料、ページ: TCP と UDP
* [ゲームプログラミングのためのネットワーク](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)
* [TCP と UDP プロトコルの主な違い](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)
* [TCP と UDPの違い](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
* [Transmission control protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)
* [User datagram protocol](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [Facebookのメムキャッシュスケーリング](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)
### 遠隔手続呼出 (RPC)
<p align="center">
<img src="images/iF4Mkb5.png">
<br/>
<i><a href=http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview>Source: Crack the system design interview</a></i>
</p>
RPCではクライアントがリモートサーバーなどの異なるアドレス空間でプロシージャーが処理されるようにします。プロシージャーはローカルでのコールのように、クライアントからサーバーにどのように通信するかという詳細を省いた状態でコードが書かれます。リモートのコールは普通、ローカルのコールよりも遅く、信頼性に欠けるため、RPCコールをローカルコールと区別させておくことが好ましいでしょう。人気のRPCフレームワークは以下です。[Protobuf](https://developers.google.com/protocol-buffers/)、 [Thrift](https://thrift.apache.org/)、[Avro](https://avro.apache.org/docs/current/)
RPC は リクエストレスポンスプロトコル:
* **クライアントプログラム** - クライアントスタブプロシージャーを呼び出します。パラメータはローカルでのプロシージャーコールのようにスタックへとプッシュされていきます。
* **クライアントスタブプロシージャー** - プロシージャIDとアーギュメントをパックしてリクエストメッセージにします。
* **クライアント通信モジュール** - OSがクライアントからサーバーへとメッセージを送ります。
* **サーバー通信モジュール** - OSが受け取ったパケットをサーバースタブプロシージャーに受け渡します。
* **サーバースタブプロシージャー** - 結果を展開し、プロシージャーIDにマッチするサーバープロシージャーを呼び出し、結果を返します。
* サーバーレスポンスは上記のステップを逆順で繰り返します。
Sample RPC calls:
```
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
```
RPCは振る舞いを公開することに焦点を当てています。RPCは内部通信パフォーマンスを理由として使われることが多いです。というのも、使用する状況に合わせてネイティブコールを自作することができるからです。
ネイティブライブラリー (aka SDK) を呼ぶのは以下の時:
* ターゲットのプラットフォームを知っている時
* ロジックがどのようにアクセスされるのかを管理したいとき
* ライブラリー外でエラーがどのようにコントロールされるかを管理したい時
* パフォーマンスとエンドユーザーエクスペリエンスが最優先の時
**REST** プロトコルに従うHTTP APIはパブリックAPIにおいてよく用いられます。
#### 欠点: RPC
* RPCクライアントとはサービス実装により厳密に左右されることになります。
* 新しいオペレーション、使用例があるたびに新しくAPIが定義されなければなりません。
* RPCをデバッグするのは難しい可能性があります。
* 既存のテクノロジーをそのまま使ってサービスを構築することはできないかもしれません。例えば、[Squid](http://www.squid-cache.org/)などのサーバーに[RPCコールが正しくキャッシュ](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/) されるように追加で骨を折る必要があるかもしれません。
### Representational state transfer (REST)
RESTは、クライアントがサーバーによってマネージされるリソースに対して処理を行うクライアント・サーバーモデルを支持するアーキテキチャスタイルです。サーバーは操作できるもしくは新しいリソースレプレゼンテーションを受け取ることができるようなリソースやアクションのレプレゼンテーションを提供します。すべての通信はステートレスでキャッシュ可能でなければなりません。
RESTful なインターフェースには次の四つの特徴があります:
* **特徴的なリソース (URI in HTTP)** - どのオペレーションであっても同じURIを使う。
* **HTTP動詞によって変わる (Verbs in HTTP)** - 動詞、ヘッダー、ボディを使う
* **自己説明的なエラーメッセージ (status response in HTTP)** - ステータスコードを使い、新しく作ったりしないこと。
* **[HATEOAS](http://restcookbook.com/Basics/hateoas/) (HTML interface for HTTP)** - 自分のwebサービスがブラウザで完全にアクセスできること。
サンプル REST コール:
```
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
```
RESTはデータを公開することに焦点を当てています。クライアントとサーバーのカップリングを最小限にするもので、パブリックAPIなどによく用いられます。RESTはURI、 [representation through headers](https://github.com/for-GET/know-your-http-well/blob/master/headers.md)、そして、GET、POST、PUT、 DELETE、PATCHなどのHTTP動詞等のよりジェネリックで統一されたメソッドを用います。ステートレスであるのでRESTは水平スケーリングやパーティショニングに最適です。
#### 欠点: REST
* RESTはデータ公開に焦点を当てているので、リソースが自然に整理されていなかったり、シンプルなヒエラルキーで表せられない時にはよい選択肢とは言えないかもしれません。例えば、とあるイベントのセットにマッチするすべての更新情報を返すと言った処理は簡単にはパスで表現することができません。RESTでは、URIパス、クエリパラメータ、そして場合によってはリクエストボディなどによって実装されることが多いでしょう。
* RESTは少数の動詞に依存しています(GET、POST、PUT、DELETE、そして PATCH) が時には使いたい事例に合わないことがあります。例えば、期限の切れたドキュメントをアーカイブに移したい場合などはこれらの動詞の中には綺麗にはフィットしません。
* ネストされたヒエラルキーの中にあるリソースをとってくるのはシングルビューを描画するのにクライアントとサーバー間で数回やりとりしなければなりません。例として、ブログエントリーのコンテンツとそれに対するコメントを表示する場合などです。様々なネットワーク環境で動作する可能性が考えられるモバイルアプリケーションにおいてはこのような複数のやり取りは好ましくありません。
* 時が経つにつれて、APIレスポンスにより多くのフィールドが与えられて、古いクライアントはすでにいらないものも含めてすべてのデータフィールドを受け取ることになります。そのことで、ペイロードが大きくなりすぎて、レイテンシーも拡大することになります。
### RPCとREST比較
| Operation | RPC | REST |
|---|---|---|
| サインアップ | **POST** /signup | **POST** /persons |
| リザイン | **POST** /resign<br/>{<br/>"personid": "1234"<br/>} | **DELETE** /persons/1234 |
| Person読み込み | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| Personのアイテムリスト読み込み | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| Personのアイテムへのアイテム追加 | **POST** /addItemToUsersItemsList<br/>{<br/>"personid": "1234";<br/>"itemid": "456"<br/>} | **POST** /persons/1234/items<br/>{<br/>"itemid": "456"<br/>} |
| アイテム更新 | **POST** /modifyItem<br/>{<br/>"itemid": "456";<br/>"key": "value"<br/>} | **PUT** /items/456<br/>{<br/>"key": "value"<br/>} |
| アイテム削除 | **POST** /removeItem<br/>{<br/>"itemid": "456"<br/>} | **DELETE** /items/456 |
<p align="center">
<i><a href=https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/>Source: Do you really know why you prefer REST over RPC</a></i>
</p>
#### その他の参考資料、ページ: REST と RPC
* [Do you really know why you prefer REST over RPC](https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/)
* [When are RPC-ish approaches more appropriate than REST?](http://programmers.stackexchange.com/a/181186)
* [REST vs JSON-RPC](http://stackoverflow.com/questions/15056878/rest-vs-json-rpc)
* [Debunking the myths of RPC and REST](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)
* [What are the drawbacks of using REST](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)
* [Crack the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Thrift](https://code.facebook.com/posts/1468950976659943/)
* [Why REST for internal use and not RPC](http://arstechnica.com/civis/viewtopic.php?t=1190508)
## セキュリティ
このセクションは更新が必要です。[contributing](#contributing)してください!
セキュリティは幅広いトピックです。十分な経験、セキュリティ分野のバックグラウンドがなくても、セキュリティの知識を要する職に応募するのでない限り、基本以上のことを知る必要はないでしょう。
* 情報伝達、保存における暗号化
* [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) や [SQL injection](https://en.wikipedia.org/wiki/SQL_injection)を防ぐために、全てのユーザー入力もしくはユーザーに露出される入力パラメーターをサニタイズする
* SQL injectionを防ぐためにパラメータ化されたクエリを用いる。
* [least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)の原理を用いる
### その他の参考資料、ページ:
* [APIセキュリティチェックリスト](https://github.com/shieldfy/API-Security-Checklist)
* [開発者のためのセキュリティガイド](https://github.com/FallibleInc/security-guide-for-developers)
* [OWASP top ten](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
## 補遺
暗算で、推計値を求める必要があることも時にはあります。例えば、ディスクから100枚イメージ分のサムネイルを作る時間を求めたり、その時にどれだけディスクメモリーが消費されるかなどの値です。**2の乗数表** と **全てのプログラマーが知るべきレイテンシー値** は良い参考になるでしょう。
### 2の乗数表
```
乗数 厳密な値 約 Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
```
#### その他の参考資料、ページ:
* [2の乗数表](https://en.wikipedia.org/wiki/Power_of_two)
### 全てのプログラマーが知るべきレイテンシー値
```
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from disk 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
```
上記表に基づいた役に立つ数値:
* ディスクからの連続読み取り速度 30 MB/s
* 1 Gbps Ethernetからの連続読み取り速度 100 MB/s
* SSDからの連続読み取り速度 1 GB/s
* main memoryからの連続読み取り速度 4 GB/s
* 1秒で地球6-7周できる
* 1秒でデータセンターと2000周やりとりできる
#### レイテンシーの視覚的表
![](https://web.archive.org/web/20200702021143im_/https://camo.githubusercontent.com/77f72259e1eb58596b564d1ad823af1853bc60a3/687474703a2f2f692e696d6775722e636f6d2f6b307431652e706e67)
#### その他の参考資料、ページ:
* [全てのプログラマーが知るべきレイテンシー値 - 1](https://gist.github.com/jboner/2841832)
* [全てのプログラマーが知るべきレイテンシー値 - 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)
### 他のシステム設計面接例題
> 頻出のシステム設計面接課題とその解答へのリンク
| 質問 | 解答 |
|---|---|
| Dropboxのようなファイル同期サービスを設計する | [youtube.com](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| 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) |
| Googleのようなスケーラブルなwebクローラーの設計 | [quora.com](https://www.quora.com/How-can-I-build-a-web-crawler-from-scratch) |
| Google docsの設計 | [code.google.com](https://code.google.com/p/google-mobwrite/)<br/>[neil.fraser.name](https://neil.fraser.name/writing/sync/) |
| Redisのようなキーバリューストアの設計 | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| Memcachedのようなキャッシュシステムの設計 | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| Amazonのようなレコメンデーションシステムの設計 | [hulu.com](http://tech.hulu.com/blog/2011/09/19/recommendation-system.html)<br/>[ijcai13.org](http://ijcai13.org/files/tutorial_slides/td3.pdf) |
| BitlyのようなURL短縮サービスの設計 | [n00tc0d3r.blogspot.com](http://n00tc0d3r.blogspot.com/) |
| WhatsAppのようなチャットアプリの設計 | [highscalability.com](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html)
| 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) |
| Facebookニュースフィードの設計 | [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) |
| Facebookタイムラインの設計 | [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) |
| Facebookチャットの設計 | [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) |
| Facebookのようなgraph検索の設計 | [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) |
| CloudFlareのようなCDNの設計 | [cmu.edu](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci) |
| Twitterのトレンド機能の設計 | [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/) |
| ランダムID発行システムの設計 | [blog.twitter.com](https://blog.twitter.com/2010/announcing-snowflake)<br/>[github.com](https://github.com/twitter/snowflake/) |
| 一定のインターバル時間での上位k件を返す | [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) |
| 複数のデータセンターからデータを配信するサービスの設計 | [highscalability.com](http://highscalability.com/blog/2009/8/24/how-google-serves-data-from-multiple-datacenters.html) |
| オンラインの複数プレイヤーカードゲームの設計 | [indieflashblog.com](https://web.archive.org/web/20180929181117/http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)<br/>[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| ガーベッジコレクションシステムの設計 | [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) |
| APIのRate Limitを設計する | [https://stripe.com/blog/](https://stripe.com/blog/rate-limiters) |
| (NASDAQやBinanceのような)株式取引所を設計する | [Jane Street](https://youtu.be/b1e4t2k2KJY)<br/>[Golang Implementation](https://around25.com/blog/building-a-trading-engine-for-a-crypto-exchange/)<br/>[Go Implemenation](http://bhomnick.net/building-a-simple-limit-order-in-go/) |
| システム設計例題を追加する | [Contribute](#contributing) |
### 実世界のアーキテクチャ
> 世の中のシステムがどのように設計されているかについての記事
<p align="center">
<img src="images/TcUo2fw.png">
<br/>
<i><a href=https://www.infoq.com/presentations/Twitter-Timeline-Scalability>Source: Twitter timelines at scale</a></i>
</p>
**以下の記事の重箱の隅をつつくような細かい詳細にこだわらないこと。むしろ**
* 共通の原理、技術、パターンを探ること
* それぞれのコンポーネントでどんな問題が解決され、コンポーネントはどこでうまく使えもしくは使えないかを知ること
* 学んだことを復習すること
|種類 | システム | 参考ページ |
|---|---|---|
| データ処理 | **MapReduce** - Googleの分散データ処理システム | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/mapreduce-osdi04.pdf) |
| データ処理 | **Spark** - Databricksの分散データ処理システム | [slideshare.net](http://www.slideshare.net/AGrishchenko/apache-spark-architecture) |
| データ処理 | **Storm** - Twitterの分散データ処理システム | [slideshare.net](http://www.slideshare.net/previa/storm-16094009) |
| | | |
| データストア | **Bigtable** - Googleのカラム指向分散データベース | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) |
| データストア | **HBase** - Bigtableのオープンソース実装 | [slideshare.net](http://www.slideshare.net/alexbaranau/intro-to-hbase) |
| データストア | **Cassandra** - Facebookのカラム指向分散データベース | [slideshare.net](http://www.slideshare.net/planetcassandra/cassandra-introduction-features-30103666)
| データストア | **DynamoDB** - Amazonのドキュメント指向分散データベース | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) |
| データストア | **MongoDB** - ドキュメント指向分散データベース | [slideshare.net](http://www.slideshare.net/mdirolf/introduction-to-mongodb) |
| データストア | **Spanner** - Googleのグローバル分散データベース | [research.google.com](http://research.google.com/archive/spanner-osdi2012.pdf) |
| データストア | **Memcached** - 分散メモリーキャッシングシステム | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| データストア | **Redis** - 永続性とバリュータイプを兼ね備えた分散メモリーキャッシングシステム | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| | | |
| ファイルシステム | **Google File System (GFS)** - 分散ファイルシステム | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/gfs-sosp2003.pdf) |
| ファイルシステム | **Hadoop File System (HDFS)** - GFSのオープンソース実装 | [apache.org](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html) |
| | | |
| Misc | **Chubby** - 疎結合の分散システムをロックするGoogleのサービス | [research.google.com](http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/archive/chubby-osdi06.pdf) |
| Misc | **Dapper** - 分散システムを追跡するインフラ | [research.google.com](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf)
| Misc | **Kafka** - LinkedInによるPub/subメッセージキュー | [slideshare.net](http://www.slideshare.net/mumrah/kafka-talk-tri-hug) |
| Misc | **Zookeeper** - 同期を可能にする中央集権インフラとサービス | [slideshare.net](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) |
| | アーキテクチャを追加する | [Contribute](#contributing) |
### 各企業のアーキテクチャ
| 企業 | 参考ページ |
|---|---|
| Amazon | [Amazon architecture](http://highscalability.com/amazon-architecture) |
| Cinchcast | [Producing 1,500 hours of audio every day](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html) |
| DataSift | [Realtime datamining At 120,000 tweets per second](http://highscalability.com/blog/2011/11/29/datasift-architecture-realtime-datamining-at-120000-tweets-p.html) |
| DropBox | [How we've scaled Dropbox](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| 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: Facebooks 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/>[Facebooks photo storage](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf) |
| Flickr | [Flickr architecture](http://highscalability.com/flickr-architecture) |
| 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) |
| PlentyOfFish | [PlentyOfFish architecture](http://highscalability.com/plentyoffish-architecture) |
| Salesforce | [How they handle 1.3 billion transactions a day](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html) |
| Stack Overflow | [Stack Overflow architecture](http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html) |
| TripAdvisor | [40M visitors, 200M dynamic page views, 30TB data](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.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) |
| Uber | [How Uber scales their real-time market platform](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html) |
| WhatsApp | [The WhatsApp architecture Facebook bought for $19 billion](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| YouTube | [YouTube scalability](https://www.youtube.com/watch?v=w5WVu624fY8)<br/>[YouTube architecture](http://highscalability.com/youtube-architecture) |
### 企業のエンジニアブログ
> 面接を受ける企業のアーキテクチャ
>
> 投げられる質問は同じ分野から来ることもあるでしょう
* [Airbnb Engineering](http://nerds.airbnb.com/)
* [Atlassian Developers](https://developer.atlassian.com/blog/)
* [Autodesk Engineering](http://cloudengineering.autodesk.com/blog/)
* [AWS Blog](https://aws.amazon.com/blogs/aws/)
* [Bitly Engineering Blog](http://word.bitly.com/)
* [Box Blogs](https://www.box.com/blog/engineering/)
* [Cloudera Developer Blog](http://blog.cloudera.com/blog/)
* [Dropbox Tech Blog](https://tech.dropbox.com/)
* [Engineering at Quora](http://engineering.quora.com/)
* [Ebay Tech Blog](http://www.ebaytechblog.com/)
* [Evernote Tech Blog](https://blog.evernote.com/tech/)
* [Etsy Code as Craft](http://codeascraft.com/)
* [Facebook Engineering](https://www.facebook.com/Engineering)
* [Flickr Code](http://code.flickr.net/)
* [Foursquare Engineering Blog](http://engineering.foursquare.com/)
* [GitHub Engineering Blog](https://github.blog/category/engineering)
* [Google Research Blog](http://googleresearch.blogspot.com/)
* [Groupon Engineering Blog](https://engineering.groupon.com/)
* [Heroku Engineering Blog](https://engineering.heroku.com/)
* [Hubspot Engineering Blog](http://product.hubspot.com/blog/topic/engineering)
* [High Scalability](http://highscalability.com/)
* [Instagram Engineering](http://instagram-engineering.tumblr.com/)
* [Intel Software Blog](https://software.intel.com/en-us/blogs/)
* [Jane Street Tech Blog](https://blogs.janestreet.com/category/ocaml/)
* [LinkedIn Engineering](http://engineering.linkedin.com/blog)
* [Microsoft Engineering](https://engineering.microsoft.com/)
* [Microsoft Python Engineering](https://blogs.msdn.microsoft.com/pythonengineering/)
* [Netflix Tech Blog](http://techblog.netflix.com/)
* [Paypal Developer Blog](https://medium.com/paypal-engineering)
* [Pinterest Engineering Blog](http://engineering.pinterest.com/)
* [Engineering](https://www.quora.com/q/quoraengineering)
* [Reddit Blog](http://www.redditblog.com/)
* [Salesforce Engineering Blog](https://developer.salesforce.com/blogs/engineering/)
* [Slack Engineering Blog](https://slack.engineering/)
* [Spotify Labs](https://labs.spotify.com/)
* [Stripe Engineering Blog](https://stripe.com/blog/engineering)
* [Twilio Engineering Blog](http://www.twilio.com/engineering)
* [Twitter Engineering](https://engineering.twitter.com/)
* [Uber Engineering Blog](http://eng.uber.com/)
* [Yahoo Engineering Blog](http://yahooeng.tumblr.com/)
* [Yelp Engineering Blog](http://engineeringblog.yelp.com/)
* [Zynga Engineering Blog](https://www.zynga.com/blogs/engineering)
#### その他の参考資料、ページ:
* [kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)
ここにあるリストは比較的小規模なものにとどめ、[kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)により詳細に記すことで重複しないようにしておくことにする。エンジニアブログへのリンクを追加する場合はここではなく、engineering-blogsレボジトリに追加することを検討してください。
## 進行中の作業
セクションの追加や、進行中の作業を手伝っていただける場合は[こちら](#contributing)!
* MapReduceによる分散コンピューティング
* Consistent hashing
* Scatter gather
* [Contribute](#contributing)
## クレジット
クレジット及び、参照ページは適時このリポジトリ内に記載してあります
Special thanks to:
* [Hired in tech](http://www.hiredintech.com/system-design/the-system-design-process/)
* [Cracking the coding interview](https://www.amazon.com/dp/0984782850/)
* [High scalability](http://highscalability.com/)
* [checkcheckzz/system-design-interview](https://github.com/checkcheckzz/system-design-interview)
* [shashank88/system_design](https://github.com/shashank88/system_design)
* [mmcgrana/services-engineering](https://github.com/mmcgrana/services-engineering)
* [System design cheat sheet](https://gist.github.com/vasanthk/485d1c25737e8e72759f)
* [A distributed systems reading list](http://dancres.github.io/Pages/)
* [Cracking the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
## Contact info
Feel free to contact me to discuss any issues, questions, or comments.
My contact info can be found on my [GitHub page](https://github.com/donnemartin).
## License
*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)
http://creativecommons.org/licenses/by/4.0/

1837
docs/README-tr.md Normal file
View File

@@ -0,0 +1,1837 @@
*[English](README.md) ∙ [日本語](README-ja.md) ∙ [简体中文](README-zh-Hans.md) ∙ [繁體中文](README-zh-TW.md) | [العَرَبِيَّة‎](https://github.com/donnemartin/system-design-primer/issues/170) ∙ [বাংলা](https://github.com/donnemartin/system-design-primer/issues/220) ∙ [Português do Brasil](https://github.com/donnemartin/system-design-primer/issues/40) ∙ [Deutsch](https://github.com/donnemartin/system-design-primer/issues/186) ∙ [ελληνικά](https://github.com/donnemartin/system-design-primer/issues/130) ∙ [עברית](https://github.com/donnemartin/system-design-primer/issues/272) ∙ [Italiano](https://github.com/donnemartin/system-design-primer/issues/104) ∙ [한국어](https://github.com/donnemartin/system-design-primer/issues/102) ∙ [فارسی](https://github.com/donnemartin/system-design-primer/issues/110) ∙ [Polski](https://github.com/donnemartin/system-design-primer/issues/68) ∙ [русский язык](https://github.com/donnemartin/system-design-primer/issues/87) ∙ [Español](https://github.com/donnemartin/system-design-primer/issues/136) ∙ [ภาษาไทย](https://github.com/donnemartin/system-design-primer/issues/187) ∙ [Türkçe](README-tr.md) ∙ [tiếng Việt](https://github.com/donnemartin/system-design-primer/issues/127) ∙ [Français](https://github.com/donnemartin/system-design-primer/issues/250) | [Add Translation](https://github.com/donnemartin/system-design-primer/issues/28)*
**Bu kaynağın [çeviri](TRANSLATIONS.md)sine yardım edebirsiniz!**
# Sistem Tasarım Rehberi
<p align="center">
<img src="images/jj3A5N8.png">
<br/>
</p>
## Amaç
> Büyük ölçekli sistemler için sistem tasarımını öğrenmek.
>
> Sistem tasarımı mülakatlarına hazırlanmak.
### Büyük sistemlerin nasıl tasarlacağını öğrenin
Ölçeklenebilir sistemlerin nasıl tasarlanacağını öğrenmek, daha iyi bir mühendis olmanıza yardımcı olacaktır.
Sistem tasarımı, çok geniş bir konudur. İnternette sistem tasarım ilkelerine ilişkin sayısız kaynak bulunmaktadır. **
Bu repo, ölçeklenebilir sistemlerin nasıl oluşturulacağını öğrenmenize yardımcı olabilecek düzenli bir kaynak koleksiyonudur.
### Açık kaynak topluluğundan bilgi edinin
Bu, sürekli güncellenen açık kaynak projesinin ilk sürümüdür.
[Katkı](#katkı)da bulunabilirsiniz!
### Sistem tasarımı görüşmelerine hazırlanın
Pek çok teknoloji şirketinde, görüşmeleri kodlamanın yanı sıra sistem tasarımı da **teknik görüşme sürecinde** **gerekli bir adımdır**.
**Sistem tasarımıyla ilgili yaygın mülakat sorularını pratik yapın** ve **örnek çözümler** ile yanıtlarınızı karşılaştırın: tartışmalar, kodlar ve diyagramlar.
Mülakata hazırlık için diğer konular:
* [Çalışma rehberi](#Çalışma-rehberi)
* [Sistem tasarımı mülakat sorusu nasıl ele alınır](#sistem-tasarımı-mülakat-sorusu-nasıl-ele-alınır)
* [Sistem tasarımı mülakat soruları ve **çözümleri**](#sistem-tasarımı-mülakat-soruları-ve-çözümleri)
* [Nesne yönelimli tasarım mülakat soruları ve **çözümleri**](#nesne-yönelimli-tasarım-mülakat-soruları-ve-çözümleri)
* [Diğer sistem tasarımı mülakat soruları](#diğer-sistem-tasarımı-mülakat-soruları)
## Anki bilgi kartları
<p align="center">
<img src="images/zdCAkB3.png">
<br/>
</p>
[Anki bilgi kartları](https://apps.ankiweb.net/)nı temel sistem tasarımı kavramlarını ezberlemenize yardımcı olmak için kullanabilirsiniz.
* [Sistem tasarımı kartları](resources/flash_cards/System%20Design.apkg)
* [Sistem tasarımı alıştırma kartları](resources/flash_cards/System%20Design%20Exercises.apkg)
* [Nesneye yönelik tasarım alıştırma kartları](resources/flash_cards/OO%20Design.apkg)
Her zaman ve her yerde kullanılabilir.
### Kod Kaynakları: Etkileşimli Kodlama Yarışmaları
[**Kodlama Mülakatları**](https://github.com/donnemartin/interactive-coding-challenges)na hazırlanmak için kaynak mı arıyorsunuz?
<p align="center">
<img src="images/b4YtAEN.png">
<br/>
</p>
Lütfen ek bilgi kartlarını içeren [**Etkileşimli Kodlama Yarışmaları**](https://github.com/donnemartin/interactive-coding-challenges) reposuna göz atın:
* [Kodlama kartları](https://github.com/donnemartin/interactive-coding-challenges/tree/master/anki_cards/Coding.apkg)
## Katkı
> Topluluktan öğrenin.
Yardım etmek için değişiklik gönderme talebi(pull request) göndermekten çekinmeyin:
* Hataları düzeltmek
* Bölümleri geliştirmek
* Yeni bölüm eklemek
* [Çeviri Yardımı](https://github.com/donnemartin/system-design-primer/issues/28)
Hala geliştirilmesi gereken bazı içerikler, [Geliştirme aşamasında](#geliştirme-aşamasında) bölümünde bulunmaktadır.
Lütfen [katkı kurallarını](CONTRIBUTING.md) inceleyin.
## Sistem tasarımı konuları dizini
> Avantajlar ve dezavantajlar da dahil olmak üzere çeşitli sistem tasarımı konularının özeti. **Her şeyin bir karşılığı vardır.**. (Ek çeviri notu: Karşılaştırma sonucunda bir şeyden feragat etmek gerektiği vurgulanmaktadır.)
>
> Her bölüm, ek kaynaklara bağlantılar içerir.
<p align="center">
<img src="images/jrUBAF7.png">
<br/>
</p>
* [Sistem tasarımı konuları: buradan başlayın](#sistem-tasarımı-konuları-buradan-başlayın)
* [1. Adım: Ölçeklenebilirlik video dersini inceleyin](#1-adım-ölçeklenebilirlik-video-dersini-inceleyin)
* [2. Adım: Ölçeklenebilirlik makalesini inceleyin](#2-adım-ölçeklenebilirlik-makalesini-inceleyin)
* [Sonraki adımlar](#sonraki-adımlar)
* [Performans veya ölçeklenebilirlik](#performans-veya-ölçeklenebilirlik)
* [Gecikme veya verim](#gecikme-veya-verim)
* [Kullanılabilirlik veya tutarlılık](#kullanılabilirlik-veya-tutarlılık)
* [CAP teoremi](#cap-teoremi)
* [CP - Tutarlılık ve bölüm toleransı](#cp--tutarlılık-ve-bölüm-toleransı)
* [AP - Kullanılabilirlik ve bölüm toleransı](#ap--kullanılabilirlik-ve-bölüm-toleransı)
* [Tutarlılık modelleri](#tutarlılık-modelleri)
* [Zayıf tutarlılık](#zayıf-tutarlılık)
* [Nihai tutarlılık](#Nihai-tutarlılık)
* [Güçlü tutarlılık](#güçlü-tutarlılık)
* [Kullanılabilirlik modları](#kullanılabilirlik-modları)
* [Yük devretme](#yük-devretme)
* [Çoğaltma](#çoğaltma)
* [Sayılarla erişilebilirlik](#sayılarla-erişilebilirlik)
* [Alan adı sistemi (DNS)](#alan-adı-sistemi-dns)
* [İçerik dağıtım ağı (CDN)](#içerik-dağıtım-ağı-cdn)
* [Push CDN](#push-cdn)
* [Pull CDN](#pull-cdn)
* [Yük dengeleyici (Load balancer)](#yük-dengeleyici-load-balancer)
* [Aktif-pasif)](#aktif-pasif)
* [Aktif-aktif)](#aktif-aktif)
* [Katman 4 yük dengeleyicisi](#katman-4-yük-dengeleyicisi)
* [Katman 7 yük dengeleyicisi](#katman-7-yük-dengeleyicisi)
* [Yatay ölçekleme](#yatay-ölçekleme)
* [Ters proxy (web sunucusu)](#ters-proxy-web-sunucusu)
* [Yük dengeleyici ve ters proxy](#yük-dengeleyici-ve-ters-proxy)
* [Uygulama katmanı](#uygulama-katmanı)
* [Mikroservisler](#mikroservisler)
* [Servis keşfi](#servis-keşfi)
* [Veritabanı](#veritabanı)
* [İlişkisel veritabanı yönetim sistemi (RDBMS)](#ilişkisel-veritabanı-yönetim-sistemi-rdbms)
* [Master-slave çoğaltma](#master-slave-çoğaltma)
* [Master-master çoğaltma](#master-master-çoğaltma)
* [Federasyon](#federasyon)
* [Parçalama](#parçalama)
* [Denormalizasyon](#denormalizasyon)
* [SQL ayarlama (SQL tuning)](#sql-ayarlama-sql-tuning)
* [NoSQL](#nosql)
* [Anahtar/değer deposu](#anahtar-değer-deposu)
* [Belge deposu](#belge-deposu)
* [Geniş sütun deposu](#geniş-sütun-deposu)
* [Grafik veritabanı](#grafik-veritabanı)
* [SQL veya NoSQL](#sql-veya-nosql)
* [Önbellek](#önbellek)
* [İstemci önbelleği](#istemci-önbelleği)
* [CDN önbelleği](#cdn-önbelleği)
* [Web sunucusu önbelleği](#web-sunucusu-önbelleği)
* [Veritabanı önbelleği](#veritabanı-önbelleği)
* [Uygulama Önbelleği](#uygulama-önbelleği)
* [Veritabanı sorgu düzeyinde önbellekleme](#veritabanı-sorgu-düzeyinde-önbellekleme)
* [Nesne düzeyinde önbellekleme](#nesne-düzeyinde-önbellekleme)
* [Önbellek ne zaman güncellenmeli](#önbellek-ne-zaman-güncellenmeli)
* [Cache-aside](#cache-aside)
* [Üzerine yazma (write-through)](#üzerine-yazma-write-through)
* [Geri yazma (write-behind)](#geri-yazma-write-behind)
* [Önbelleği önceden yenileme (refresh-ahead)](#önbelleği-önceden-yenileme-refresh-ahead)
* [Asenkronizm](#asenkronizm)
* [Mesaj kuyrukları](#mesaj-kuyrukları)
* [Görev kuyrukları](#görev-kuyrukları)
* [Back pressure](#back-pressure)
* [İletişim](#iletişim)
* [İletim kontrol protokolü (TCP)](#iletim-kontrol-protokolü-tcp)
* [Kullanıcı datagram protokolü (UDP)](#kullanıcı-datagram-protokolü-udp)
* [Uzaktan yordam çağrısı (RPC)](#uzaktan-yordam-çağrısı-rpc)
* [Temsili durum transferi (REST)](#temsili-durum-transferi-rest)
* [Güvenlik](#güvenlik)
*[EK](#ek)
* [İkinin kuvveti tablosu](#ikinin-kuvveti-tablosu)
* [Her programcının bilmesi gereken gecikme sayıları](#her-programcının-bilmesi-gereken-gecikme-sayıları)
* [Diğer sistem tasarımı mülakat soruları](#diğer-sistem-tasarımı-mülakat-soruları)
* [Gerçek dünya mimarileri](#gerçek-dünya-mimarileri)
* [Şirketlerin sistem mimarileri](#şirketlerin-sistem-mimarileri)
*[Şirketlerin mühendislik blogları](#şirketlerin-mühendislik-blogları)
*[Geliştirme aşamasında](#geliştirme-aşamasında)
* [Katkıda bulunanlar](#katkıda-bulunanlar)
* [İletişim](#iletişim)
* [Lisans](#lisans)
## Çalışma rehberi
> Mülakat zaman çizelgenize (kısa, orta, uzun) göre önerilen konuları gözden geçirin.
![Imgur](images/OfVllex.png)
**S: Mülakatlar için buradaki her şeyi bilmem gerekiyor mu? **
**C: Hayır, mülakata hazırlanmak için buradaki her şeyi bilmenize gerek yok. **
Bir mülakatta size ne sorulacağı aşağıdaki faktörlere bağlıdır:
* Tecrübeniz
* Teknik geçmişiniz
* Görüşme yapacağınız pozisyon(lar)
* Görüşme yapacağınız firma(lar)
* Şans
Daha fazla deneyime sahip adayların genellikle sistem tasarımı konusunda daha fazla bilgiye sahip olmaları beklenir. Yazılım mimarlarından veya ekip liderlerden diğer adaylara göre daha fazlasını bilmeleri beklenebilir. En iyi teknoloji şirketleri, genellikle bir veya daha fazla sistem tasarımı mülakatı yapmaktadır.
Geniş bir perspektifle başlayın ve daha derine inmek için birkaç alana odaklanın. Önemli bazı sistem tasarım konuları hakkında biraz bilgi sahibi olmak faydalı olacaktır. Aşağıdaki rehberi, zaman çizelgenize, deneyiminize, hangi pozisyonlar için hangi şirketlerle mülakat yapacağınıza göre ayarlayın.
* **Kısa zaman çizelgesi** - Sistem tasarımı konularında **geniş bir bakış açısı** hedefleyin. **Birkaç** mülakat sorusu çözerek pratiğinizi artırın.
* **Orta zaman çizelgesi** - Sistem tasarımı konularında **geniş bir bakış açısı** ve **biraz derinlik** elde etmeyi hedefleyin. **Birçok** mülakat sorusunu çözerek pratiğinizi artırın.
* **Uzun zaman çizelgesi** - Sistem tasarımı konularında **geniş bir bakış açısı** ve **daha fazla derinlik** elde etmeyi hedefleyin. Mülakat sorularının **çoğu**nu çözerek pratiğinizi artırın.
| | Kısa | Orta | Uzun |
|---------------------------------------------------------------------------------------------------------------------------|--------|--------|------|
| [Sistem tasarımı konuları dizini](#sistem-tasarımı-konuları-dizini)ni okuyarak geniş bir fikir edinin | :+1: | :+1: | :+1: |
| Mülakat yapacağınız şirketlerin bazı [mühendislik blog yazılarını](#şirketlerin-mühendislik-blogları) okuyun | :+1: | :+1: | :+1: |
| Bazı [Gerçek dünya mimarileri](#gerçek-dünya-mimarileri) başlıklarını inceleyin | :+1: | :+1: | :+1: |
| [Sistem tasarımı mülakat sorusu nasıl ele alınır](#sistem-tasarımı-mülakat-sorusu-nasıl-ele-alınır) başlığını inceleyin | :+1: | :+1: | :+1: |
| [Sistem tasarımı mülakat soruları ve çözümleri](#sistem-tasarımı-mülakat-soruları-ve-çözümleri)ne çalışın | Birkaç | Birçok | Çoğu |
| [Nesne yönelimli tasarım mülakat soruları ve cevapları](#nesne-yönelimli-tasarım-mülakat-soruları-ve-çözümleri)ne çalışın | Birkaç | Birçok | Çoğu |
| [Diğer sistem tasarımı mülakat soruları](#diğer-sistem-tasarımı-mülakat-soruları)nı gözden geçirin | Birkaç | Birçok | Çoğu |
## Sistem tasarımı mülakat sorusu nasıl ele alınır?
Sistem tasarımı mülakatı **açık uçlu bir görüşmedir**. Konuşmayı sizin yönlendirmeniz beklenir.
Tartışmayı yönlendirmek için aşağıdaki adımları kullanabilirsiniz. Bu süreci sağlamlaştırmak için lütfen aşağıdaki adımları kullanarak [Sistem tasarımı mülakat soruları ve çözümleri](#sistem-tasarımı-mülakat-soruları-ve-çözümleri) bölümüne bakınız.
### Adım 1: Kullanım senaryolarını, kısıtlamaları ve varsayımlarııklayın
İhtiyacınız olan her şeyi bir araya toplayın ve soruna bakın. Kullanım senaryolarını ve kısıtlamaları net bir şekilde anlayabilmek için sorular sormaya devam edin. Varsayımları tartışın.
* Kim kullanacak?
* Nasıl kullanacaklar?
* Kaç kullanıcı var?
* Sistemin işlevi nedir?
* Sistemin girişi ve çıkışı nelerdir?
* Ne kadar veri işlenmek isteniyor?
* Saniyede kaç isteğin işleme alınması bekleniyor?
* İstenilen okuma-yazma oranı nedir?
### Adım 2: Üst düzey bir tasarım oluşturun
Üst düzey bir tasarımın ana hatlarını çizmek için tüm önemli bileşenleri kullanın.
* Ana bileşenleri ve bağlantıları çizin
* Fikrinizi gerekçelendirin
### Adım 3: Temel bileşenleri tasarlayın
Her bir temel bileşenin ayrıntılı ve derinlemesine analizini gerçekleştirin. Örneğin, sizden [URL kısaltma hizmeti tasarlamanız](solutions/system_design/pastebin/README.md) istendiyse, bunları tartışın:
* Tam URL'nin hash değerini oluşturmak ve saklamak
* [MD5](solutions/system_design/pastebin/README.md) ve [Base62](solutions/system_design/pastebin/README.md)
* Hash çakışmaları (Hash collisions)
* SQL veya NoSQL
* Veritabanı modeli
* Hash edilmiş URL'yi tam bir URL'ye çevirmek
* Veritabanı araması
* API ve nesne yönelimli tasarım
### Adım 4: Tasarımı genişletin
Sistemin performansını etkileyen durumları ve sınırlamaları belirleyin ve ele alın. Örneğin, genişletme sorununu(address scalability issue) tanımlamak için aşağıdakilere ihtiyacınız var mı?
* Yük dengeleme (Load balancer)
* Yatay genişleme (Horizontal scaling)
* Önbellek (Caching)
* Veritabanı parçalama (Database sharding)
Olası çözümleri ve maliyetleri tartışın. Her şeyin bir karşılığı vardır. (Ek çeviri notu: Karşılaştırma sonucunda bir şeyden feragat etmek gerektiği vurgulanmaktadır.) [Ölçeklenebilir sistemler için tasarım ilkeleri](#sistem-tasarımı-konuları-dizini)ni kullanarak tasarımdaki performans veya kapasite kısıtlamalarını belirleyin.
### Tahmini hesaplama
Elle bazı tahminler yapmanız istenebilir. [Ek](#ek) olarak aşağıdaki kaynaklara bakabilirsiniz:
* [Use back of the envelope calculations](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
* [2'nin kuvvet tablosu](#ikinin-kuvveti-tablosu)
* [Her programcının bilmesi gereken gecikme sayıları](#Her-programcının-bilmesi-gereken-gecikme-sayıları)
### Kaynak(lar) ve ek okuma
Daha iyi bir fikir edinmek için aşağıdaki bağlantılara göz atın:
* [How to ace a systems design interview](https://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)
* [The system design interview](http://www.hiredintech.com/system-design)
* [Intro to Architecture and Systems Design Interviews](https://www.youtube.com/watch?v=ZgdS0EUmn70)
* [System design template](https://leetcode.com/discuss/career/229177/My-System-Design-Template)
## Sistem tasarımı mülakat soruları ve çözümleri
> Genel sistem tasarımı mülakat soruları ve çözümler, kodlar ve diyagramlar.
>
> Çözümler, `solutions/` klasöründe bulunmaktadır.
| Soru | |
|----------------------------------------------------------------------------------|--------------------------------------------------------------|
| Pastebin.com(veya Bit.ly) tasarlayın | [Çözüm](solutions/system_design/pastebin/README-zh-Hans.md) |
| Twitter zaman çizelgesi ve arama(veya Facebook haber akışı ve arama) tasarlayın | [Çözüm](solutions/system_design/twitter/README.md) |
| Bir web tarayıcısı tasarlayın | [Çözüm](solutions/system_design/web_crawler/README.md) |
| Mint.com tasarlayın | [Çözüm](solutions/system_design/mint/README.md) |
| Sosyal ağ için veri yapılarını tasarlayın | [Çözüm](solutions/system_design/social_graph/README.md) |
| Arama motorları için bir anahtar/değer(key-value) deposu tasarlayın | [Çözüm](solutions/system_design/query_cache/README.md) |
| Amazon'un satış sıralamasını kategori özellikleri aracılığıyla tasarlayın | [Çözüm](solutions/system_design/sales_rank/README.md) |
| AWS'de milyon kullanıcılı bir sistem tasarlayın | [Çözüm](solutions/system_design/scaling_aws/README.md) |
| Sistem tasarımı sorusu ekleyin | [Katkı](#katkı) |
### Pastebin.com(veya Bit.ly) tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/pastebin/README.md)
![Imgur](images/4edXG0T.png)
### Twitter zaman çizelgesi ve arama(veya Facebook haber akışı ve arama) tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/twitter/README.md)
![Imgur](images/jrUBAF7.png)
### Bir web tarayıcısı tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/web_crawler/README.md)
![Imgur](images/bWxPtQA.png)
### Mint.com tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/mint/README.md)
![Imgur](images/V5q57vU.png)
### Sosyal ağ için veri yapılarını tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/social_graph/README.md)
![Imgur](images/cdCv5g7.png)
### Arama motorları için bir anahtar/değer(key-value) deposu tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/query_cache/README.md)
![Imgur](images/4j99mhe.png)
### Amazon'un satış sıralamasını kategori özellikleri aracılığıyla tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/sales_rank/README.md)
![Imgur](images/MzExP06.png)
### AWS'de milyon kullanıcılı bir sistem tasarlayın
[Alıştırma ve çözümü görüntüleyin](solutions/system_design/scaling_aws/README.md)
![Imgur](images/jj3A5N8.png)
## Nesne yönelimli tasarım mülakat soruları ve çözümleri
> Genel nesne yönelimli tasarım mülakat soruları ve çözümler, kodlar ve diyagramlar.
> >
> Çözümler, `solutions/` klasöründe bulunmaktadır.
>**Not: Bu bölüm halen geliştirilme aşamasındadır**
| Soru | |
|------------------------------------------|-------------------------------------------------------------------------------|
| Karma tablo(Hash map) tasarlayın | [Çözüm](solutions/object_oriented_design/hash_table/hash_map.ipynb) |
| LRU önbelleğini tasarlayın | [Çözüm](solutions/object_oriented_design/lru_cache/lru_cache.ipynb) |
| Çağrı merkezi tasarlayın | [Çözüm](solutions/object_oriented_design/call_center/call_center.ipynb) |
| Kart destesi tasarlayın | [Çözüm](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| Park yeri tasarlayın | [Çözüm](solutions/object_oriented_design/parking_lot/parking_lot.ipynb) |
| Sohbet hizmeti tasarlayın | [Çözüm](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| Dairesel dizi(circular array) tasarlayın | [Katkı](#katkı) |
| Nesne yönelimli tasarım sorusu ekleyin | [Katkı](#katkı) |
## Sistem tasarımı konuları: buradan başlayın
Sistem tasarımına aşina değil misiniz?
Öncelikle; genel ilkeler, bunların ne olduğu, nasıl kullanılacağı, artıları ve eksileri hakkında temel bir anlayışa sahip olmanız gerekir.
### 1. Adım: Ölçeklenebilirlik video dersini inceleyin
[Scalability Lecture at Harvard](https://www.youtube.com/watch?v=-W9F__D3oY4)
* İşlenen konular:
* Dikey ölçeklendirme(Vertical scaling)
* Yatay ölçeklendirme(Horizontal scaling)
* Önbellek(Caching)
* Yük dengeleme(Load balancing)
* Veritabanı çoğaltma(Database replication)
* Veritabanı bölümü(Database partitioning)
### 2. Adım: Ölçeklenebilirlik makalesini inceleyin
[Scalability](http://www.lecloud.net/tagged/scalability/chrono)
* İşlenen konular:
* [Klonlar(Clones)](http://www.lecloud.net/post/7295452622/scalability-for-dummies-part-1-clones)
* [Veritabanları(Databases)](http://www.lecloud.net/post/7994751381/scalability-for-dummies-part-2-database)
* [Önbellekler(Caches)](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
* [Asenkronizm(Asynchronism)](http://www.lecloud.net/post/9699762917/scalability-for-dummies-part-4-asynchronism)
### Sonraki adımlar
Daha sonra, üst düzey karşılaştırmalara bakacağız:
* **Performans** veya **Ölçeklenebilirlik**
* **Gecikme** veya **Verim**
* **Kullanılabilirlik** veya **Tutarlılık**
Her şeyin bir karşılığı olduğunu unutmayın. (Ek çeviri notu: Karşılaştırma sonucunda bir şeyden feragat etmek gerektiği vurgulanmaktadır.)
Daha sonra alan adı sistemi(DNS), içerik dağıtım ağları(CDNs) ve yük dengeleyiciler(load balancers) gibi daha spesifik konuları inceleyeceğiz.
## Performans veya ölçeklenebilirlik
Bir hizmetin **performansı** kaynaklardaki artışla orantılı olarak artıyorsa ölçeklenebilirdir. Performansı artırmak genellikle daha fazla iş birimine hizmet etmek anlamına gelir ancak diğer yandan veri seti büyüdüğünde daha büyük iş birimlerini de işleyebilir. <sup><a href="http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html">1</a></sup>
Performans veya ölçeklenebilirliğe başka bir bakış açısı:
* Sisteminizde **performans** sorunları varsa, tek bir kullanıcı için yavaş olacaktır.
* Sisteminizde **ölçeklenebilirlik** sorunları varsa, tek kullanıcı için daha hızlı olacaktır ancak yüksek yük altında yavaşlayacaktır.
### Kaynak(lar) ve ek okuma
* [A word on scalability](http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
## Gecikme veya verim
**Gecikme**, bir işlemin veya bir hesaplamanın sonucunun gerçekleştirilmesi için gereken süredir.
**Verim**, birim zamanda gerçekleştirilen bu tür işlemlerin veya işlemlerin sayısıdır.
Genel olarak, kabul edilebilir gecikme süresiyle verimi en üst düzeye çıkarmayı hedeflemelisiniz.
### Kaynak(lar) ve ek okuma
* [Understanding latency vs throughput](https://community.cadence.com/cadence_blogs_8/b/fv/posts/understanding-latency-vs-throughput)
## Kullanılabilirlik veya tutarlılık
### CAP Teoremi
<p align="center">
<img src="images/bgLMI2u.png">
<br/>
<i><a href=http://robertgreiner.com/2014/08/cap-theorem-revisited>Kaynak: CAP theorem revisited</a></i>
</p>
Dağıtılmış bir bilgisayar sisteminde aynı anda yalnızca aşağıdaki iki nokta karşılanabilir:
* **Tutarlılık** ─ Her okuma, en güncel yazıyı veya bir hatayı alır.
* **Ulaşılabilirlik** ─ Her istek bir yanıt alır, ancak bu yanıtın en güncel bilgiyi içerme garantisi yoktur.
* **Bölüm Toleransı** ─ Sistem, ağ hatalarından kaynaklanan keyfi bölünmelere rağmen çalışmaya devam eder.
*Ağlar güvenilir değil, bu nedenle bölüm toleransını desteklemeniz gerekecektir. Tutarlılık ve erişilebilirlik arasında bir yazılım takası yapmanız gerekecektir.*
#### CP ─ Tutarlılık ve Bölüm Toleransı
Bölünmüş bir düğümden yanıt beklemek, bir zaman aşımı hatasına neden olabilir. CP, iş gereksinimleriniz atomik okuma ve yazma gerektiriyorsa iyi bir seçenektir.
#### AP ─ Kullanılabilirlik ve Bölüm Toleransı
Yanıtlar, herhangi bir düğümde bulunan en hızlı mevcut veri sürümünü döndürür, bu her zaman en güncel olmayabilir. Yazılar, bölüm çözüldüğünde yayılmak için bir süre alabilir.
AP, iş gereksinimlerinin [nihai tutarlılığı](#nihai-tutarlılık)na izin vermesi veya sistem dış hatalara rağmen çalışmaya devam etmesi gerekiyorsa iyi bir seçenektir.
### Kaynak(lar) ve ek okuma
* [CAP theorem revisited](http://robertgreiner.com/2014/08/cap-theorem-revisited/)
* [A plain english introduction to CAP theorem](http://ksat.me/a-plain-english-introduction-to-cap-theorem)
* [CAP FAQ](https://github.com/henryr/cap-faq)
* [The CAP theorem](https://www.youtube.com/watch?v=k-Yaq8AHlFA)
## Tutarlılık modelleri
Aynı verinin birden fazla kopyasıyla, bu verileri nasıl senkronize edeceğimize dair seçeneklerle karşılaşırız, böylece istemciler verilerin tutarlı bir görünümüne sahiptir. [CAP Teoremi](#cap-teoremi)ndeki tutarlılık tanımını hatırlayalım - Her okuma, en güncel yazıyı veya bir hatayı alır.
### Zayıf tutarlılık
Bir yazma işleminden sonra, okumalar bunu görebilir veya görmeyebilir. Burada bir çaba sarf edilir.
Bu yaklaşım, memcached gibi sistemlerde görülür. Zayıf tutarlılık, VoIP, video sohbet ve gerçek zamanlı çok oyunculu oyunlar gibi gerçek zamanlı kullanım durumlarında iyi çalışır. Örneğin, bir telefon görüşmesinde birkaç saniyeliğine bağlantı kaybı yaşarsanız, bağlantıyı tekrar sağladığınızda bağlantı kaybı sırasında söylenenleri duymazsınız.
### Nihai tutarlılık
Bir yazma işleminden sonra, okumalar bunu nihayetinde görecektir (genellikle milisaniyeler içinde). Veri asenkron olarak replike edilir.
Bu yaklaşım, DNS ve e-posta gibi sistemlerde görülür. Nihai tutarlılık, yüksek düzeyde erişilebilir sistemlerde iyi çalışır.
### Güçlü tutarlılık
Bir yazma işleminden sonra, okumalar bunu görecektir. Veri senkron olarak replike edilir.
Bu yaklaşım, dosya sistemleri ve RDBMS gibi sistemlerde görülür. Güçlü tutarlılık, işlemlere ihtiyaç duyan sistemlerde iyi çalışır.
### Kaynak(lar) ve ek okuma
* [Transactions across data centers](http://snarfed.org/transactions_across_datacenters_io.html)
## Kullanılabilirlik modları
Yüksek kullanılabilirliği destekleyen iki mod vardır: yük devretme(fail-over) ve çoğaltma(replication).
### Yük devretme
#### Aktif-pasif
Aktif-pasif yük devretme(fail-over) durumunda, aktif ve pasif durumda bekleyen sunucular arasında kalp atışları(heartbeats) gönderilir. Eğer kalp atışı kesilirse, pasif sunucu aktifin IP adresini devralır ve hizmete devam eder.
Downtime süresi, pasif sunucunun zaten 'sıcak' beklemede çalışıp çalışmadığına veya 'soğuk' beklemeden başlaması gerekip gerekmediğine bağlıdır. Trafik sadece aktif sunucuyu işler.
Aktif-pasif yük devretme(fail-over), aynı zamanda master-slave yük devretme(fail-over) olarak da adlandırılabilir.
#### Aktif-aktif
Aktif-aktif durumunda, her iki sunucu da trafik yönetir ve yükü aralarında paylaşır.
Eğer sunucular genel erişimliyse, DNS her iki sunucunun genel IP'lerini bilmelidir. Eğer sunucular içerideyse, uygulama mantığı her iki sunucuyu bilmelidir.
Aktif-aktif yük devretme(fail-over) aynı zamanda master-master yük devretme(fail-over) olarak da adlandırılabilir.
### Dezavantaj: Yük Devretme
* Fail-over, daha fazla donanım ekler ve ek karmaşıklık getirir..
* Aktif sistem başarısız olmadan önce yeni yazılan veriler pasife replike edilemezse veri kaybı potansiyeli bulunur.
### Çoğaltma
#### Master-slave ve master-master
Bu konu, [veritabanı](#veritabanı) bölümünde daha ayrıntılı olarak incelenmiştir:
* [Master-slave çoğaltma](#master-slave-çoğaltma)
* [Master-master çoğaltma](#master-master-çoğaltma)
### Sayılarla erişilebilirlik
Erişilebilirlik genellikle hizmetin kullanılabilir(veya kullanılamaz) olduğu sürenin bir yüzdesi olarak ölçülür. Genellikle erişilebilirlik, 9 sayısıyla ifade edilir - %99.99 erişilebilirliğe sahip bir hizmet, "4 tane 9'a sahip" olarak tanımlanabilir.
#### 99.9% erişilebilirlik - 3 tane 9'a sahip hizmet
| Süre | Kabul edilebilir kesinti süresi |
|-------------------|---------------------------------|
| Yıllık | 8h 45min 57s |
| Aylık | 43m 49.7s |
| Haftalık | 10m 4.8s |
| Günlük | 1m 26.4s |
#### 99.99% erişilebilirlik - 4 tane 9'a sahip hizmet
| Duration | Kabul edilebilir kesinti süresi |
|---------------|---------------------------------|
| Yıllık | 52min 35.7s |
| Aylık | 4m 23s |
| Haftalık | 1m 5s |
| Günlük | 8.6s |
#### Paralel ve sıralı erişilebilirlik
Bir hizmet, birden çok hataya duyarlı bileşenden oluşuyorsa, hizmetin genel erişilebilirliği, bileşenlerin sıralı mı yoksa paralel mi olduğuna bağlıdır.
###### Sıralı
Erişilebilirliği %100'den küçük iki bileşenin sıralı olduğu durumda toplam erişilebilirlik düşecektir:
```
Erişilebilirlik (Toplam) = Erişilebilirlik (Bileşen 1) * Erişilebilirlik (Bileşen 2)
```
Eğer "Bileşen 1" ve "Bileşen 2" %99.9 erişilebilirliğe sahiplerse toplam erişilebilirlik %99.8 olacaktır.
###### Paralel
Erişilebilirliği %100'den küçük iki bileşenin paralel olduğu durumda toplam erişilebilirlik artacaktır:
```
Erişilebilirlik (Toplam) = 1 - (1 - Erişilebilirlik (Bileşen 1)) * (1 - Erişilebilirlik (Bileşen 2))
```
Eğer "Bileşen 1" ve "Bileşen 2" %99.9 erişilebilirliğe sahiplerse toplam erişilebilirlik %99.9999 olacaktır.
## Alan Adı Sistemi (DNS)
<p align="center">
<img src="images/IOyLj4i.jpg">
<br/>
<i><a href=http://www.slideshare.net/srikrupa5/dns-security-presentation-issa>Kaynak: DNS security presentation</a></i>
</p>
Alan adı sistemi(DNS), www.example.com gibi alan adlarını IP adreslerine dönüştürür.
DNS hiyerarşik bir yapıya sahiptir ve en üst düzeyde birkaç yetkili sunucu bulunur. Modeminiz veya İSS'niz, bir sorgu yaparken hangi DNS sunucusuyla iletişim kurmanız gerektiği konusunda bilgi sağlar. Daha düşük seviyedeki DNS sunucuları eşlemeleri önbelleğe alır ve DNS yayılma gecikmeleri nedeniyle eski hale gelebilir. DNS sonuçları, [Time to Live TTL](https://en.wikipedia.org/wiki/Time_to_live) tarafından belirlenen belirli bir süre boyunca tarayıcınız veya işletim sisteminiz tarafından önbelleğe alınabilir.
* **Ad sunucuları(NS) kaydı (name server)** ─ Alanınız/alt alanınız için DNS sunucularını belirtir.
* **MX Kaydı (mail exchange)** ─ Mesajları alacak posta sunucusunu belirtir.
* **Kayıt (adres)** ─ Belirtilen alan adına karşılık gelen IP adresi kaydı.
* **CNAME (kanonik)** ─ Başka bir alan adı veya "CNAME" kaydıyla (example.com, www.example.com'u işaret eder) veya bir "A" kaydıyla eşleşen bir alan adı.
[CloudFlare](https://www.cloudflare.com/dns/) ve [Route 53](https://aws.amazon.com/route53/) gibi servisler, yönetilen DNS hizmetleri sağlar. Bazı DNS hizmetleri, trafiği çeşitli yöntemlerle yönlendirebilir:
* [ırlıklı round robin](https://www.jscape.com/blog/load-balancing-algorithms)
* Bakım altındaki sunuculara trafik gitmesini engelleme
* Farklı küme boyutları arasında denge sağlama
* A/B testi
* [Gecikme tabanlı](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-latency)
* [Coğrafi konum tabanlı](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-geo)
### Dezavantaj(lar): Alan adı sistemi(DNS)
* Bir DNS sunucusuna erişim, yukarıda açıklanan önbellekleme işlemlerinden dolayı hafif bir gecikmeye neden olabilir.
* DNS sunucu yönetimi karmaşık olabilir ve genellikle [hükümetler, İSS'ler ve büyük şirketler](http://superuser.com/questions/472695/who-controls-the-dns-servers/472729) tarafından yönetilir.
* DNS hizmetleri, [DDoS saldırısı](http://dyn.com/blog/dyn-analiz-summary-of-friday-october-21-attack/)na maruz kalabilir, bu da kullanıcıların Twitter gibi web sitelerine erişmesini Twitter'ın IP adres(ler)ini bilmeden engelleyebilir.
### Kaynak(lar) ve ek okuma
* [DNS architecture](https://technet.microsoft.com/en-us/library/dd197427(v=ws.10).aspx)
* [Wikipedia](https://en.wikipedia.org/wiki/Domain_Name_System)
* [DNS articles](https://support.dnsimple.com/categories/dns/)
## İçerik Dağıtım Ağı (CDN)
<p align="center">
<img src="images/h9TAuGI.jpg">
<br/>
<i><a href=https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/>Kaynak: Why use a CDN</a></i>
</p>
İçerik Dağıtım Ağı(CDN), kullanıcılara yakın konumlardan içerik sunan, küresel olarak dağıtılmış bir proxy sunucu ağıdır. Tipik olarak HTML/CSS/JS gibi statik içerikler, resimler ve videolar bir CDN tarafından sunulur, ancak bazı CDNler(örneğin Amazon'un CloudFront dağıtım ağı) dinamik içerik destekler. Sitenin DNS çözümlemesi, istemcilerin hangi sunucuyla iletişim kurması gerektiğini belirtir.
CDN'den içerik sunmak, performansı önemli ölçüde arttırır:
* Kullanıcılar içeriği kendilerine yakın veri merkezlerinden alır.
* Sunucularınız, CDN'nin karşıladığı istekleri karşılamak zorunda kalmaz.
### Push CDN
Push CDN'leri, sunucunuzda değişiklikler olduğunda yeni içerik alır. İçeriği sağlama, doğrudan CDN'ye yükleme ve URL'leri CDN'ye işaret etmek için yeniden yazma konusunda tam sorumluluk alırsınız. İçeriğin ne zaman süresinin dolduğunu ve ne zaman güncellendiğini yapılandırabilirsiniz. İçerik, yeni veya değiştiğinde yalnızca yüklenir, bu da trafiği en aza indirir, ancak depolamayı maksimize eder.
Düşük trafiğe sahip siteler veya içeriği sık güncellenmeyen siteler, push CDN'lerle iyi çalışır. İçerik, düzenli aralıklarla tekrar çekilmek yerine bir kez CDN'lere yerleştirilir.
### Pull CDN
Pull CDN'leri, ilk kullanıcı içeriği istediğinde yeni içeriği sunucunuzdan alır. İçeriği sunucunuzda bırakır ve URL'leri CDN'ye işaret etmek için yeniden yazarsınız. Bu, içerik CDN üzerinde önbelleğe alındığında daha yavaş bir isteğe neden olur.
[Yaşam süresi (TTL)](https://en.wikipedia.org/wiki/Time_to_live), içeriğin ne kadar süreyle önbelleğe alınacağını belirler. Pull CDN'leri, CDN üzerinde depolama alanını en aza indirir, ancak dosyaların süresi dolarsa ve gerçekte değiştirilmeden çekilirse gereksiz trafiğe neden olabilir.
Yüksek trafikli siteler, trafiği daha düzenli bir şekilde dağıttığı için pull CDN'lerle iyi çalışır. CDN'de yalnızca son zamanlarda istenen içerik kalır.
### Dezavantaj(lar): CDN
* CDN maliyetleri, trafiğe bağlı olarak önemli olabilir, ancak bu, CDN kullanmamanız durumunda karşılaşacağınız ek maliyetlerle karşılaştırılmalıdır.
* İçerik, TTL süresi dolmadan önce güncellenirse eski kalabilir.
* CDN'ler, statik içeriğin URL'lerini CDN'ye işaret etmek için değiştirmeyi gerektirir.
### Kaynak(lar) ve ek okuma
* [Globally distributed content delivery](https://figshare.com/articles/Globally_distributed_content_delivery/6605972)
* [The differences between push and pull CDNs](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)
* [Wikipedia](https://en.wikipedia.org/wiki/Content_delivery_network)
## Yük dengeleyici (Load balancer)
<p align="center">
<img src="images/h81n9iK.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Kaynak: Scalable system design patterns</a></i>
</p>
Yük dengeleyicileri, gelen istemci isteklerini uygulama sunucuları ve veritabanları gibi bilgi işlem kaynaklarına dağıtır. Her durumda, yük dengeleyici, bilgi işlem kaynağından gelen yanıtı uygun istemciye döndürür. Yük dengeleyicileri şu konularda etkilidir:
* İsteklerin hatalı sunuculara girmesini önlemek
* Kaynak aşırı yüklenmesini önlemek
* Tek hata noktalarını ortadan kaldırmaya yardımcı olmak
Yük dengeleyicileri, donanım (pahalı) veya HAProxy gibi yazılım ile uygulanabilir.
Ek avantajlar şunları içerir:
* **SSL Sonlandırma** ─ Gelen isteklerin şifresini çözer ve sunucu yanıtlarını şifreler, böylece arka uç sunucusunun(back-end) artık bu potansiyel olarak pahalı işlemleri gerçekleştirmesi gerekmez.
* Her sunucuya [X.509 sertifikasını](https://en.wikipedia.org/wiki/X.509) yüklemek gerekmez.
* **Oturum Tutma** ─ Web uygulaması oturumları izlemiyorsa, bir çerez yayınlar ve belirli istemci isteklerini aynı örneğe yönlendirir.
Hataları önlemek için [aktif-pasif](#aktif-pasif) veya [aktif-aktif](#aktif-aktif) modunda birden fazla yük dengeleyicinin kurulması yaygındır.
Yük dengeleyiciler trafiği çeşitli şekillerde yönlendirebilir:
* Rastgele (Random)
* En düşük yüklü (Least loaded)
* Oturum/çerez (Session/cookies)
* [Round robin or ağırlıklı round robin](https://www.g33kinfo.com/info/round-robin-vs-weighted-round-robin-lb)
* [Katman 4](#katman-4-yük-dengeleyicisi)
* [Katman 7](#katman-7-yük-dengeleyicisi)
### Katman 4 yük dengeleyicisi
Katman 4 yük dengeliyicileri, istekleri nasıl dağıtacaklarına karar vermek için [iletişim katmanındaki](#iletişim) bilgilere bakarlar. Genellikle, bu başlıkta bulunan kaynak, hedef IP adresleri ve portları içerir, ancak paketin içeriğini içermez. 4. Katman yük dengeleyicileri, ağ paketlerini yukarı akış sunucuya ve ondan yönlendirirken [Ağ Adresi Çevirisi (NAT)](https://www.nginx.com/resources/glossary/layer-4-load-balancing/) işlemini gerçekleştirirler.
### Katman 7 yük dengeleyicisi
Katman 7 yük dengeleyicileri, [uygulama katmanına](#iletişim) bakarak istekleri nasıl dağıtacaklarına karar verirler. Bu, başlık, mesaj ve çerez içeriğini içerebilir. Katman 7 yük dengeleyicileri, ağ trafiğini sonlandırır, mesajı okur, bir yük dengeleme kararı alır ve ardından seçilen sunucuya bir bağlantı açar. Örneğin, Katman 7 yük dengeleyici, video trafiğini videoları barındıran sunuculara yönlendirirken, daha hassas kullanıcı fatura trafiğini güvenlik açısından güçlendirilmiş sunuculara yönlendirebilir.
Esneklik maliyetine karşılık olarak, Katman 4 yük dengeleme, 7. Katmana göre daha az zaman ve hesaplama kaynağı gerektirir, ancak performans etkisi modern ticari donanımlarda minimal olabilir.
### Yatay ölçekleme
Yük dengeleyicileri, yatay ölçeklendirmeye de yardımcı olabilir, performansı ve erişilebilirliği artırabilir. Ticari makineler kullanarak ölçeklendirmek, daha pahalı donanımda tek bir sunucuyu ölçeklendirmekten daha uygun maliyet ve daha yüksek erişilebilirlik sağlar; bu duruma **dikey olarak ölçeklendirme** denir. Ayrıca, ticari donanımda çalışan yetenekleri bulmak, özel kurumsal sistemlerde çalışan yetenekleri bulmaktan daha kolaydır.
#### Dezavantaj(lar): yatay ölçekleme
* Yatay ölçeklendirme karmaşıklığa neden olur ve sunucunun çoğaltılmasını gerektirir.
* Sunucular durum bilgisiz olmalıdır: Ayrıca oturum veya profil resimleri gibi kullanıcıyla ilgili veriler içermemelidir.
* Oturumlar merkezi olarak veritabanında veya kalıcı [önbellek](#önbellek) (Redis, Memcached) veri depolama alanında saklanabilir.
* Önbellekler ve veritabanları gibi aşağı akış(downstream) sunucularının, daha fazla eş zamanlı bağlantıyı yönetebilmek için yukarı akış(upstream) sunucularıyla ölçeklendirilmesi gerekir.
### Dezavantaj(lar): Yük Dengeleyici
* Yeterli kaynak yapılandırılmazsa veya yanlış yapılandırılırsa yük dengeleyici performans darboğazı haline gelebilir.
* Tek hata noktalarını ortadan kaldırmaya yardımcı olmak için yük dengeleyiciler tanıtıldı ancak ek karmaşıklığa yol açtı.
* Tek bir yük dengeleyici tek bir hata noktası oluşturur ancak birden fazla yük dengeleyiciyi yapılandırmak daha fazla karmaşıklık katar.
### Kaynak(lar) ve ek okuma
* [NGINX architecture](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy architecture guide](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [Scalability](http://www.lecloud.net/post/7295452622/scalability-for-dummies-part-1-clones)
* [Wikipedia](https://en.wikipedia.org/wiki/Load_balancing_(computing))
* [Layer 4 load balancing](https://www.nginx.com/resources/glossary/layer-4-load-balancing/)
* [Layer 7 load balancing](https://www.nginx.com/resources/glossary/layer-7-load-balancing/)
* [ELB listener config](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html)
## Ters proxy (web sunucusu)
<p align="center">
<img src="images/n41Azff.png">
<br/>
<i><a href=https://upload.wikimedia.org/wikipedia/commons/6/67/Reverse_proxy_h2g2bob.svg>Kaynak: Wikipedia</a></i>
<br/>
</p>
Ters proxy, dahili hizmetleri merkezi olarak arayabilen ve genel istemcilere birleşik bir arayüz sağlayabilen bir web sunucusudur. İstemciden gelen istek, önce ters proxy sunucusu tarafından isteğe yanıt verebilecek sunucuya iletilir ve ardından proxy, sunucunun yanıt sonucunu istemciye döndürür.
Faydaları şunları içerir:
* **Artırılmış güvenlik** - Arka uç(backend) sunucu bilgilerini gizler, kara listedeki IP'leri engeller ve istemci başına bağlantı sayısını sınırlar.
* **Geliştirilmiş ölçeklenebilirlik ve esneklik** - İstemciler yalnızca ters proxy sunucusunun IP'sini görebilir, bu da sunucuları eklemenize veya kaldırmanıza veya yapılandırmalarını değiştirmenize olanak tanır.
* **SSL Oturumlarının Yerel Sonlandırılması** - Gelen isteklerin şifresini çözer ve sunucu yanıtlarını şifreler, böylece arka uç(backend) sunucusunun maliyetli olabilecek işlemleri tamamlamasına gerek kalmaz.
- Her sunucuya bir [X.509](https://en.wikipedia.org/wiki/X.509) sertifikası yükleme ihtiyacını ortadan kaldırır.
* **SIKIŞTIRMA** - Sunucu yanıtını sıkıştır.
* **Önbellek** - Doğrudan isabet önbellek sonucunu döndürür.
* **Statik İçerik** - Statik içeriği doğrudan yayınlar.
* HTML/CSS/JS
* Resimler
* Videolar
* vs
### Yük dengeleyici ve ters proxy
* Birden fazla sunucunuz olduğunda yük dengeleyici dağıtmak kullanışlıdır. Tipik olarak bir yük dengeleyici, trafiği aynı işlevselliğe sahip bir dizi sunucuya yönlendirir.
* Yalnızca bir web sunucusu veya uygulama sunucusu olduğunda bile ters proxy faydalıdır.Bir önceki bölümde tanıtılan avantajlara bakabilirsiniz.
* NGINX ve HAProxy gibi çözümler hem Katman 7 ters proxy'yi hem de yük dengelemeyi destekleyebilir.
### Dezavantaj(lar): Ters proxy
* Ters proxy'nin eklenmesi sistemin karmaşıklığını artıracaktır.
* Tek bir ters proxy sunucusu yine de tek bir hata noktası olabilir ve birden fazla ters proxy sunucusunun ([yük devretme(failover)](https://en.wikipedia.org/wiki/Failover) gibi) yapılandırılması karmaşıklığı daha da artıracaktır.
### Kaynak(lar) ve ek okuma
* [Reverse proxy vs load balancer](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)
* [NGINX architecture](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy architecture guide](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [Wikipedia](https://en.wikipedia.org/wiki/Reverse_proxy)
## Uygulama katmanı
<p align="center">
<img src="images/yB5SYwm.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Kaynak: Intro to architecting systems for scale</a></i>
</p>
Web hizmetleri katmanının uygulama katmanından (platform katmanı olarak da bilinir) ayırmak, her iki katmanı bağımsız olarak ölçeklendirmenize ve yapılandırmanıza olanak tanır. Yeni bir API eklemek, genellikle ek web sunucuları eklemeye gerek olmadan uygulama sunucularını eklemek anlamına gelir.
**Tek Sorumluluk İlkesi**, birbirleriyle birlikte çalışan küçük ve otonom hizmetleri savunur. Küçük ekipler, küçük hizmetlerle hızlı büyüme için daha agresif planlama yapabilirler.
Uygulama katmanındaki iş süreçleri aynı zamanda [asenkronizm](#asenkronizm)i mümkün kılar.
### Mikroservisler
Bu tartışma ile ilgili olan [mikroservisler](https://en.wikipedia.org/wiki/Microservices), bağımsız bir şekilde dağıtılabilen, küçük, modüler hizmetlerin bir paketidir. Her servis, bir iş hedefini karşılamak için iyi tanımlanmış, hafif bir mekanizma aracılığıyla iletişim kuran benzersiz bir süreç çalıştırır. <sup><a href=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
Örneğin, Pinterest aşağıdaki mikroservislere sahip olabilir: kullanıcı profili, takipçi, haber akışı, arama, fotoğraf yükleme, vb.
### Servis keşfi
[Consul](https://www.consul.io/docs/index.html), [Etcd](https://coreos.com/etcd/docs/latest) ve [Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) gibi sistemler, hizmetlerin kayıtlı isimlerini, adreslerini ve bağlantı noktalarını takip ederek birbirlerini bulmalarına yardımcı olabilir. [Sağlık kontrolü](https://www.consul.io/intro/getting-started/checks.html), hizmet bütünlüğünü doğrulamaya yardımcı olur ve genellikle bir [HTTP](#köprü-metni-aktarım-protokolü-http) uç noktası kullanılarak gerçekleştirilir. Hem Consul hem de Etcd, konfigürasyon değerleri ve diğer paylaşılan verileri depolamak için kullanışlı olabilen bir [anahtar-değer deposu](#anahtar-değer-deposu)na sahiptir.
### Dezavantaj(lar): Uygulama katmanı
* Gevşek bağlı hizmetlerle bir uygulama katmanı eklemek, mimari, işletme ve süreç açısından (monolitik bir sistemle karşılaştırıldığında) farklı bir yaklaşım gerektirir.
* Mikroservisler, dağıtımlar ve operasyonlar açısından karmaşıklığı arttırabilir.
### Kaynaklar ve ek okuma
* [Intro to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale)
* [Crack the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Service oriented architecture](https://en.wikipedia.org/wiki/Service-oriented_architecture)
* [Introduction to Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper)
* [Here's what you need to know about building microservices](https://cloudncode.wordpress.com/2016/07/22/msa-getting-started/)
## Veritabanı
<p align="center">
<img src="images/Xkm5CXz.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>Kaynak: Scaling up to your first 10 million users</a></i>
</p>
### İlişkisel veritabanı yönetim sistemi (RDBMS)
SQL gibi ilişkisel bir veritabanı, tablolar halinde düzenlenmiş veri öğelerinin bir koleksiyonudur.
**ACID**, ilişkisel veritabanı [işlemlerinin](https://en.wikipedia.org/wiki/Database_transaction) özelliklerini bir kümeyi ifade eder.
* **Atomluk (Atomicity)** - Her işlem tamamen gerçekleşir veya hiçbiri gerçekleşmez.
* **Tutarlılık (Consistency)** - Herhangi bir işlem, veritabanını bir geçerli durumdan başka bir geçerli duruma getirir.
* **İzolasyon (Isolation)** - İşlemlerin eşzamanlı yürütülmesinin sonuçları, işlemlerin sıralı yürütülmesinin sonuçlarıyla aynıdır.
* **Dayanıklılık (Durability)** - Bir işlem gerçekleştirildikten sonra sistem üzerindeki etkisi kalıcı olur.
İlişkisel bir veritabanını ölçeklendirmek için birçok teknik vardır: **master-slave çoğaltma**, **master-master çoğaltma**, **federasyon**, **parçalama**, **denormalizasyon** ve **SQL Tuning**.
#### Master-slave çoğaltma
Master sunucu, okuma ve yazma hizmeti sunar, yazma işlemlerini bir veya daha fazla slave sunucalara replike eder ve slave sunucular yalnızca okuma işlemleri sunar. Slave sunucular aynı zamanda daha fazla slave sunucuya ağaç benzeri bir şekilde replike edebilir. Master sunucu çevrimdışıysa; bir slave sunucu, ana bilgisayar olarak atanana veya yeni bir master sunucu tahsis edilene kadar; sistem okuma modunda çalışmaya devam edebilir.
<p align="center">
<img src="images/C9ioGtn.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Kaynak: Scalability, availability, stability, patterns</a></i>
</p>
##### Dezavantaj(lar): master-slave çoğaltma
* Bir slave sunucuyu, master sunucuya yükseltmek ek bir iş gerektirir.
* Master-slave çoğaltma ve master-master çoğaltma ile ilgili bilgiler için [Dezavantaj(lar): çoğaltma] (#dezavantajlar-çoğaltma) bölümüne bakınız.
#### Master-master çoğaltma
Her iki ana sunucu da okuma ve yazma işlemlerinden sorumludur ve yazma işlemleri sırasında birbirleriyle koordineli çalışırlar. Ana sunuculardan biri kapanırsa sistem okumaya ve yazmaya devam edebilir.
<p align="center">
<img src="images/krAHLGg.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Kaynak: Scalability, availability, stability, patterns</a></i>
</p>
##### Dezavantaj(lar): master-master
* Hangi veritabanına yazacağınızı belirlemek için yük dengeleyiciye(load balancer) veya uygulama mantığınızda değişiklik yapmanız gerekecektir.
* Çoğu master-master sistem ya tutarlılığı garanti edemez (ACID'i ihlal eder) veya senkronizasyon nedeniyle artan yazma gecikmesine sahiptir.
* Yazma düğümleri(write nodes) ekledikçe ve gecikme arttıkça çatışma çözümü daha fazla devreye girer.
* Master-slave çoğaltma ve master-master çoğaltma ile ilgili bilgiler için [Dezavantaj(lar): çoğaltma] (#dezavantajlar-çoğaltma) bölümüne bakınız.
##### Dezavantaj(lar): çoğaltma
* Yeni yazılan verileri diğer düğümlere kopyalanamadan önce master sunucu kapanırsa veri kaybı olasılığı vardır.
* Yazma işlemleri, okuma işleminden sorumlu kopyaya yeniden dağıtılır. Aşırı yazma işlemleri nedeniyle slave sunucular etkilenebilir ve bu da okuma işlemlerine engel olabilir.
* Ne kadar çok slave sunucu var ise o kadar çoğaltma işlemi yapılması gerekir, bu da ciddi gecikme sorunlarına sebep verecektir.
* Bazı veritabanı sistemlerinde master sunucuya yazma işlemi birden fazla iş parçacığı kullanılarak paralel olarak yazılabilir ancak slave sunucu yalnızca tek iş parçacıklı sıralı yazmayı destekler.
* Çoğaltma, daha fazla donanım ve ek karmaşıklık anlamına gelir.
##### Kaynak(lar) ve ek okuma
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [Multi-master replication](https://en.wikipedia.org/wiki/Multi-master_replication)
#### Federasyon
<p align="center">
<img src="images/U3qV33e.png">
<br/>
<strong><a href="https://www.youtube.com/watch?v=w95murBkYmU">Kaynak: Kullanıcılarınızı İlk On Milyona Kadar Ölçeklendirme</a></strong>
</p>
Federasyon (veya fonksiyonel bölümleme), veritabanını ilgili işlevlere göre böler. Örneğin, tek bir veritabanı yerine üç veritabanınız olabilir: **forumlar**, **kullanıcılar** ve **ürünler**; böylece veritabanı başına okuma ve yazma trafiğini ve çoğaltma gecikmesini azaltırsınız. Daha küçük bir veritabanı, belleğe sığan daha fazla veri anlamına gelir; bu da daha yüksek önbellek isabeti şansı anlamına gelir. Sadece seri olarak yazabilen merkezi bir master sunucu yoktur, yük kapasitesini arttırmak için paralel olarak yazabilirsiniz.
##### Dezavantaj(lar): federasyon
* Veritabanı şemanız çok sayıda işlev ve veri tablosu gerektiriyorsa, federasyon iyi değildir.
* Hangi veritabanından okunacağını ve hangi veritabanına yazılacağını belirlemek için uygulamanızın mantığını güncellemeniz gerekir.
* İki veritabanından gelen veri güncellemelerini birleştirmek [sunucu bağlantısı](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers) ile daha karmaşıktır.
* Federasyon daha fazla donanım ve ek karmaşıklık gerektirir.
##### Kaynak(lar) ve ek okuma: federasyon
* [Scaling up to your first 10 million users](https://www.youtube.com/watch?v=kKjm4ehYiMs)
#### Parçalama
<p align="center">
<img src="images/wU8x5Id.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Kaynak: Scalability, availability, stability, patterns</a></i>
</p>
Parçalama, veriyi farklı veritabanları arasında dağıtan bir yöntemdir, böylece her bir veritabanı yalnızca verinin bir alt kümesini yönetebilir. Kullanıcı veritabanını örnek olarak alalım, kullanıcı sayısı arttıkça kümelere daha fazla parça(shard) eklenir.
[Federasyon](#federasyon)un avantajlarına benzer şekilde, parçalama daha az okuma ve yazma trafiği, daha az çoğaltma ve daha fazla önbellek isabeti sağlar. Ayrıca, genellikle sorguları hızlandırarak performansı artırır. Bir parça(shard) devre dışı kalırsa, diğer parçalar(shard) hala işlevseldir, ancak veri kaybını önlemek için bir tür çoğaltma eklemek isteyebilirsiniz. Federasyon gibi, yazıları seri hale getiren tek bir merkezi ana yoktur, bu da artan bir işlem hızıyla paralel olarak yazma imkanı sağlar.
Kullanıcı tablosunu parçalamak için yaygın yöntemler, kullanıcının soyadının baş harfi veya kullanıcının coğrafi konumu gibi faktörlere dayanmaktadır.
##### Dezavantaj(lar): parçalama
* Parçalamayı uygulamak için uygulama mantığını değiştirmeniz gerekebilir, bu da karmaşık SQL sorgularına yol açabilir.
* Makul olmayan parçalama, dengesiz veri yüküne yol açabilir. Örneğin sık erişilen kullanıcı verileri, kendi parçasının yükünün diğer parçalara göre daha fazla olmasına neden olacaktır.
* Yeniden dengeleme, ek karmaşıklık getirir. [Tutarlı hashing(Consistent hashing)](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)'e dayalı parçalama işlemleri, transfer edilen veri miktarını azaltabilir.
* Birden fazla parçadan veri birleştirmek daha karmaşıktır.
* Parçalama daha fazla donanım ve ek karmaşıklık gerektirir.
#### Kaynak(lar) ve ek okuma: parçalama
* [The coming of the shard](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)
* [Shard database architecture](https://en.wikipedia.org/wiki/Shard_(database_architecture))
* [Consistent hashing](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)
#### Denormalizasyon
Denormalizasyon, bazı yazma performansı kaybı karşılığında okuma performansını artırmaya çalışır. Pahalı birleştirme işlemlerini önlemek için; veriler, birden fazla tabloya yazılır. [PostgreSQL](https://en.wikipedia.org/wiki/PostgreSQL) ve Oracle gibi bazı ilişkisel veritabanları, gereksiz bilgileri depolamanın ve gereksiz kopyaları tutmanın işini yapan [materyalleştirilmiş görünümleri](https://en.wikipedia.org/wiki/Materialized_view) destekler.
Veriler, [federasyon](#federasyon) ve [parçalama](#parçalama) gibi teknikler kullanılarak dağıtıldığında, veri merkezleri arasında birleştirmeleri yönetmek karmaşıklığı daha da artırır. Denormalizasyon, bu tür karmaşık birleştirmeler için ihtiyacı ortadan kaldırabilir.
Çoğu sistemde, okuma işlemlerinin sıklığı, 100:1 ve hatta 1000:1 oranında, yazma işlemlerinden çok daha yüksektir. Karmaşık veritabanı birleştirmeleri gerektiren okuma işlemleri çok maliyetlidir ve disk işlemlerinde çok fazla zaman harcar.
##### Dezavantaj(lar): Denormalizasyon
* Tekrar eden(yinelenen) veri.
* Kısıtlamalar, bilgilerin gereksiz kopyalarının senkronize olmasına yardımcı olabilir, bu da veritabanı tasarımının karmaşıklığını artırır.
* Yoğun yazma yükü altındaki bir denormalize veritabanı, normalleştirilmiş karşıtına göre daha kötü performans gösterebilir.
##### Kaynak(lar) ve ek okuma: Denormalizasyon
* [Denormalization](https://en.wikipedia.org/wiki/Denormalization)
#### SQL ayarlama (SQL tuning)
SQL ayarlama geniş kapsamlı bir konudur ve bu konuyla ilgili pek çok [kitap](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning) yazılmıştır.
Sistem darboğazlarını(bottleneck) simüle etmek ve ortaya çıkarmak için **benchmark** ve **profile**'dan yararlanmak önemlidir.
* **Benchmark** - [ab](http://httpd.apache.org/docs/2.2/programs/ab.html) gibi araçları kullanarak yüksek yük durumlarını simüle eder.
* **Profile** - [Yavaş sorgu log(Slow query log)](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html) gibi araçları etkinleştirerek performans sorunlarının izlenmesine yardımcı olur.
Performans analizi(benchmarking) ve profilleme(profiling), aşağıdaki optimizasyonlara yönlendirebilir.
##### Şemayı sınırlandırın
* Hızlı erişim için MySQL, verileri diskteki bitişik bloklarda saklar.
* Sabit uzunluklu alanlar için `VARCHAR` yerine `CHAR` türünü kullanın.
* 'CHAR' hızlı, rastgele erişim için etkilidir. Eğer `VARCHAR` kullanıyorsanız, bir sonraki stringi okumak istiyorsanız öncelikle mevcut stringin sonuna kadar okumanız gerekir.
* Blog metni gibi büyük metin bloklarını depolamak için `TEXT` kullanın. `TEXT` ayrıca boolean aramalarına da izin verir. `TEXT` alanının kullanılması, diskte metin bloğunun yerini belirleyen bir işaretçinin saklanmasını gerektirir.
* 2^32 veya 4 milyara kadar daha büyük sayıları depolamak için `INT` kullanın.
* Para birimlerini saklamak için `DECIMAL` tipini kullanmak, kayan nokta gösterim hatalarını önler.
* Büyük `BLOBS`'leri depolamaktan kaçının, bunun yerine nesnenin alınabileceği konumu depolayın.
* `VARCHAR(255)`, bazı RDBMS'lerde bir baytın kullanımını maksimuma çıkaran bir 8 bit sayısında sayılabilecek en büyük karakter sayısıdır.
* [Arama performansını iyileştirmek](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performans-in-a-database-search) için geçerli senaryolarda `NOT NULL` kısıtlamalarını ayarlayın.
##### Doğru dizini kullanın
* Sorgulanan sütunlar ("SELECT", "GROUP BY", "ORDER BY", "JOIN") bir indekleme kullanıyorsa daha hızlı olacaktır.
* İndeksler genellikle veriyi sıralı tutan ve logaritmik zamanda aramalara, ardışık erişime, ekleme ve silmeye olanak tanıyan öz-dengeli [B-ağacı](https://en.wikipedia.org/wiki/B-tree) olarak temsil edilir.
* Bir indeks yerleştirmek, veriyi bellekte tutabilir ve daha fazla alan gerektirebilir.
* İndekslerin güncellenmesi gerektiğinden yazma işlemleri daha yavaş olabilir.
* Büyük miktarda veri yüklenirken indeksleri devre dışı bırakmak, verileri yüklemek ve ardından indeksleri yeniden oluşturmak daha hızlı olabilir.
##### Pahalı birleştirme işlemlerinden kaçının
* Performans gerekiyorsa [denormalizasyon](#denormalizasyon) yapılabilir.
##### Veri tablosunu bölün
* Tabloyu parçalayarak sıcak noktaları ayrı bir tabloya yerleştirmek, veriyi bellekte tutmaya yardımcı olabilir.
##### Sorgu önbelleğini ayarlayın
* Bazı durumlarda; [sorgu önbelleği](http://dev.mysql.com/doc/refman/5.7/en/query-cache), [performans sorunlarına](https://www.percona.com/blog/2016/10/12/mysql-5-7-performance-tuning-immediately-after-installation/) neden olabilir.
##### Kaynak(lar) ve ek okuma
* [Tips for optimizing MySQL queries](http://aiddroid.com/10-tips-optimizing-mysql-queries-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)
* [Slow query log](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)
### NoSQL
NoSQL, **anahtar-değer deposu**, **belge deposu**, **geniş sütun deposu** veya **grafik veritabanı** içinde temsil edilen veri öğelerinin bir koleksiyonudur. Veri denormalize edilmiş ve genellikle birleştirmeler uygulama kodu içinde yapılır. Çoğu NoSQL deposu gerçek ACID işlemlerine sahip değildir ve sonunda [nihai tutarlılık](#nihai-tutarlılık) lehine olur.
**BASE**, genellikle NoSQL veritabanlarının özelliklerini tanımlamak için kullanılır. [CAP teoremi](#cap-teoremi) ile karşılaştırıldığında BASE, tutarlılıktan ziyade kullanılabilirliği vurgular.
* **Temel Olarak Kullanılabilir** - sistem, kullanılabilirliği garanti eder.
* **Yumuşak durum** - sistem durumu, giriş yapılmasa bile zaman içinde değişebilir.
* **Nihai tutarlılık** - sistem, belirli bir süre içinde giriş almadığı takdirde zamanla tutarlı hale gelir.
[SQL veya NoSQL](#sql-veya-nosql) arasında seçim yapmanın yanı sıra, NoSQL veritabanı türlerinden hangisinin kullanım durumlarınıza en iyi uyduğunu anlamak da faydalıdır. Sonraki bölümde **anahtar-değer depoları**, **belge depoları**, **geniş sütun depoları** ve **grafik veritabanları**nı gözden geçireceğiz.
#### Anahtar-değer deposu
> Soyutlama: Hash tablosu
Anahtar/değer deposu, genellikle O(1) okuma ve yazma işlemlerine izin verir ve genellikle bellek veya SSD tarafından desteklenir. Veri deposu, anahtarları [sözlük sırasına göre](https://en.wikipedia.org/wiki/Lexicographical_order) tutabilir ve bu da anahtar aralıklarının verimli bir şekilde alınmasına olanak tanır. Anahtar-değer depoları, bir değerle ilişkilendirilmiş meta verilerin depolanmasına izin verebilir.
Anahtar-değer depoları yüksek performans sağlar ve genellikle basit veri modelleri veya hızla değişen veriler için kullanılır, örneğin bellekte tutulan önbellek katmanı. Yalnızca sınırlı bir işlem kümesi sundukları için, ek işlemler gerekiyorsa karmaşıklık uygulama katmanına kaydırılır.
Anahtar-değer deposu, belge deposu gibi daha karmaşık sistemlerin temelini oluşturur ve bazı durumlarda grafik veritabanı olarak da kullanılabilir.
#### Kaynak(lar) ve ek okuma
* [Key-value database](https://en.wikipedia.org/wiki/Key-value_database)
* [Disadvantages of key-value stores](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
* [Redis architecture](http://qnimate.com/overview-of-redis-architecture/)
* [Memcached architecture](https://adayinthelifeof.nl/2011/02/06/memcache-internals/)
#### Belge deposu
> Soyutlama: değerler olarak depolanan belgelerle anahtar-değer deposu
Bir belge deposu, belgeler (XML, JSON, ikili, vb.) etrafında odaklanmıştır, bir belge bir nesne için tüm bilgileri depolar. Belge depolar, belgenin kendi iç yapısına dayalı sorgular yapmak için API'lar veya bir sorgu dilini sağlar. *Not, birçok anahtar-değer deposu, bir değerin meta verileriyle çalışma özellikleri içerir, bu da bu iki depolama türü arasındaki çizgileri bulanıklaştırabilir.*
Kullanılan uygulamaya bağlı olarak belgeler, koleksiyonlar, etiketler, meta veriler veya dizinler tarafından düzenlenir. Belirli bir araya getirilebilecek veya gruplandırılabilecek olsa da belgeler, birbirinden tamamen farklı alanlara sahip olabilir.
[MongoDB](https://www.mongodb.com/mongodb-architecture) ve [CouchDB](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/) gibi bazı belge depoları ayrıca karmaşık sorguları gerçekleştirmek için bir SQL benzeri dil sağlar. [DynamoDB](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf), hem anahtar-değerleri hem de belgeleri destekler.
Belge depoları yüksek esneklik sağlar ve genellikle zaman zaman değişen verilerle çalışmak için kullanılır.
#### Kaynak(lar) ve ek okuma: belge deposu
* [Document-oriented database](https://en.wikipedia.org/wiki/Document-oriented_database)
* [MongoDB architecture](https://www.mongodb.com/mongodb-architecture)
* [CouchDB architecture](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/)
* [Elasticsearch architecture](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)
#### Geniş sütun deposu
<p align="center">
<img src="images/n16iOGk.png">
<br/>
<i><a href=http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html>Kaynak: SQL & NoSQL, a brief history</a></i>
</p>
> Soyutlama: İç içe geçmiş harita(nested map) `ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>`
Geniş sütun depolama biriminin temel veri birimi bir sütundur (ad/değer çifti). Bir sütun, sütun ailelerine (SQL tablosuna benzer) gruplanabilir. Süper sütun aileleri, sütun ailelerini daha da gruplar. Her sütuna bir satır anahtarıyla bağımsız olarak erişebilirsiniz ve aynı satır anahtarına sahip sütunlar bir satır oluşturur. Her değer, sürümleme ve çakışma çözümü için bir zaman damgası içerir.
Google, [Bigtable'ı](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) ilk geniş sütun depolama olarak tanıttı, bu da Hadoop ekosisteminde sıkça kullanılan açık kaynaklı [HBase](https://www.mapr.com/blog/in-third-look-hbase-architecture) ve Facebook tarafından geliştirilen [Cassandra](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html) üzerinde etkili oldu. BigTable, HBase ve Cassandra gibi depolama sistemleri anahtarları leksikografik(alfabetik) sırayla tutar, bu da seçici anahtar aralıklarının etkili bir şekilde alınmasına olanak tanır.
Geniş sütun depolamaları yüksek kullanılabilirlik ve ölçeklenebilirlik sunar. Genellikle çok büyük veri setleri için kullanılırlar.
##### Kaynak(lar) ve ek okuma: geniş sütun depolama
* [SQL & NoSQL, a brief history](http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html)
* [Bigtable architecture](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)
* [HBase architecture](https://www.edureka.co/blog/hbase-architecture/)
* [Cassandra architecture](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html)
#### Grafik veritabanı
<p align="center">
<img src="images/fNcl65g.png">
<br/>
<i><a href=https://en.wikipedia.org/wiki/File:GraphDatabase_PropertyGraph.png>Kaynak: Graph database</a></i>
</p>
> Soyutlama: grafik(graph)
Grafik veritabanlarında, her düğüm bir kayıtı temsil eder ve her yay bir düğüm arasındaki ilişkiyi ifade eder. Grafik veritabanları, birçok yabancı anahtar veya çoktan çoklu ilişkiyi temsil etmek için optimize edilmiştir.
Grafik veritabanları, sosyal ağ gibi karmaşık ilişkilere sahip veri modelleri için yüksek performans sunar. Nispeten yeni bir teknoloji olmalarına rağmen, henüz geniş çapta kullanılmamaktadırlar; bu nedenle geliştirme araçları ve kaynakları bulmak daha zor olabilir. Birçok grafik veritabanına yalnızca REST API'leri aracılığıyla erişilebilir.
##### Kaynak(lar) ve ek okuma: grafik
* [Graph database](https://en.wikipedia.org/wiki/Graph_database)
* [Neo4j](https://neo4j.com/)
* [FlockDB](https://blog.twitter.com/2010/introducing-flockdb)
#### Kaynak(lar) ve ek okuma: NoSQL
* [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)
* [Scalability](http://www.lecloud.net/post/7994751381/scalability-for-dummies-part-2-database)
* [Introduction to NoSQL](https://www.youtube.com/watch?v=qI_g07C_Q5I)
* [NoSQL patterns](http://horicky.blogspot.com/2009/11/nosql-patterns.html)
### SQL veya NoSQL
<p align="center">
<img src="images/wXGqG5f.png">
<br/>
<i><a href=https://www.infoq.com/articles/Transition-RDBMS-NoSQL/>Kaynak: Transitioning from RDBMS to NoSQL</a></i>
</p>
**SQL**'i seçme nedenleri:
* Yapılandırılmış veri
* Katı şema
* İlişkisel veri
* Karmaşık birleştirmelere ihtiyaç
* İşlemler
* Ölçeklendirme için açık kalıplar
* Mevcut kaynaklar daha zengindir: geliştiriciler, topluluklar, kod kitaplıkları, araçlar vb.
* İndeksleme ile aramalar çok hızlıdır
**NoSQL**'i seçme nedenleri:
* Yarı yapılandırılmış veri
* Dinamik veya esnek şema
* İlişkisel olmayan veri
* Karmaşık birleştirmelere ihtiyaç yok
* Birkaç terabayt (veya petabayt) veri depolama ihtiyacı
* Çok veri yoğun iş yükü
* IOPS için çok yüksek işlem kapasitesi
NoSQL'e uygun örnek veriler:
* Tıklama akışı ve günlük verilerinin hızlı alımı
* Sıralama veya puanlama verileri
* Geçici veriler, örneğin bir alışveriş sepeti
* Sıkça erişilen ('sıcak') tablolar
* Metadata/arama tabloları
##### Kaynak(lar) ve ek okuma: SQL veya NoSQL
* [Scaling up to your first 10 million users](https://www.youtube.com/watch?v=kKjm4ehYiMs)
* [SQL vs NoSQL differences](https://www.sitepoint.com/sql-vs-nosql-differences/)
## Önbellek
<p align="center">
<img src="images/Q6z24La.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Kaynak: Scalable system design patterns</a></i>
</p>
Önbellekleme, sayfa yükleme sürelerini iyileştirir ve sunucularınız ile veritabanlarınıza olan yükü azaltabilir. Bu modelde, yönlendirici önce isteğin daha önce yapılmış olup olmadığını kontrol eder ve önceki sonucu bulmaya çalışır, böylece gerçek yürütümü kaydetmeye çalışır.
Veritabanları, okuma ve yazma işlemlerinin bölümler arasında homojen bir şekilde dağılımından genellikle fayda sağlar. Popüler öğeler, dağılımı bozarak darboğazlara neden olabilir. Bir önbelleği bir veritabanının önüne koymak, düzensiz yükleri ve trafiğin ani artışlarını absorbe etmeye yardımcı olabilir.
### İstemci önbelleği
Önbellekler, istemci tarafında (işletim sistemi veya tarayıcı), [sunucu tarafında](#ters-proxy-web-sunucusu) veya ayrı bir önbellek katmanında bulunabilir.
### CDN önbelleği
[İçerik dağıtım ağları (CDNs)](#içerik-dağıtım-ağı-cdn) aynı zamanda bir önbellek türü olarak kabul edilir.
### Web sunucusu önbelleği
[Ters proxyler](#ters-proxy-web-sunucusu) ve ([Varnish](https://www.varnish-cache.org/)) gibi önbellekler, statik ve dinamik içerikleri doğrudan sunabilir. Web sunucuları ayrıca istekleri önbelleğe alabilir ve uygulama sunucularına başvurmadan yanıtları döndürebilir.
### Veritabanı önbelleği
Veritabanınız genellikle genel bir kullanım durumu için optimize edilmiş varsayılan bir yapılandırmada bir düzeyde önbelleği içerir. Bu ayarları belirli kullanım modelleri için ayarlamak, performansı daha da artırabilir.
### Uygulama önbelleği
Memcached ve Redis gibi in-memory önbellekler, uygulamanız ile veri depolama arasında bulunan anahtar-değer depolama sistemleridir. Veri RAM'de tutulduğundan, veri disk üzerinde depolandığı tipik veritabanlarından çok daha hızlıdır. RAM, diskten daha sınırlıdır, bu nedenle [önbellek geçersiz kılma algoritmaları](https://en.wikipedia.org/wiki/Cache_algorithms), örneğin [en az kullanılan (LRU)](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)), 'soğuk' girişleri geçersiz kılmaya ve 'sıcak' veriyi RAM'de tutmaya yardımcı olabilir.
Redis aşağıdaki ek özelliklere sahiptir:
* Kalıcılık seçeneği
* Sıralı kümeler ve listeler gibi yerleşik veri yapıları
İki ana kategoriye ayrılmış birden çok önbellek düzeyi vardır: **veritabanı sorguları** ve **nesneler**:
* Satır seviyesi
* Sorgu seviyesi
* Tamamen oluşturulmuş(fully-formed) serilenebilir(serializable) nesneler
* Tamamen işlenmiş(fully-rendered) HTML
Genel olarak dosya tabanlı önbelleğe alma işleminden kaçınmaya çalışmalısınız; çünkü bu, çoğaltmayı ve otomatik ölçeklendirmeyi zorlaştırır.
### Veritabanı sorgu düzeyinde önbellekleme
Veritabanını sorguladığınız her zaman, sorguyu bir anahtar olarak kullanın ve sonucu önbelleğe depolayın. Bu yaklaşımın süresi dolma sorunlarına neden olabilir:
* Karmaşık sorgularla önbelleğe alınmış sonuçları silmek zordur.
* Tablodaki bir öğe gibi bir veri parçası değiştirilirse, değiştirilen öğeyi içerebilecek önbelleğe alınmış tüm sonuçların silinmesi gerekir.
### Nesne düzeyinde önbellekleme
Verinizi, uygulama kodunuzdaki objeler gibi düşünün. Uygulamanın veritabanındaki verileri sınıf örneklerine veya veri yapılarına birleştirmesine izin verin:
* Nesnenin temel verileri değiştiyse nesneyi önbellekten silin.
* Asenkron işleme izin verin: çalışanlar, önbelleğe alınmış en son nesneleri kullanarak nesneleri birleştirin.
Önbellekleme için öneriler:
* Kullanıcı oturumları
* Tamamen render edilmiş web sayfaları
* Aktivite akışları
* Kullanıcı grafik verileri
### Önbellek ne zaman güncellenmeli
Önbellekte yalnızca sınırlı veri depolayabildiğiniz için, kullanım durumunuza uygun bir önbellek güncelleme stratejisi seçmeniz gerekir.
#### Cache-aside
<p align="center">
<img src="images/ONjORqk.png">
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>Kaynak: From cache to in-memory data grid</a></i>
</p>
Uygulama, bellekten okumak ve yazmaktan sorumludur. Önbellek, doğrudan bellekle bağlantısı/etkileşimi yoktur. Uygulama, aşağıdaki işlemleri gerçekleştirir:
* Önbellekte veriyi arar; veri, önbellekte bulunmadığı için "cache miss" durumu oluşur.
* Veritabanından veriyi yükler.
* Bulunan sonuçları önbellekte saklar.
* İhtiyacı olunan veriyi döndürür.
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
[Memcached](https://memcached.org/) genellikle bu şekilde kullanılır.
Önbelleğe eklenen veriler çok hızlı okunur. Önbellek moduna tembel yükleme de denir. Yalnızca istenen veriler önbelleğe alınır; bu, önbelleğin istenmeyen verilerle doldurulmasını önler.
##### Dezavantaj(lar): cache-aside
* Önbellekte olmayan verileri talep etmek, verileri almak için üç adım gerektirir ve bu da önemli gecikmelere neden olabilir.
* Veritabanındaki veriler güncellenirse önbellekteki veriler güncelliğini yitirir. Bu sorunun, TTL'nin önbellek güncellemelerini veya doğrudan yazma modunu zorlayacak şekilde ayarlanmasıyla hafifletilmesi gerekir.
* Bir düğüm başarısız olduğunda, onun yerini yeni bir düğüm alır, bu da gecikmeyi artırır.
#### Üzerine yazma (write-through)
<p align="center">
<img src="images/0vBc0hN.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Kaynak: Scalability, availability, stability, patterns</a></i>
</p>
Uygulama, önbelleği ana veri deposu olarak kullanır ve veriyi okuma ve yazma işlemlerini buraya gerçekleştirir, bu sırada önbellek, veritabanına okuma ve yazma işlemlerini gerçekleştirmekten sorumludur:
* Uygulama, önbelleğe giriş ekler/günceller.
* Önbellek, girişi senkron bir şekilde veri deposuna yazar.
* Geri dönüş.
Uygulama kodu:
```python
set_user(12345, {"foo":"bar"})
```
Önbellek kodu:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
Depolama ve yazma işlemleri nedeniyle, üzerine yazma yöntemi genel olarak çok yavaş bir işlemdir, ancak yeni yazılan verilerin okunması çok hızlıdır. Kullanıcılar genellikle veriyi okurken veriyi güncelleme sırasındaki gecikmeye daha toleranslıdır. Önbellekteki veriler eski değildir.
##### Dezavantaj(lar): üzerine yazma (write-through)
* Bir hata veya ölçeklendirme nedeniyle oluşturulan yeni düğümler, veritabanı güncellenene kadar önbelleğe alınmayacaktır. Cache-aside'in yanı sıra üzerine yazma yöntemini kullanmak, bu sorunu hafifletebilir.
* Yazılan verilerin çoğu hiç okunmayabilir, bu durum bir TTL ile minimize edilebilir.
#### Geri yazma (write-behind)
<p align="center">
<img src="images/rgSrvjG.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Kaynak: Scalability, availability, stability, patterns</a></i>
</p>
Geri yazma yönteminde, uygulama aşağıdaki adımları gerçekleştirir:
* Önbelleğe giriş ekler/günceller
* Girişi veri deposuna asenkron bir şekilde yazarak yazma performansını artırır
##### Dezavantaj(lar): geri yazma (write-behind)
* Önbelleğin içeriği veri deposuna yazılmadan; önbellek devre dışı bırakılırsa veri kaybı olabilir.
* Geri yazma yöntemini uygulamak, cache-aside veya üzerine yazma yöntemini uygulamaktan daha karmaşıktır.
#### Önbelleği önceden yenileme (refresh-ahead)
<p align="center">
<img src="images/kxtjqgE.png">
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>Kaynak: From cache to in-memory data grid</a></i>
</p>
Önbelleği, süresi dolmadan önce erişilen herhangi bir önbellek girişini; otomatik olarak yenileyecek şekilde yapılandırabilirsiniz.
Refresh-ahead, önbelleğin gelecekte hangi öğelere ihtiyaç duyulma olasılığını doğru bir şekilde tahmin edebiliyorsa, okuma işlemine göre daha az gecikmeye neden olabilir.
##### Dezavantaj(lar): önbelleği önceden yenileme (refresh-ahead)
* Gelecekte hangi öğelerin muhtemelen ihtiyaç duyulacağını doğru bir şekilde tahmin edememek, refresh-ahead olmadan daha düşük performansa neden olabilir.
### Dezavantaj(lar): önbellek
* Önbellek ile veritabanı gibi gerçek kaynak arasındaki tutarlılığı sürdürmek için [önbellek geçersiz kılma](https://en.wikipedia.org/wiki/Cache_algorithms) gerekebilir.
* Önbellek geçersiz kılma, zorlu bir sorundur ve önbelleği ne zaman güncellemek gerektiğiyle ilgili ek karmaşıklıklar içerir.
* Redis veya memcached gibi öğeleri eklemek gibi uygulama değişiklikleri yapmak gerekebilir.
### Kaynak(lar) ve ek okuma
* [From cache to in-memory data grid](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
* [Scalable system design patterns](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
* [Introduction to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale/)
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [Scalability](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
* [AWS ElastiCache strategies](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
* [Wikipedia](https://en.wikipedia.org/wiki/Cache_(computing))
## Asenkronizm
<p align="center">
<img src="images/54GYsSx.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Kaynak: Intro to architecting systems for scale</a></i>
</p>
Asenkron iş akışları, maliyetli işlemler için talep sürelerini azaltmaya yardımcı olur ve aksi takdirde içeride gerçekleştirilecek olan işlemleri iyileştirir. Ayrıca, verinin periyodik olarak bir araya getirilmesi gibi zaman alıcı işleri önceden gerçekleştirerek de yardımcı olabilir.
### Mesaj kuyrukları
Message queues, mesajları alır, tutar ve iletiler. Bir işlem, içeride yürütülmek için çok yavaşsa, aşağıdaki iş akışını kullanarak bir mesaj kuyruğu kullanabilirsiniz:
* Bir uygulama bir işi kuyruğa gönderir ve ardından kullanıcıya iş durumu bildirilir
* Bir çalışan (worker), işi kuyruktan alır, işler, ardından işin tamamlandığını bildirir.
Kullanıcı engellenmez ve iş arka planda işlenir. Bu süre zarfında istemci, görevin tamamlandığı gibi görünmesi için isteğe bağlı olarak küçük bir işlem yapabilir. Örneğin, bir tweet gönderiyorsanız, tweet hemen zaman akışınıza gönderilebilir, ancak tweet'iniz gerçekten tüm takipçilere ulaşması biraz zaman alabilir.
**Redis** basit bir mesaj aracı olarak kullanışlıdır, ancak mesajlar kaybolabilir.
**RabbitMQ** popülerdir, ancak 'AMQP' protokolüne uyum sağlamanızı ve kendi düğümlerinizi yönetmenizi gerektirir.
**Amazon SQS** yüksek gecikme süresine sahip olabilir ve mesajların iki kez teslim edilme olasılığı vardır.
### Görev kuyrukları
Görev kuyrukları, görevleri ve ilgili verileri alır, bunları çalıştırır ve ardından sonuçlarını teslim eder. Zamanlamayı destekleyebilirler ve hesaplama yoğun işleri arka planda çalıştırmak için kullanılabilirler.
**[Celery](https://docs.celeryproject.org/en/stable/)** planlamayı destekler ve Python desteği sunar.
### Back pressure
Eğer kuyruk önemli ölçüde büyümeye başlarsa, sıra boyutu bellek boyutunu aşabilir. Bu durum, önbellek kayıplarına, disk okumalarına ve hatta performansın yavaşlamasına neden olabilir. [Back pressure](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-press-when-overloaded.html), kuyruk boyutunu sınırlandırarak bize yardımcı olabilir. Böylece, yüksek düzeyde işlemlerin korunmasını sağlayarak kuyruk verimini ve iyi yanıt süresini artırabiliriz. Kuyruk dolu olduğunda, istemci bir Sunucu Meşgul veya HTTP 503 durum kodu alacak ve isteği daha sonra, belki de [üstel geri çekilme](https://en.wikipedia.org/wiki/Exponential_backoff) ile yeniden denemek üzere tekrar deneyebilir.
### Dezavantaj(lar): asenkronizm
* Maliyetsiz hesaplamalar ve gerçek zamanlı iş akışları gibi durumlar, senkron işlemler için daha uygun olabilir, çünkü kuyrukların eklenmesi gecikmelere ve karmaşıklığa neden olabilir.
### Kaynak(lar) ve ek okuma
* [It's all a numbers game](https://www.youtube.com/watch?v=1KRYH75wgy4)
* [Applying back pressure when overloaded](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
* [Little's law](https://en.wikipedia.org/wiki/Little%27s_law)
* [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)
## İletişim
<p align="center">
<img src="images/5KeocQs.jpg">
<br/>
<i><a href=http://www.escotal.com/osilayer.html>Kaynak: OSI 7 layer model</a></i>
</p>
### Köprü metni aktarım protokolü (HTTP)
HTTP, bir istemci ve bir sunucu arasında veri kodlama ve iletimi için bir yöntemdir. Bu, bir istek/yanıt protokolüdür: istemciler talepler gönderir ve sunucular taleplere ilişkin içerik ve tamamlama durumu bilgileri ile yanıtlar verir. HTTP, kendi içinde bağımsızdır, bu da taleplerin ve yanıtların birçok ara yönlendirici ve yük dengeleme, önbellekleme, şifreleme ve sıkıştırma işlemi yapan sunucu üzerinden geçmesine olanak tanır.
Temel bir HTTP isteği, bir fiil (metot) ve bir kaynak (nokta) içerir. Aşağıda yaygın HTTP fiilleri bulunmaktadır:
| Metotlar | Açıklama | Tekrarlanabilir* | Güvenli | Önbelleğe Alınabilir |
|----------|--------------------------------------------------------------|------------------|---------|--------------------------------------------------------|
| GET | Bir kaynağı okur | Evet | Evet | Evet |
| POST | Bir kaynak oluşturur veya veriyi işleyen bir süreci tetikler | Hayır | Hayır | Evet,eğer yanıt taze bilgi(freshness info) içeriyorsa |
| PUT | Bir kaynak yaratır veya değiştirir | Evet | Hayır | Hayır |
| PATCH | Bir kaynağı kısmen günceller | Hayır | Hayır | Evet,eğer yanıt taze bilgi(freshness info) içeriyorsa |
| DELETE | Bir kaynağı siler | Evet | Hayır | Hayır |
**Birden çok kez çağrılabilir, ve farklı sonuçlar elde edilmeyecektir.**.
HTTP, **TCP** ve **UDP** gibi alt düzey protokollere dayanan bir uygulama katmanı protokolüdür.
#### Kaynak(lar) ve ek okuma: HTTP
* [What is HTTP?](https://www.nginx.com/resources/glossary/http/)
* [Difference between HTTP and TCP](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)
* [Difference between PUT and PATCH](https://laracasts.com/discuss/channels/general-discussion/whats-the-differences-between-put-and-patch?page=1)
### İletim kontrol protokolü (TCP)
<p align="center">
<img src="images/JdAsdvG.jpg">
<br/>
<i><a href=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>Kaynak: How to make a multiplayer game</a></i>
</p>
TCP, [IP ağı](https://en.wikipedia.org/wiki/Internet_Protocol) üzerinde bağlantı odaklı bir protokoldür. [El Sıkışma](https://en.wikipedia.org/wiki/Handshaking) yöntemi kullanılarak bağlantı kurulur ve sonlandırılır. Gönderilen tüm veri paketlerinin hedefe orijinal sırasıyla, zarar görmeden ulaşması aşağıdaki maddeler ile garanti edilir:
* Her paket için sıra numaraları ve [checksum alanları](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation).
* [Onaylama](https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)) paketleri ve otomatik yeniden iletim
Eğer gönderici doğru bir yanıt almazsa, paketleri yeniden gönderir. Birden fazla zaman aşımı durumunda bağlantı kapatılır. TCP aynı zamanda [akış kontrolü](https://en.wikipedia.org/wiki/Flow_control_(data)) ve [tıkanıklık kontrolü](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control) de uygular. Bu garantiler gecikmelere neden olur ve genellikle UDP'den daha az verimli iletim sonuçları doğurur.
Yüksek verimlilik sağlamak için web sunucuları, büyük bir TCP bağlantısı sayısınıık tutabilir, bu da yüksek bellek kullanımına neden olabilir. Web sunucu iş parçacıkları ile örneğin bir [memcached](https://memcached.org/) sunucusu arasında çok sayıda açık bağlantıya sahip olmak maliyetli olabilir. [Bağlantı havuzu (connection pooling)](https://en.wikipedia.org/wiki/Connection_pool), uygun olan yerlerde UDP'ye geçişe ek olarak yardımcı olabilir.
TCP, yüksek güvenilirlik gerektiren ancak zaman açısından daha az kritik olan uygulamalar için kullanışlıdır. Bazı örnekler arasında web sunucuları, veritabanı bilgileri, SMTP, FTP ve SSH bulunur.
Aşağıdaki durumlarda UDP yerine TCP tercih ediniz:
* Tüm verilerin sağlam bir şekilde varmasına ihtiyacınız varsa.
* Ağ bant genişliğini otomatik olarak en iyi şekilde kullanmak istiyorsanız.
### Kullanıcı datagram protokolü (UDP)
<p align="center">
<img src="images/yzDrJtA.jpg">
<br/>
<i><a href=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>Kaynak: How to make a multiplayer game</a></i>
</p>
UDP bağlantısızdır. Datagramlar (paketlere benzer) yalnızca datagram düzeyinde garanti edilir. Datagramlar hedeflerine sırasız veya hiç ulaşmayabilir. UDP, tıkanıklık kontrolünü desteklemez. TCP'nin sunduğu garantiler olmadan, UDP genellikle daha verimlidir.
UDP, datagramları alt ağdaki tüm cihazlara göndererek yayın yapabilir. Bu, [DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) ile kullanışlıdır çünkü istemci henüz bir IP adresi almamıştır, bu nedenle TCP'nin IP adresi olmadan akış yapmasını engeller.
UDP daha az güvenilir olsa da, VoIP, video sohbet, yayın ve gerçek zamanlı çok oyunculu oyunlar gibi gerçek zamanlı kullanım durumlarında kullanışlıdır.
Aşağıdaki durumlarda TCP yerine UDP kullanın:
* Düşük gecikmeye ihtiyacınız var
* Verinin gecikmesi, veri kaybından daha önemli
* Kendi hata düzeltme yönteminizi uygulamak istiyorsunuz
#### Kaynak(lar) ve ek okuma: TCP ve UDP
* [Networking for game programming](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)
* [Key differences between TCP and UDP protocols](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)
* [Difference between TCP and UDP](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
* [Transmission control protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)
* [User datagram protocol](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [Scaling memcache at Facebook](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)
### Uzaktan yordam çağrısı (RPC)
<p align="center">
<img src="images/iF4Mkb5.png">
<br/>
<i><a href=http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview>Kaynak: Crack the system design interview</a></i>
</p>
Bir RPC'de, bir istemci genellikle uzak bir sunucuda olmak üzere farklı bir adres alanında bir prosedürün yürütülmesine neden olur. Prosedür, istemci programından sunucu ile iletişim kurma ayrıntılarını soyutlar şekilde kodlanmıştır, sanki yerel bir prosedür çağrısı gibi. Uzak çağrılar genellikle yerel çağrılardan daha yavaş ve güvenilir olabilir, bu nedenle RPC çağrılarını yerel çağrılardan ayırmak faydalıdır. Popüler RPC çerçeveleri arasında [Protobuf](https://developers.google.com/protocol-buffers/), [Thrift](https://thrift.apache.org/) ve [Avro](https://avro.apache.org/docs/current/) bulunmaktadır.
RPC, bir istek-yanıt protokolüdür:
* **İstemci program** - İstemci tanımlama prosedürünü çağırır. Parametreler, yerel bir prosedür çağrısı gibi yığına itilir.
* **İstemci tanımlama prosedürü** ─ Prosedür kimliğini ve argümanları bir istek mesajına paketler (marshal).
* **İstemci iletişim modülü** ─ İşletim sistemi, mesajı istemciden sunucuya gönderir.
* **Sunucu iletişim modülü** ─ İşletim sistemi, gelen paketleri sunucu tanımlama prosedürüne iletilir.
* **Sunucu tanımlama prosedürü** ─ Sonuçları açar (unmarshal), prosedür kimliği ile eşleşen sunucu prosedürünü çağırır ve verilen argümanları iletilir.
* Sunucu yanıtı, yukarıdaki adımları ters sırayla tekrarlar.
* Örnek RPC çağrısı:
```
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
```
RPC, davranışları ortaya çıkarmaya odaklanmıştır. RPC'ler, genellikle iç iletişimde performans nedenleriyle kullanılır, çünkü kullanım durumlarınıza daha iyi uyan özelleştirilmiş çağrıları el ile oluşturabilirsiniz.
Aşağıdaki durumlarda yerel kitaplığı (yani SDK'yı) seçin:
* Hedef platformunuzu biliyorsunuz.
* "Mantığınızın" nasıl erişileceğini kontrol etmek istiyorsunuz.
* Kitaplığınızda oluşan hatalar üzerinde kontrol sahibi olmak istiyorsunuz.
* Performans ve kullanıcı deneyimi birincil endişeniz.
**REST** uyumlu HTTP API'ları, genellikle genel API'lar için daha sık kullanılır.
#### Dezavantajları: RPC
* RPC istemcileri, servis uygulamasına sıkı bir şekilde bağlı olur.
* Her yeni işlem veya kullanım durumu için yeni bir API tanımlanmalıdır.
* RPC'de hata ayıklanması(debug) zordur.
* Mevcut teknolojiyi kolayca değiştiremeyebilirsiniz. Örneğin, [RPC çağrılarının önbelleğe alınmasının](http://etherealbits.com/2012/12/); [Squid](http://www.squid-cache.org/) gibi bir önbellek sunucularında) uygun bir şekilde yapılması ek çaba gerekebilir.
### Temsili Durum Transferi (REST)
REST, bir istemci/sunucu modelini zorlayan bir mimari tarzıdır, burada istemci, sunucu tarafından yönetilen bir dizi kaynak üzerinde işlem yapar. Sunucu, kaynakların temsilini sağlar ve kaynakları ya manipüle edebilen ya da yeni bir temsil alabilen eylemleri içerir. Tüm iletişim durumsuz ve önbelleğe alınabilir olmalıdır.
RESTful arayüzün dört temel özelliği vardır:
* **Kaynakları tanımlama (HTTP'deki URI)** - herhangi bir işlemle ilgili olmaksızın aynı URI'yi kullanır.
* **Temsillemelerle değiştirme (HTTP'deki metotlar)** - metotları, başlıkları ve gövdeyi kullanır.
* **Kendi açıklamalı(Self-descriptive) hata mesajları (HTTP'deki durum yanıtları)** - Durum kodlarını kullanır, tekerleği yeniden icat etmeyin.
* **[HATEOAS](http://restcookbook.com/Basics/hateoas/) (HTTP için HTML arayüzü)** - Web servisiniz tarayıcıda tamamen erişilebilir olmalıdır.
Örnek REST isteği:
```
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
```
REST, veri sunmaya odaklanmıştır. İstemci/sunucu arasındaki bağı minimuma indirir ve genellikle genel HTTP API'leri için kullanılır. REST, kaynakları URI'lar aracılığıyla, [başlıklar](https://github.com/for-GET/know-your-http-well/blob/master/headers.md) aracılığıyla temsil edilme ve GET, POST, PUT, DELETE ve PATCH gibi metotlar aracılığıyla metotları açma konusunda daha genel ve birleşik bir yöntem kullanır. Durum bilgisi olmayan(stateless) yapısı nedeniyle, REST yatay ölçeklendirme ve bölütleme için uygundur.
#### Dezavantaj(lar): REST
* REST, veri sunmaya odaklandığından, kaynaklar doğal olarak düzenlenmiyorsa veya basit bir hiyerarşi içinde erişilmiyorsa iyi bir tercih olmayabilir. Örneğin, belirli bir etkinlik kümesiyle eşleşen son bir saat içinde güncellenmiş tüm kayıtları döndürmek, kolayca bir yol olarak ifade edilemez. REST ile muhtemelen URI yolu, sorgu parametreleri ve belki de istek gövdesinin bir kombinasyonuyla uygulanacaktır.
* REST genellikle kullanım durumunuza uymayan birkaç metoda (GET, POST, PUT, DELETE ve PATCH) dayanır. Örneğin, süresi dolmuş belgeleri arşiv klasörüne taşımak, bu metotların içine temiz bir şekilde sığmayabilir.
* Karmaşık kaynakları iç içe geçmiş hiyerarşilerle almak, tek bir görünümü oluşturmak için istemci ve sunucu arasında çok sayıda tur yapmayı gerektirir; örneğin, bir blog girişinin içeriğini ve o giriş üzerindeki yorumları almak vs. Değişken ağ koşullarında çalışan mobil uygulamalar için bu çoklu tur işlemleri istenmeyen durumlardır.
* Zamanla, bir API yanıtına daha fazla alan eklenebilir ve eski istemciler tüm yeni veri alanlarını, ihtiyaç duymadıkları halde alacakları için veri boyutunu şişirir.
### RPC ve REST karşılaştırması
| İşlem | RPC | REST |
|--------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------|
| Kayıt ol | **POST** /signup | **POST** /persons |
| Ayrıl | **POST** /resign<br/>{<br/>"personid": "1234"<br/>} | **DELETE** /persons/1234 |
| Bir kişinin bilgilerini okuma | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| Bir kişinin öğe listesini oku | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| Bir kişinin öğelerine öğe ekle | **POST** /addItemToUsersItemsList<br/>{<br/>"personid": "1234";<br/>"itemid": "456"<br/>} | **POST** /persons/1234/items<br/>{<br/>"itemid": "456"<br/>} |
| Bir öğeyi güncelle | **POST** /modifyItem<br/>{<br/>"itemid": "456";<br/>"key": "value"<br/>} | **PUT** /items/456<br/>{<br/>"key": "value"<br/>} |
| Bir öğeyi sil | **POST** /removeItem<br/>{<br/>"itemid": "456"<br/>} | **DELETE** /items/456 |
<p align="center">
<i><a href=https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/>Kaynak: Do you really know why you prefer REST over RPC</a></i>
</p>
#### Kaynak(lar) ve ek okuma: REST ve RPC
* [Do you really know why you prefer REST over RPC](https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/)
* [When are RPC-ish approaches more appropriate than REST?](http://programmers.stackexchange.com/a/181186)
* [REST vs JSON-RPC](http://stackoverflow.com/questions/15056878/rest-vs-json-rpc)
* [Debunking the myths of RPC and REST](http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)
* [What are the drawbacks of using REST](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)
* [Crack the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Thrift](https://code.facebook.com/posts/1468950976659943/)
* [Why REST for internal use and not RPC](http://arstechnica.com/civis/viewtopic.php?t=1190508)
## Güvenlik
Bu bölümün biraz değiştirilmeye ihtiyacı var. [Katkı yapmayı değerlendirebilirsiniz](#katkı)!
Güvenlik geniş bir konudur. Eğer önemli bir deneyiminiz yoksa, güvenlik geçmişiniz yoksa veya güvenlik bilgisi gerektiren bir pozisyon için başvuruda bulunmuyorsanız, muhtemelen temel bilgilerden daha fazlasını bilmeye ihtiyaç duymayacaksınız:
* İletim ve dinlenme sırasında şifreleme kullanın.
* [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) ve [SQL enjeksiyonunu](https://en.wikipedia.org/wiki) önlemek için tüm kullanıcı girdilerini veya kullanıcıya açık parametreleri gizleyin.
* SQL enjeksiyonunu önlemek için parametreli sorgular kullanın.
* [En az ayrıcalık ilkesi](https://en.wikipedia.org/wiki/Principle_of_least_privilege)ni kullanın.
### Kaynak(lar) ve ek okuma
* [API security checklist](https://github.com/shieldfy/API-Security-Checklist)
* [Security guide for developers](https://github.com/FallibleInc/security-guide-for-developers)
* [OWASP top ten](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
## Ek
Bazen sizden geçerli tahminler yapmanız istenecektir. Örneğin, diskten 100 görüntünün küçük resimlerini oluşturmanın ne kadar süreceğini veya bir veri yapısının ne kadar bellek gerektireceğini tahmin etmeniz gerekebilir. **İkinin kuvveti tablosu** ve **Her geliştiricinin bilmesi gereken bazı zaman verileri** bazı kullanışlı referans materyalleridir.
### İkinin kuvveti tablosu
```
Kuvvet Gerçek değer Yaklaşık değer Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
```
#### Kaynak(lar) ve ek okuma
* [Powers of two](https://en.wikipedia.org/wiki/Power_of_two)
### Her programcının bilmesi gereken gecikme sayıları
```
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from disk 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
```
Yukarıdaki sayılar temelinde kullanışlı ölçümler:
* HDD'den sıralı okuma hızı: 30 MB/s
* 1 Gbps Ethernet üzerinden sıralı okuma hızı: 100 MB/s
* SSD'den sıralı okuma hızı: 1 GB/s
* Ana bellekten sıralı okuma hızı: 4 GB/s
* Dünya çapında 6-7 tur/saniye arası dolaşımlar
* Bir veri merkezi içinde 2,000 tur/saniye dolaşımlar
#### Gecikme numarası görselleştirmesi
![](https://camo.githubusercontent.com/77f72259e1eb58596b564d1ad823af1853bc60a3/687474703a2f2f692e696d6775722e636f6d2f6b307431652e706e67)
#### Kaynak(lar) ve ek okuma
* [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)
### Diğer sistem tasarımı mülakat soruları
> Genel sistem tasarımı mülakat soruları, ve çözümleri
| Soru | Kaynak(lar) |
|------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Dropbox benzeri bir dosya senkronizasyon hizmeti tasarlayın | [youtube.com](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| Google benzeri bir arama motoru tasarlayın | [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) |
| Google benzeri ölçeklenebilir web tarayıcısı(scalable web crawler) tasarlayın | [quora.com](https://www.quora.com/How-can-I-build-a-web-crawler-from-scratch) |
| Google Dokümanlar'ı tasarlama | [code.google.com](https://code.google.com/p/google-mobwrite/)<br/>[neil.fraser.name](https://neil.fraser. ad/yazma/senkronizasyon/) |
| Redis benzeri anahtar-değer(key-value) deposu tasarlayın | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| Memcached'e benzer önbellekleme sistemi tasarlayın | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| Amazon'a benzer öneri sistemi tasarlayın | [hulu.com](http://tech.hulu.com/blog/2011/09/19/recommendation-system.html)<br/>[ijcai13.org](http : //ijcai13.org/files/tutorial_slides/td3.pdf) |
| Bitly'ye benzer kısa bağlantı sistemi tasarlayın | [n00tc0d3r.blogspot.com](http://n00tc0d3r.blogspot.com/) |
| WhatsApp gibi sohbet uygulaması tasarlayın | [highscalability.com](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| Instagram'a benzer fotoğraf paylaşım sistemi tasarlayın | [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) |
| Facebook'un haber öneri yöntemini tasarlama | [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) |
| Facebook'un zaman çizelgesi sistemini tasarlama | [facebook.com](https://www.facebook.com/note.php?note_id=10150468255628920)<br/>[highscalability.com](http://highscalability.com/ blog/ 2012/1/23/facebook-zaman çizelgesi-denormaliza.html'nin-gücüyle-size-getirildi) |
| Facebook'un sohbet sistemini tasarlayın | [erlang-factory.com](http://www.erlang-factory.com/upload/sunumlar/31/EugeneLetuchy-ErlangatFacebook.pdf)<br/>[facebook.com](https : //www.facebook.com/note.php?note_id=14218138919&id=9445547199&index=0) |
| Facebook benzeri grafik arama sistemi tasarlayın | [facebook.com](https://www.facebook.com/notes/facebook-engineering/under-the-hood-building-out-the-infrastructure-for-graph- arama /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) |
| CloudFlare gibi içerik dağıtım ağı tasarlama | [cmu.edu](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci) |
| Twitter'a benzer trend konu sistemi tasarlama | [michael-noll.com](http://www.michael-noll.com/blog/2013/01/18/implementing-real-time-trending-topics-in- fırtına /)<br/>[snikolov .wordpress.com](http://snikolov.wordpress.com/2012/11/14/early-detection-of-twitter-trends/) |
| Rastgele bir kimlik oluşturma sistemi tasarlayın | [blog.twitter.com](https://blog.twitter.com/2010/announcing-snowflake)<br/>[github.com](https://github.com/ twitter/kar tanesi/) |
| Belirli bir süre içinde en sık yapılan k isteklerini döndürün | [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) |
| Birden çok veri merkezinden gelen verilerle bir hizmet sistemi tasarlayın | [highscalability.com](http://highscalability.com/blog/2009/8/24/how-google-serves-data-from-multiple-datacenters.html) |
| Çok oyunculu çevrimiçi kart oyunu tasarlayın | [indieflashblog.com](https://web.archive.org/web/20180929181117/http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer- game.html)<br/>[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| Borsa sistemi tasarlayın | [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) |
| Daha fazla sistem tasarımı sorunu ekleyin<br/> | [katkı](#katkı) |
### Gerçek dünya mimarileri
> Sistemlerin gerçekte nasıl tasarlandığına dair makaleler.
<p align="center">
<img src="images/TcUo2fw.png">
<br/>
<i><a href=https://www.infoq.com/presentations/Twitter-Timeline-Scalability>Kaynak: Twitter timelines at scale</a></i>
</p>
**Aşağıdaki makalenin ayrıntılarına odaklanmayın, onun yerine bunlara odaklanın:**
* Bu makalelerdeki ortak ilkeleri, teknikleri ve kalıpları keşfedin
* Her bileşenin hangi sorunları çözdüğünü, ne zaman kullanılacağını ve ne zaman kullanılamayacağını öğrenin
* Öğrendiklerinizi tekrar gözden geçirin
| Tür | Sistem | Referans(lar) |
|---------------|------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|
| Veri işleme | **MapReduce** - Google'da dağıtık veri işleme | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/mapreduce-osdi04.pdf) |
| Veri işleme | **Spark** - Databricks'te dağıtık veri işleme | [slideshare.net](http://www.slideshare.net/AGrishchenko/apache-spark-architecture) |
| Veri işleme | **Storm** - Twitter'da dağıtık veri işleme | [slideshare.net](http://www.slideshare.net/previa/storm-16094009) |
| | | |
| Veri deposu | **Bigtable** - Google'da dağıtık sütun-tabanlı(column-oriented) veritabanı | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) |
| Veri deposu | **HBase** - Bigtable'ın açık kaynak kodu | [slideshare.net](http://www.slideshare.net/alexbaranau/intro-to-hbase) |
| Veri deposu | **Cassandra** - Facebook'ta dağıtık sütun-tabanlı(column-oriented) veritabanı | [slideshare.net](http://www.slideshare.net/planetcassandra/cassandra-introduction-features-30103666) |
| Veri deposu | **DynamoDB** - Amazon'da doküman-tabanlı(document-oriented) veritabanı | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) |
| Veri deposu | **MongoDB** - Doküman-tabanlı(document-oriented) veritabanı | [slideshare.net](http://www.slideshare.net/mdirolf/introduction-to-mongodb) |
| Veri deposu | **Spanner** - Google'da küresel(globally-distributed) dağıtılmış veritabanı | [research.google.com](http://research.google.com/archive/spanner-osdi2012.pdf) |
| Veri deposu | **Memcached** - Dağıtık bellek önbellek sistemi | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| Veri deposu | **Redis** - Kalıcılık ve değer türleri ile dağıtık önbellekleme(distributed caching) sistemi | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| | | |
| Dosya sistemi | **Google File System (GFS)** - Dağıtık dosya sistemi | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/gfs-sosp2003.pdf) |
| Dosya sistemi | **Hadoop File System (HDFS)** - GFS'in açık kaynak kodu | [apache.org](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html) |
| | | |
| Diğer | **Chubby** - Google'dan gevşek bağlı dağıtık sistemler için kilit hizmeti | [research.google.com](http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/archive/chubby-osdi06.pdf) |
| Diğer | **Dapper** - Dağıtık sistemler izleme altyapısı | [research.google.com](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf) |
| Diğer | **Kafka** - LinkedIn'de yayın/abone mesaj kuyruğu | [slideshare.net](http://www.slideshare.net/mumrah/kafka-talk-tri-hug) |
| Diğer | **Zookeeper** - Senkronizasyonu sağlayan merkezi altyapı ve hizmetler | [slideshare.net](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) |
| | Daha fazla yazılım mimari örneği ekleyin | [katkı](#katkı) |
### Şirketlerin sistem mimarileri
| Şirket | Referans(lar) |
|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Amazon | [Amazon architecture](http://highscalability.com/amazon-architecture) |
| Cinchcast | [Producing 1,500 hours of audio every day](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html) |
| DataSift | [Realtime datamining At 120,000 tweets per second](http://highscalability.com/blog/2011/11/29/datasift-architecture-realtime-datamining-at-120000-tweets-p.html) |
| Dropbox | [How we've scaled Dropbox](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| 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: Facebooks 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/>[Facebooks photo storage](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf)<br/>[How Facebook Live Streams To 800,000 Simultaneous Viewers](http://highscalability.com/blog/2016/6/27/how-facebook-live-streams-to-800000-simultaneous-viewers.html) |
| Flickr | [Flickr architecture](http://highscalability.com/flickr-architecture) |
| 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) |
| Netflix | [A 360 Degree View Of The Entire Netflix Stack](http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html)<br/>[Netflix: What Happens When You Press Play?](http://highscalability.com/blog/2017/12/11/netflix-what-happens-when-you-press-play.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) |
| PlentyOfFish | [PlentyOfFish architecture](http://highscalability.com/plentyoffish-architecture) |
| Salesforce | [How they handle 1.3 billion transactions a day](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html) |
| Stack Overflow | [Stack Overflow architecture](http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html) |
| TripAdvisor | [40M visitors, 200M dynamic page views, 30TB data](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.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)<br/>[How Twitter Handles 3,000 Images Per Second](http://highscalability.com/blog/2016/4/20/how-twitter-handles-3000-images-per-second.html) |
| Uber | [How Uber scales their real-time market platform](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html)<br/>[Lessons Learned From Scaling Uber To 2000 Engineers, 1000 Services, And 8000 Git Repositories](http://highscalability.com/blog/2016/10/12/lessons-learned-from-scaling-uber-to-2000-engineers-1000-ser.html) |
| WhatsApp | [The WhatsApp architecture Facebook bought for $19 billion](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| YouTube | [YouTube scalability](https://www.youtube.com/watch?v=w5WVu624fY8)<br/>[YouTube architecture](http://highscalability.com/youtube-architecture) |
### Şirketlerin mühendislik blogları
> Mülakat yaptığınız şirketlerin yazılım mimarileri.
>
> Mülakatta karşılaşacağınız sorular, şirketlerin çalışma alanından gelebilir.
* [Airbnb Engineering](http://nerds.airbnb.com/)
* [Atlassian Developers](https://developer.atlassian.com/blog/)
* [AWS Blog](https://aws.amazon.com/blogs/aws/)
* [Bitly Engineering Blog](http://word.bitly.com/)
* [Box Blogs](https://blog.box.com/blog/category/engineering)
* [Cloudera Developer Blog](http://blog.cloudera.com/)
* [Dropbox Tech Blog](https://tech.dropbox.com/)
* [Engineering at Quora](https://www.quora.com/q/quoraengineering)
* [Ebay Tech Blog](http://www.ebaytechblog.com/)
* [Evernote Tech Blog](https://blog.evernote.com/tech/)
* [Etsy Code as Craft](http://codeascraft.com/)
* [Facebook Engineering](https://www.facebook.com/Engineering)
* [Flickr Code](http://code.flickr.net/)
* [Foursquare Engineering Blog](http://engineering.foursquare.com/)
* [GitHub Engineering Blog](https://github.blog/category/engineering)
* [Google Research Blog](http://googleresearch.blogspot.com/)
* [Groupon Engineering Blog](https://engineering.groupon.com/)
* [Heroku Engineering Blog](https://engineering.heroku.com/)
* [Hubspot Engineering Blog](http://product.hubspot.com/blog/topic/engineering)
* [High Scalability](http://highscalability.com/)
* [Instagram Engineering](http://instagram-engineering.tumblr.com/)
* [Intel Software Blog](https://software.intel.com/en-us/blogs/)
* [Jane Street Tech Blog](https://blogs.janestreet.com/category/ocaml/)
* [LinkedIn Engineering](http://engineering.linkedin.com/blog)
* [Microsoft Engineering](https://engineering.microsoft.com/)
* [Microsoft Python Engineering](https://blogs.msdn.microsoft.com/pythonengineering/)
* [Netflix Tech Blog](http://techblog.netflix.com/)
* [Paypal Developer Blog](https://medium.com/paypal-engineering)
* [Pinterest Engineering Blog](https://medium.com/@Pinterest_Engineering)
* [Reddit Blog](http://www.redditblog.com/)
* [Salesforce Engineering Blog](https://developer.salesforce.com/blogs/engineering/)
* [Slack Engineering Blog](https://slack.engineering/)
* [Spotify Labs](https://labs.spotify.com/)
* [Twilio Engineering Blog](http://www.twilio.com/engineering)
* [Twitter Engineering](https://blog.twitter.com/engineering/)
* [Uber Engineering Blog](http://eng.uber.com/)
* [Yahoo Engineering Blog](http://yahooeng.tumblr.com/)
* [Yelp Engineering Blog](http://engineeringblog.yelp.com/)
* [Zynga Engineering Blog](https://www.zynga.com/blogs/engineering)
#### Kaynak(lar) ve ek okuma
Bir blog eklemek mi istiyorsunuz? Şirket blogunuzu aşağıdaki repoya eklemeyi düşünebilirsiniz:
* [kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)
## Geliştirme aşamasında
Bazı başlıklar eklemek veya bazı başlıkların iyileştirilmesine yardımcı olmak mı istiyorsunuz? [Katkıda bulunun](#katkı)!
* Distributed computing with MapReduce
* Tutarlı hashing (Consistent hashing)
* Scatter gather
* [Katkıda bulunun](#katkı)
## Katkıda bulunanlar
Bu repo, katkıda bulunanlar ve kaynakların desteğiyle oluşmuştur.
Bu sayfalara ayrıca teşekkürler:
* [Hired in tech](http://www.hiredintech.com/system-design/the-system-design-process/)
* [Cracking the coding interview](https://www.amazon.com/dp/0984782850/)
* [High scalability](http://highscalability.com/)
* [checkcheckzz/system-design-interview](https://github.com/checkcheckzz/system-design-interview)
* [shashank88/system_design](https://github.com/shashank88/system_design)
* [mmcgrana/services-engineering](https://github.com/mmcgrana/services-engineering)
* [System design cheat sheet](https://gist.github.com/vasanthk/485d1c25737e8e72759f)
* [A distributed systems reading list](http://dancres.github.io/Pages/)
* [Cracking the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
## İletişim
Bu makaleyle ilgili eksiklikleri, soruları veya yorumlarınızı tartışmak için benimle iletişime geçmekten çekinmeyin.
İletişim bilgilerimi [GitHub ana sayfamda](https://github.com/donnemartin) bulabilirsiniz.
## Lisans
*Bu repodaki kodları ve kaynakları sizlere açık kaynak lisansı altında sağlıyorum. Burası benim kişisel arşivim olduğu için, koduma ve kaynaklarıma ilişkin aldığınız lisans, işverenimden (Facebook) değil; benim tarafımdan sağlanmaktadır.*
> Copyright 2017 Donne Martin
>
> Creative Commons Attribution 4.0 International License (CC BY 4.0)
>
> http://creativecommons.org/licenses/by/4.0/

1793
docs/README-zh-Hans.md Normal file
View File

@@ -0,0 +1,1793 @@
> * 原文地址:[github.com/donnemartin/system-design-primer](https://github.com/donnemartin/system-design-primer)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 译者:[XatMassacrE](https://github.com/XatMassacrE)、[L9m](https://github.com/L9m)、[Airmacho](https://github.com/Airmacho)、[xiaoyusilen](https://github.com/xiaoyusilen)、[jifaxu](https://github.com/jifaxu)、[根号三](https://github.com/sqrthree)
> * 这个 [链接](https://github.com/xitu/system-design-primer/compare/master...donnemartin:master) 用来查看本翻译与英文版是否有差别(如果你没有看到 README.md 发生变化,那就意味着这份翻译文档是最新的)。
*[English](README.md) ∙ [日本語](README-ja.md) ∙ [简体中文](README-zh-Hans.md) ∙ [繁體中文](README-zh-TW.md) ∙ [العَرَبِيَّة‎](README-ar.md) ∙ [বাংলা](https://github.com/donnemartin/system-design-primer/issues/220) ∙ [Português do Brasil](https://github.com/donnemartin/system-design-primer/issues/40) ∙ [Deutsch](https://github.com/donnemartin/system-design-primer/issues/186) ∙ [ελληνικά](https://github.com/donnemartin/system-design-primer/issues/130) ∙ [עברית](https://github.com/donnemartin/system-design-primer/issues/272) ∙ [Italiano](https://github.com/donnemartin/system-design-primer/issues/104) ∙ [한국어](https://github.com/donnemartin/system-design-primer/issues/102) ∙ [فارسی](https://github.com/donnemartin/system-design-primer/issues/110) ∙ [Polski](https://github.com/donnemartin/system-design-primer/issues/68) ∙ [русский язык](https://github.com/donnemartin/system-design-primer/issues/87) ∙ [Español](https://github.com/donnemartin/system-design-primer/issues/136) ∙ [ภาษาไทย](https://github.com/donnemartin/system-design-primer/issues/187) ∙ [Türkçe](https://github.com/donnemartin/system-design-primer/issues/39) ∙ [tiếng Việt](https://github.com/donnemartin/system-design-primer/issues/127) ∙ [Français](https://github.com/donnemartin/system-design-primer/issues/250) | [Add Translation](https://github.com/donnemartin/system-design-primer/issues/28)*
# 系统设计入门
<p align="center">
<img src="images/jj3A5N8.png">
<br/>
</p>
## 目的
> 学习如何设计大型系统。
>
> 为系统设计的面试做准备。
### 学习如何设计大型系统
学习如何设计可扩展的系统将会有助于你成为一个更好的工程师。
系统设计是一个很宽泛的话题。在互联网上,**关于系统设计原则的资源也是多如牛毛。**
这个仓库就是这些资源的**组织收集**,它可以帮助你学习如何构建可扩展的系统。
### 从开源社区学习
这是一个不断更新的开源项目的初期的版本。
欢迎[贡献](#贡献)
### 为系统设计的面试做准备
在很多科技公司中,除了代码面试,系统设计也是**技术面试过程**中的一个**必要环节**。
**实践常见的系统设计面试题**并且把你的答案和**例子的解答**进行**对照**:讨论,代码和图表。
面试准备的其他主题:
* [学习指引](#学习指引)
* [如何处理一个系统设计的面试题](#如何处理一个系统设计的面试题)
* [系统设计的面试题,**含解答**](#系统设计的面试题和解答)
* [面向对象设计的面试题,**含解答**](#面向对象设计的面试问题及解答)
* [其它的系统设计面试题](#其它的系统设计面试题)
## 抽认卡
<p align="center">
<img src="images/zdCAkB3.png">
<br/>
</p>
这里提供的[抽认卡堆](https://apps.ankiweb.net/)使用间隔重复的方法,帮助你记忆关键的系统设计概念。
* [系统设计的卡堆](resources/flash_cards/System%20Design.apkg)
* [系统设计的练习卡堆](resources/flash_cards/System%20Design%20Exercises.apkg)
* [面向对象设计的练习卡堆](resources/flash_cards/OO%20Design.apkg)
随时随地都可使用。
### 代码资源:互动式编程挑战
你正在寻找资源以准备[**编程面试**](https://github.com/donnemartin/interactive-coding-challenges)吗?
<p align="center">
<img src="images/b4YtAEN.png">
<br/>
</p>
请查看我们的姐妹仓库[**互动式编程挑战**](https://github.com/donnemartin/interactive-coding-challenges),其中包含了一个额外的抽认卡堆:
* [代码卡堆](https://github.com/donnemartin/interactive-coding-challenges/tree/master/anki_cards/Coding.apkg)
## 贡献
> 从社区中学习。
欢迎提交 PR 提供帮助:
* 修复错误
* 完善章节
* 添加章节
* [帮助翻译](https://github.com/donnemartin/system-design-primer/issues/28)
一些还需要完善的内容放在了[正在完善中](#正在完善中)。
请查看[贡献指南](CONTRIBUTING.md)。
## 系统设计主题的索引
> 各种系统设计主题的摘要,包括优点和缺点。**每一个主题都面临着取舍和权衡**。
>
> 每个章节都包含着更多的资源的链接。
<p align="center">
<img src="images/jrUBAF7.png">
<br/>
</p>
* [系统设计主题:从这里开始](#系统设计主题从这里开始)
* [第一步:回顾可扩展性的视频讲座](#第一步回顾可扩展性scalability的视频讲座)
* [第二步:回顾可扩展性的文章](#第二步回顾可扩展性文章)
* [接下来的步骤](#接下来的步骤)
* [性能与拓展性](#性能与可扩展性)
* [延迟与吞吐量](#延迟与吞吐量)
* [可用性与一致性](#可用性与一致性)
* [CAP 理论](#cap-理论)
* [CP - 一致性和分区容错性](#cp--一致性和分区容错性)
* [AP - 可用性和分区容错性](#ap--可用性与分区容错性)
* [一致模式](#一致性模式)
* [弱一致性](#弱一致性)
* [最终一致性](#最终一致性)
* [强一致性](#强一致性)
* [可用模式](#可用性模式)
* [故障切换](#故障切换)
* [复制](#复制)
* [域名系统](#域名系统)
* [CDN](#内容分发网络cdn)
* [CDN 推送](#cdn-推送push)
* [CDN 拉取](#cdn-拉取pull)
* [负载均衡器](#负载均衡器)
* [工作到备用切换Active-passive](#工作到备用切换active-passive)
* [双工作切换Active-active](#双工作切换active-active)
* [四层负载均衡](#四层负载均衡)
* [七层负载均衡](#七层负载均衡器)
* [水平扩展](#水平扩展)
* [反向代理web 服务器)](#反向代理web-服务器)
* [负载均衡与反向代理](#负载均衡器与反向代理)
* [应用层](#应用层)
* [微服务](#微服务)
* [服务发现](#服务发现)
* [数据库](#数据库)
* [关系型数据库管理系统RDBMS](#关系型数据库管理系统rdbms)
* [Master-slave 复制集](#主从复制)
* [Master-master 复制集](#主主复制)
* [联合](#联合)
* [分片](#分片)
* [非规范化](#非规范化)
* [SQL 调优](#sql-调优)
* [NoSQL](#nosql)
* [Key-value 存储](#键-值存储)
* [文档存储](#文档类型存储)
* [宽列存储](#列型存储)
* [图数据库](#图数据库)
* [SQL 还是 NoSQL](#sql-还是-nosql)
* [缓存](#缓存)
* [客户端缓存](#客户端缓存)
* [CDN 缓存](#cdn-缓存)
* [Web 服务器缓存](#web-服务器缓存)
* [数据库缓存](#数据库缓存)
* [应用缓存](#应用缓存)
* [数据库查询级别的缓存](#数据库查询级别的缓存)
* [对象级别的缓存](#对象级别的缓存)
* [何时更新缓存](#何时更新缓存)
* [缓存模式](#缓存模式)
* [直写模式](#直写模式)
* [回写模式](#回写模式)
* [刷新](#刷新)
* [异步](#异步)
* [消息队列](#消息队列)
* [任务队列](#任务队列)
* [背压机制](#背压)
* [通讯](#通讯)
* [传输控制协议TCP](#传输控制协议tcp)
* [用户数据报协议UDP](#用户数据报协议udp)
* [远程控制调用协议RPC](#远程过程调用协议rpc)
* [表述性状态转移REST](#表述性状态转移rest)
* [安全](#安全)
* [附录](#附录)
* [2 的次方表](#2-的次方表)
* [每个程序员都应该知道的延迟数](#每个程序员都应该知道的延迟数)
* [其它的系统设计面试题](#其它的系统设计面试题)
* [真实架构](#真实架构)
* [公司的系统架构](#公司的系统架构)
* [公司工程博客](#公司工程博客)
* [正在完善中](#正在完善中)
* [致谢](#致谢)
* [联系方式](#联系方式)
* [许可](#许可)
## 学习指引
> 基于你面试的时间线(短、中、长)去复习那些推荐的主题。
![Imgur](images/OfVllex.png)
**问:对于面试来说,我需要知道这里的所有知识点吗?**
**答:不,如果只是为了准备面试的话,你并不需要知道所有的知识点。**
在一场面试中你会被问到什么取决于下面这些因素:
* 你的经验
* 你的技术背景
* 你面试的职位
* 你面试的公司
* 运气
那些有经验的候选人通常会被期望了解更多的系统设计的知识。架构师或者团队负责人则会被期望了解更多除了个人贡献之外的知识。顶级的科技公司通常也会有一次或者更多的系统设计面试。
面试会很宽泛的展开并在几个领域深入。这会帮助你了解一些关于系统设计的不同的主题。基于你的时间线,经验,面试的职位和面试的公司对下面的指导做出适当的调整。
* **短期** - 以系统设计主题的**广度**为目标。通过解决**一些**面试题来练习。
* **中期** - 以系统设计主题的**广度**和**初级深度**为目标。通过解决**很多**面试题来练习。
* **长期** - 以系统设计主题的**广度**和**高级深度**为目标。通过解决**大部分**面试题来练习。
| | 短期 | 中期 | 长期 |
| ---------------------------------------- | ---- | ---- | ---- |
| 阅读 [系统设计主题](#系统设计主题的索引) 以获得一个关于系统如何工作的宽泛的认识 | :+1: | :+1: | :+1: |
| 阅读一些你要面试的[公司工程博客](#公司工程博客)的文章 | :+1: | :+1: | :+1: |
| 阅读 [真实架构](#真实架构) | :+1: | :+1: | :+1: |
| 复习 [如何处理一个系统设计面试题](#如何处理一个系统设计面试题) | :+1: | :+1: | :+1: |
| 完成 [系统设计的面试题和解答](#系统设计的面试题和解答) | 一些 | 很多 | 大部分 |
| 完成 [面向对象设计的面试题和解答](#面向对象设计的面试问题及解答) | 一些 | 很多 | 大部分 |
| 复习 [其它的系统设计面试题](#其它的系统设计面试题) | 一些 | 很多 | 大部分 |
## 如何处理一个系统设计的面试题
系统设计面试是一个**开放式的对话**。他们期望你去主导这个对话。
你可以使用下面的步骤来指引讨论。为了巩固这个过程,请使用下面的步骤完成[系统设计的面试题和解答](#系统设计的面试题和解答)这个章节。
### 第一步:描述使用场景,约束和假设
把所有需要的东西聚集在一起,审视问题。不停的提问,以至于我们可以明确使用场景和约束。讨论假设。
* 谁会使用它?
* 他们会怎样使用它?
* 有多少用户?
* 系统的作用是什么?
* 系统的输入输出分别是什么?
* 我们希望处理多少数据?
* 我们希望每秒钟处理多少请求?
* 我们希望的读写比率?
### 第二步:创造一个高层级的设计
使用所有重要的组件来描绘出一个高层级的设计。
* 画出主要的组件和连接
* 证明你的想法
### 第三步:设计核心组件
对每一个核心组件进行详细深入的分析。举例来说,如果你被问到[设计一个 url 缩写服务](solutions/system_design/pastebin/README.md),开始讨论:
* 生成并储存一个完整 url 的 hash
* [MD5](solutions/system_design/pastebin/README.md) 和 [Base62](solutions/system_design/pastebin/README.md)
* Hash 碰撞
* SQL 还是 NoSQL
* 数据库模型
* 将一个 hashed url 翻译成完整的 url
* 数据库查找
* API 和面向对象设计
### 第四步:扩展设计
确认和处理瓶颈以及一些限制。举例来说就是你需要下面的这些来完成扩展性的议题吗?
* 负载均衡
* 水平扩展
* 缓存
* 数据库分片
论述可能的解决办法和代价。每件事情需要取舍。可以使用[可扩展系统的设计原则](#系统设计主题的索引)来处理瓶颈。
### 预估计算量
你或许会被要求通过手算进行一些估算。[附录](#附录)涉及到的是下面的这些资源:
* [使用预估计算量](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
* [2 的次方表](#2-的次方表)
* [每个程序员都应该知道的延迟数](#每个程序员都应该知道的延迟数)
### 相关资源和延伸阅读
查看下面的链接以获得我们期望的更好的想法:
* [怎样通过一个系统设计的面试](https://web.archive.org/web/20210505130322/https://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)
* [系统设计的面试](http://www.hiredintech.com/system-design)
* [系统架构与设计的面试简介](https://www.youtube.com/watch?v=ZgdS0EUmn70)
## 系统设计的面试题和解答
> 普通的系统设计面试题和相关事例的论述,代码和图表。
>
> 与内容有关的解答在 `solutions/` 文件夹中。
| 问题 | |
| ---------------------------------------- | ---------------------------------------- |
| 设计 Pastebin.com (或者 Bit.ly) | [解答](solutions/system_design/pastebin/README-zh-Hans.md) |
| 设计 Twitter 时间线和搜索 (或者 Facebook feed 和搜索) | [解答](solutions/system_design/twitter/README.md) |
| 设计一个网页爬虫 | [解答](solutions/system_design/web_crawler/README.md) |
| 设计 Mint.com | [解答](solutions/system_design/mint/README.md) |
| 为一个社交网络设计数据结构 | [解答](solutions/system_design/social_graph/README.md) |
| 为搜索引擎设计一个 key-value 储存 | [解答](solutions/system_design/query_cache/README.md) |
| 通过分类特性设计 Amazon 的销售排名 | [解答](solutions/system_design/sales_rank/README.md) |
| 在 AWS 上设计一个百万用户级别的系统 | [解答](solutions/system_design/scaling_aws/README.md) |
| 添加一个系统设计问题 | [贡献](#贡献) |
### 设计 Pastebin.com (或者 Bit.ly)
[查看实践与解答](solutions/system_design/pastebin/README.md)
![Imgur](images/4edXG0T.png)
### 设计 Twitter 时间线和搜索 (或者 Facebook feed 和搜索)
[查看实践与解答](solutions/system_design/twitter/README.md)
![Imgur](images/jrUBAF7.png)
### 设计一个网页爬虫
[查看实践与解答](solutions/system_design/web_crawler/README.md)
![Imgur](images/bWxPtQA.png)
### 设计 Mint.com
[查看实践与解答](solutions/system_design/mint/README.md)
![Imgur](images/V5q57vU.png)
### 为一个社交网络设计数据结构
[查看实践与解答](solutions/system_design/social_graph/README.md)
![Imgur](images/cdCv5g7.png)
### 为搜索引擎设计一个 key-value 储存
[查看实践与解答](solutions/system_design/query_cache/README.md)
![Imgur](images/4j99mhe.png)
### 设计按类别分类的 Amazon 销售排名
[查看实践与解答](solutions/system_design/sales_rank/README.md)
![Imgur](images/MzExP06.png)
### 在 AWS 上设计一个百万用户级别的系统
[查看实践与解答](solutions/system_design/scaling_aws/README.md)
![Imgur](images/jj3A5N8.png)
## 面向对象设计的面试问题及解答
> 常见面向对象设计面试问题及实例讨论,代码和图表演示。
>
> 与内容相关的解决方案在 `solutions/` 文件夹中。
>**注:此节还在完善中**
| 问题 | |
| ------------ | ---------------------------------------- |
| 设计 hash map | [解决方案](solutions/object_oriented_design/hash_table/hash_map.ipynb) |
| 设计 LRU 缓存 | [解决方案](solutions/object_oriented_design/lru_cache/lru_cache.ipynb) |
| 设计一个呼叫中心 | [解决方案](solutions/object_oriented_design/call_center/call_center.ipynb) |
| 设计一副牌 | [解决方案](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| 设计一个停车场 | [解决方案](solutions/object_oriented_design/parking_lot/parking_lot.ipynb) |
| 设计一个聊天服务 | [解决方案](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| 设计一个环形数组 | [待解决](#贡献) |
| 添加一个面向对象设计问题 | [待解决](#贡献) |
## 系统设计主题:从这里开始
不熟悉系统设计?
首先,你需要对一般性原则有一个基本的认识,知道它们是什么,怎样使用以及利弊。
### 第一步回顾可扩展性scalability的视频讲座
[哈佛大学可扩展性讲座](https://www.youtube.com/watch?v=-W9F__D3oY4)
* 主题涵盖
* 垂直扩展Vertical scaling
* 水平扩展Horizontal scaling
* 缓存
* 负载均衡
* 数据库复制
* 数据库分区
### 第二步:回顾可扩展性文章
[可扩展性](https://lecloud.tumblr.com/tagged/scalability)
* 主题涵盖:
* [Clones](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [数据库](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [缓存](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [异步](https://lecloud.tumblr.com/post/9699762917/scalability-for-dummies-part-4-asynchronism)
### 接下来的步骤
接下来,我们将看看高阶的权衡和取舍:
* **性能**与**可扩展性**
* **延迟**与**吞吐量**
* **可用性**与**一致性**
记住**每个方面都面临取舍和权衡**。
然后,我们将深入更具体的主题,如 DNS、CDN 和负载均衡器。
## 性能与可扩展性
如果服务**性能**的增长与资源的增加是成比例的,服务就是可扩展的。通常,提高性能意味着服务于更多的工作单元,另一方面,当数据集增长时,同样也可以处理更大的工作单位。<sup><a href="http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html">1</a></sup>
另一个角度来看待性能与可扩展性:
* 如果你的系统有**性能**问题,对于单个用户来说是缓慢的。
* 如果你的系统有**可扩展性**问题,单个用户较快但在高负载下会变慢。
### 来源及延伸阅读
* [简单谈谈可扩展性](http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)
* [可扩展性,可用性,稳定性和模式](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
## 延迟与吞吐量
**延迟**是执行操作或运算结果所花费的时间。
**吞吐量**是单位时间内(执行)此类操作或运算的数量。
通常,你应该以**可接受级延迟**下**最大化吞吐量**为目标。
### 来源及延伸阅读
* [理解延迟与吞吐量](https://community.cadence.com/cadence_blogs_8/b/sd/archive/2010/09/13/understanding-latency-vs-throughput)
## 可用性与一致性
### CAP 理论
<p align="center">
<img src="images/bgLMI2u.png">
<br/>
<strong><a href="http://robertgreiner.com/2014/08/cap-theorem-revisited">来源:再看 CAP 理论</a></strong>
</p>
在一个分布式计算系统中,只能同时满足下列的两点:
* **一致性** ─ 每次访问都能获得最新数据但可能会收到错误响应
* **可用性** ─ 每次访问都能收到非错响应,但不保证获取到最新数据
* **分区容错性** ─ 在任意分区网络故障的情况下系统仍能继续运行
**网络并不可靠,所以你应要支持分区容错性,并需要在软件可用性和一致性间做出取舍。**
#### CP ─ 一致性和分区容错性
等待分区节点的响应可能会导致延时错误。如果你的业务需求需要原子读写CP 是一个不错的选择。
#### AP ─ 可用性与分区容错性
响应节点上可用数据的最近版本可能并不是最新的。当分区解析完后,写入(操作)可能需要一些时间来传播。
如果业务需求允许[最终一致性](#最终一致性)或当有外部故障时要求系统继续运行AP 是一个不错的选择。
### 来源及延伸阅读
* [再看 CAP 理论](http://robertgreiner.com/2014/08/cap-theorem-revisited/)
* [通俗易懂地介绍 CAP 理论](http://ksat.me/a-plain-english-introduction-to-cap-theorem/)
* [CAP FAQ](https://github.com/henryr/cap-faq)
## 一致性模式
有同一份数据的多份副本,我们面临着怎样同步它们的选择,以便让客户端有一致的显示数据。回想 [CAP 理论](#cap-理论)中的一致性定义 ─ 每次访问都能获得最新数据但可能会收到错误响应
### 弱一致性
在写入之后,访问可能看到,也可能看不到(写入数据)。尽力优化之让其能访问最新数据。
这种方式可以 memcached 等系统中看到。弱一致性在 VoIP视频聊天和实时多人游戏等真实用例中表现不错。打个比方如果你在通话中丢失信号几秒钟时间当重新连接时你是听不到这几秒钟所说的话的。
### 最终一致性
在写入后,访问最终能看到写入数据(通常在数毫秒内)。数据被异步复制。
DNS 和 email 等系统使用的是此种方式。最终一致性在高可用性系统中效果不错。
### 强一致性
在写入后,访问立即可见。数据被同步复制。
文件系统和关系型数据库RDBMS中使用的是此种方式。强一致性在需要记录的系统中运作良好。
### 来源及延伸阅读
* [Transactions across data centers](http://snarfed.org/transactions_across_datacenters_io.html)
## 可用性模式
有两种支持高可用性的模式: **故障切换fail-over**和**复制replication**
### 故障切换
#### 工作到备用切换Active-passive
关于工作到备用的故障切换流程是,工作服务器发送周期信号给待机中的备用服务器。如果周期信号中断,备用服务器切换成工作服务器的 IP 地址并恢复服务。
宕机时间取决于备用服务器处于“热”待机状态还是需要从“冷”待机状态进行启动。只有工作服务器处理流量。
工作到备用的故障切换也被称为主从切换。
#### 双工作切换Active-active
在双工作切换中,双方都在管控流量,在它们之间分散负载。
如果是外网服务器DNS 将需要对两方都了解。如果是内网服务器,应用程序逻辑将需要对两方都了解。
双工作切换也可以称为主主切换。
### 缺陷:故障切换
* 故障切换需要添加额外硬件并增加复杂性。
* 如果新写入数据在能被复制到备用系统之前,工作系统出现了故障,则有可能会丢失数据。
### 复制
#### 主─从复制和主─主复制
这个主题进一步探讨了[数据库](#数据库)部分:
* [主─从复制](#主从复制)
* [主─主复制](#主主复制)
## 域名系统
<p align="center">
<img src="images/IOyLj4i.jpg">
<br/>
<strong><a href="http://www.slideshare.net/srikrupa5/dns-security-presentation-issa">来源DNS 安全介绍</a></strong>
</p>
域名系统是把 www.example.com 等域名转换成 IP 地址。
域名系统是分层次的,一些 DNS 服务器位于顶层。当查询(域名) IP 时,路由或 ISP 提供连接 DNS 服务器的信息。较底层的 DNS 服务器缓存映射,它可能会因为 DNS 传播延时而失效。DNS 结果可以缓存在浏览器或操作系统中一段时间,时间长短取决于[存活时间 TTL](https://en.wikipedia.org/wiki/Time_to_live)。
* **NS 记录(域名服务)** ─ 指定解析域名或子域名的 DNS 服务器。
* **MX 记录(邮件交换)** ─ 指定接收信息的邮件服务器。
* **A 记录(地址)** ─ 指定域名对应的 IP 地址记录。
* **CNAME规范** ─ 一个域名映射到另一个域名或 `CNAME` 记录( example.com 指向 www.example.com )或映射到一个 `A` 记录。
[CloudFlare](https://www.cloudflare.com/dns/) 和 [Route 53](https://aws.amazon.com/route53/) 等平台提供管理 DNS 的功能。某些 DNS 服务通过集中方式来路由流量:
* [加权轮询调度](http://g33kinfo.com/info/archives/2657)
* 防止流量进入维护中的服务器
* 在不同大小集群间负载均衡
* A/B 测试
* 基于延迟路由
* 基于地理位置路由
### 缺陷:DNS
* 虽说缓存可以减轻 DNS 延迟,但连接 DNS 服务器还是带来了轻微的延迟。
* 虽然它们通常由[政府,网络服务提供商和大公司](http://superuser.com/questions/472695/who-controls-the-dns-servers/472729)管理,但 DNS 服务管理仍可能是复杂的。
* DNS 服务最近遭受 [DDoS 攻击](http://dyn.com/blog/dyn-analysis-summary-of-friday-october-21-attack/),阻止不知道 Twitter IP 地址的用户访问 Twitter。
### 来源及延伸阅读
* [DNS 架构](https://technet.microsoft.com/en-us/library/dd197427(v=ws.10).aspx)
* [Wikipedia](https://en.wikipedia.org/wiki/Domain_Name_System)
* [关于 DNS 的文章](https://support.dnsimple.com/categories/dns/)
## 内容分发网络CDN
<p align="center">
<img src="images/h9TAuGI.jpg">
<br/>
<strong><a href="https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/">来源:为什么使用 CDN</a></strong>
</p>
内容分发网络CDN是一个全球性的代理服务器分布式网络它从靠近用户的位置提供内容。通常HTML/CSS/JS图片和视频等静态内容由 CDN 提供,虽然亚马逊 CloudFront 等也支持动态内容。CDN 的 DNS 解析会告知客户端连接哪台服务器。
将内容存储在 CDN 上可以从两个方面来提供性能:
* 从靠近用户的数据中心提供资源
* 通过 CDN 你的服务器不必真的处理请求
### CDN 推送push
当你服务器上内容发生变动时,推送 CDN 接受新内容。直接推送给 CDN 并重写 URL 地址以指向你的内容的 CDN 地址。你可以配置内容到期时间及何时更新。内容只有在更改或新增是才推送,流量最小化,但储存最大化。
### CDN 拉取pull
CDN 拉取是当第一个用户请求该资源时,从服务器上拉取资源。你将内容留在自己的服务器上并重写 URL 指向 CDN 地址。直到内容被缓存在 CDN 上为止,这样请求只会更慢,
[存活时间TTL](https://en.wikipedia.org/wiki/Time_to_live)决定缓存多久时间。CDN 拉取方式最小化 CDN 上的储存空间,但如果过期文件并在实际更改之前被拉取,则会导致冗余的流量。
高流量站点使用 CDN 拉取效果不错,因为只有最近请求的内容保存在 CDN 中,流量才能更平衡地分散。
### 缺陷CDN
* CDN 成本可能因流量而异,可能在权衡之后你将不会使用 CDN。
* 如果在 TTL 过期之前更新内容CDN 缓存内容可能会过时。
* CDN 需要更改静态内容的 URL 地址以指向 CDN。
### 来源及延伸阅读
* [全球性内容分发网络](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci)
* [CDN 拉取和 CDN 推送的区别](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)
* [Wikipedia](https://en.wikipedia.org/wiki/Content_delivery_network)
## 负载均衡器
<p align="center">
<img src="images/h81n9iK.png">
<br/>
<strong><a href="http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html">来源:可扩展的系统设计模式</a></strong>
</p>
负载均衡器将传入的请求分发到应用服务器和数据库等计算资源。无论哪种情况,负载均衡器将从计算资源来的响应返回给恰当的客户端。负载均衡器的效用在于:
* 防止请求进入不好的服务器
* 防止资源过载
* 帮助消除单一的故障点
负载均衡器可以通过硬件(昂贵)或 HAProxy 等软件来实现。
增加的好处包括:
* **SSL 终结** ─ 解密传入的请求并加密服务器响应,这样的话后端服务器就不必再执行这些潜在高消耗运算了。
* 不需要再每台服务器上安装 [X.509 证书](https://en.wikipedia.org/wiki/X.509)。
* **Session 留存** ─ 如果 Web 应用程序不追踪会话,发出 cookie 并将特定客户端的请求路由到同一实例。
通常会设置采用[工作─备用](#工作到备用切换active-passive) 或 [双工作](#双工作切换active-active) 模式的多个负载均衡器,以免发生故障。
负载均衡器能基于多种方式来路由流量:
* 随机
* 最少负载
* Session/cookie
* [轮询调度或加权轮询调度算法](http://g33kinfo.com/info/archives/2657)
* [四层负载均衡](#四层负载均衡)
* [七层负载均衡](#七层负载均衡)
### 四层负载均衡
四层负载均衡根据监看[传输层](#通讯)的信息来决定如何分发请求。通常,这会涉及来源,目标 IP 地址和请求头中的端口,但不包括数据包(报文)内容。四层负载均衡执行[网络地址转换NAT](https://www.geeksforgeeks.org/network-address-translation-nat/)来向上游服务器转发网络数据包。
### 七层负载均衡器
七层负载均衡器根据监控[应用层](#通讯)来决定怎样分发请求。这会涉及请求头的内容,消息和 cookie。七层负载均衡器终结网络流量读取消息做出负载均衡判定然后传送给特定服务器。比如一个七层负载均衡器能直接将视频流量连接到托管视频的服务器同时将更敏感的用户账单流量引导到安全性更强的服务器。
以损失灵活性为代价,四层负载均衡比七层负载均衡花费更少时间和计算资源,虽然这对现代商用硬件的性能影响甚微。
### 水平扩展
负载均衡器还能帮助水平扩展,提高性能和可用性。使用商业硬件的性价比更高,并且比在单台硬件上**垂直扩展**更贵的硬件具有更高的可用性。相比招聘特定企业系统人才,招聘商业硬件方面的人才更加容易。
#### 缺陷:水平扩展
* 水平扩展引入了复杂度并涉及服务器复制
* 服务器应该是无状态的:它们也不该包含像 session 或资料图片等与用户关联的数据。
* session 可以集中存储在数据库或持久化[缓存](#缓存)Redis、Memcached的数据存储区中。
* 缓存和数据库等下游服务器需要随着上游服务器进行扩展,以处理更多的并发连接。
### 缺陷:负载均衡器
* 如果没有足够的资源配置或配置错误,负载均衡器会变成一个性能瓶颈。
* 引入负载均衡器以帮助消除单点故障但导致了额外的复杂性。
* 单个负载均衡器会导致单点故障,但配置多个负载均衡器会进一步增加复杂性。
### 来源及延伸阅读
* [NGINX 架构](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy 架构指南](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [可扩展性](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [Wikipedia](https://en.wikipedia.org/wiki/Load_balancing_(computing))
* [四层负载平衡](https://www.nginx.com/resources/glossary/layer-4-load-balancing/)
* [七层负载平衡](https://www.nginx.com/resources/glossary/layer-7-load-balancing/)
* [ELB 监听器配置](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html)
## 反向代理web 服务器)
<p align="center">
<img src="images/n41Azff.png">
<br/>
<strong><a href="https://upload.wikimedia.org/wikipedia/commons/6/67/Reverse_proxy_h2g2bob.svg">资料来源:维基百科</a></strong>
<br/>
</p>
反向代理是一种可以集中地调用内部服务,并提供统一接口给公共客户的 web 服务器。来自客户端的请求先被反向代理服务器转发到可响应请求的服务器,然后代理再把服务器的响应结果返回给客户端。
带来的好处包括:
- **增加安全性** - 隐藏后端服务器的信息,屏蔽黑名单中的 IP限制每个客户端的连接数。
- **提高可扩展性和灵活性** - 客户端只能看到反向代理服务器的 IP这使你可以增减服务器或者修改它们的配置。
- **本地终结 SSL 会话** - 解密传入请求,加密服务器响应,这样后端服务器就不必完成这些潜在的高成本的操作。
- 免除了在每个服务器上安装 [X.509](https://en.wikipedia.org/wiki/X.509) 证书的需要
- **压缩** - 压缩服务器响应
- **缓存** - 直接返回命中的缓存结果
- **静态内容** - 直接提供静态内容
- HTML/CSS/JS
- 图片
- 视频
- 等等
### 负载均衡器与反向代理
- 当你有多个服务器时,部署负载均衡器非常有用。通常,负载均衡器将流量路由给一组功能相同的服务器上。
- 即使只有一台 web 服务器或者应用服务器时,反向代理也有用,可以参考上一节介绍的好处。
- NGINX 和 HAProxy 等解决方案可以同时支持第七层反向代理和负载均衡。
### 不利之处:反向代理
- 引入反向代理会增加系统的复杂度。
- 单独一个反向代理服务器仍可能发生单点故障,配置多台反向代理服务器(如[故障转移](https://en.wikipedia.org/wiki/Failover))会进一步增加复杂度。
### 来源及延伸阅读
- [反向代理与负载均衡](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)
- [NGINX 架构](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
- [HAProxy 架构指南](http://www.haproxy.org/download/1.2/doc/architecture.txt)
- [Wikipedia](https://en.wikipedia.org/wiki/Reverse_proxy)
## 应用层
<p align="center">
<img src="images/yB5SYwm.png">
<br/>
<strong><a href="http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer">资料来源:可缩放系统构架介绍</a></strong>
</p>
将 Web 服务层与应用层(也被称作平台层)分离,可以独立缩放和配置这两层。添加新的 API 只需要添加应用服务器,而不必添加额外的 web 服务器。
**单一职责原则**提倡小型的,自治的服务共同合作。小团队通过提供小型的服务,可以更激进地计划增长。
应用层中的工作进程也有可以实现[异步化](#异步)。
### 微服务
与此讨论相关的话题是 [微服务](https://en.wikipedia.org/wiki/Microservices),可以被描述为一系列可以独立部署的小型的,模块化服务。每个服务运行在一个独立的线程中,通过明确定义的轻量级机制通讯,共同实现业务目标。<sup><a href=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
例如Pinterest 可能有这些微服务: 用户资料、关注者、Feed 流、搜索、照片上传等。
### 服务发现
像 [Consul](https://www.consul.io/docs/index.html)[Etcd](https://coreos.com/etcd/docs/latest) 和 [Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) 这样的系统可以通过追踪注册名、地址、端口等信息来帮助服务互相发现对方。[Health checks](https://www.consul.io/intro/getting-started/checks.html) 可以帮助确认服务的完整性和是否经常使用一个 [HTTP](#超文本传输协议http) 路径。Consul 和 Etcd 都有一个内建的 [key-value 存储](#键-值存储) 用来存储配置信息和其他的共享信息。
### 不利之处:应用层
- 添加由多个松耦合服务组成的应用层,从架构、运营、流程等层面来讲将非常不同(相对于单体系统)。
- 微服务会增加部署和运营的复杂度。
### 来源及延伸阅读
- [可缩放系统构架介绍](http://lethain.com/introduction-to-architecting-systems-for-scale)
- [破解系统设计面试](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
- [面向服务架构](https://en.wikipedia.org/wiki/Service-oriented_architecture)
- [Zookeeper 介绍](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper)
- [构建微服务,你所需要知道的一切](https://cloudncode.wordpress.com/2016/07/22/msa-getting-started/)
## 数据库
<p align="center">
<img src="images/Xkm5CXz.png">
<br/>
<strong><a href="https://www.youtube.com/watch?v=w95murBkYmU">资料来源:扩展你的用户数到第一个一千万</a></strong>
</p>
### 关系型数据库管理系统RDBMS
像 SQL 这样的关系型数据库是一系列以表的形式组织的数据项集合。
> 校对注:这里作者 SQL 可能指的是 MySQL
**ACID** 用来描述关系型数据库[事务](https://en.wikipedia.org/wiki/Database_transaction)的特性。
- **原子性** - 每个事务内部所有操作要么全部完成,要么全部不完成。
- **一致性** - 任何事务都使数据库从一个有效的状态转换到另一个有效状态。
- **隔离性** - 并发执行事务的结果与顺序执行事务的结果相同。
- **持久性** - 事务提交后,对系统的影响是永久的。
关系型数据库扩展包括许多技术:**主从复制**、**主主复制**、**联合**、**分片**、**非规范化**和 **SQL调优**
<p align="center">
<img src="images/C9ioGtn.png">
<br/>
<strong><a href="http://www.slideshare.net/jboner/scalability-availability-stability-patterns/">资料来源:可扩展性、可用性、稳定性、模式</a></strong>
</p>
#### 主从复制
主库同时负责读取和写入操作,并复制写入到一个或多个从库中,从库只负责读操作。树状形式的从库再将写入复制到更多的从库中去。如果主库离线,系统可以以只读模式运行,直到某个从库被提升为主库或有新的主库出现。
##### 不利之处:主从复制
- 将从库提升为主库需要额外的逻辑。
- 参考[不利之处:复制](#不利之处复制)中,主从复制和主主复制**共同**的问题。
<p align="center">
<img src="images/krAHLGg.png">
<br/>
<strong><a href="http://www.slideshare.net/jboner/scalability-availability-stability-patterns/">资料来源:可扩展性、可用性、稳定性、模式</a></strong>
</p>
#### 主主复制
两个主库都负责读操作和写操作,写入操作时互相协调。如果其中一个主库挂机,系统可以继续读取和写入。
##### 不利之处: 主主复制
- 你需要添加负载均衡器或者在应用逻辑中做改动,来确定写入哪一个数据库。
- 多数主-主系统要么不能保证一致性(违反 ACID要么因为同步产生了写入延迟。
- 随着更多写入节点的加入和延迟的提高,如何解决冲突显得越发重要。
- 参考[不利之处:复制](#不利之处复制)中,主从复制和主主复制**共同**的问题。
##### 不利之处:复制
- 如果主库在将新写入的数据复制到其他节点前挂掉,则有数据丢失的可能。
- 写入会被重放到负责读取操作的副本。副本可能因为过多写操作阻塞住,导致读取功能异常。
- 读取从库越多,需要复制的写入数据就越多,导致更严重的复制延迟。
- 在某些数据库系统中,写入主库的操作可以用多个线程并行写入,但读取副本只支持单线程顺序地写入。
- 复制意味着更多的硬件和额外的复杂度。
##### 来源及延伸阅读
- [扩展性,可用性,稳定性模式](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
- [多主复制](https://en.wikipedia.org/wiki/Multi-master_replication)
#### 联合
<p align="center">
<img src="images/U3qV33e.png">
<br/>
<strong><a href="https://www.youtube.com/watch?v=w95murBkYmU">资料来源:扩展你的用户数到第一个一千万</a></strong>
</p>
联合(或按功能划分)将数据库按对应功能分割。例如,你可以有三个数据库:**论坛**、**用户**和**产品**,而不仅是一个单体数据库,从而减少每个数据库的读取和写入流量,减少复制延迟。较小的数据库意味着更多适合放入内存的数据,进而意味着更高的缓存命中几率。没有只能串行写入的中心化主库,你可以并行写入,提高负载能力。
##### 不利之处:联合
- 如果你的数据库模式需要大量的功能和数据表,联合的效率并不好。
- 你需要更新应用程序的逻辑来确定要读取和写入哪个数据库。
- 用 [server link](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers) 从两个库联结数据更复杂。
- 联合需要更多的硬件和额外的复杂度。
##### 来源及延伸阅读:联合
- [扩展你的用户数到第一个一千万](https://www.youtube.com/watch?v=w95murBkYmU)
#### 分片
<p align="center">
<img src="images/wU8x5Id.png">
<br/>
<strong><a href="http://www.slideshare.net/jboner/scalability-availability-stability-patterns/">资料来源:可扩展性、可用性、稳定性、模式</a></strong>
</p>
分片将数据分配在不同的数据库上,使得每个数据库仅管理整个数据集的一个子集。以用户数据库为例,随着用户数量的增加,越来越多的分片会被添加到集群中。
类似[联合](#联合)的优点,分片可以减少读取和写入流量,减少复制并提高缓存命中率。也减少了索引,通常意味着查询更快,性能更好。如果一个分片出问题,其他的仍能运行,你可以使用某种形式的冗余来防止数据丢失。类似联合,没有只能串行写入的中心化主库,你可以并行写入,提高负载能力。
常见的做法是用户姓氏的首字母或者用户的地理位置来分隔用户表。
##### 不利之处:分片
- 你需要修改应用程序的逻辑来实现分片,这会带来复杂的 SQL 查询。
- 分片不合理可能导致数据负载不均衡。例如,被频繁访问的用户数据会导致其所在分片的负载相对其他分片高。
- 再平衡会引入额外的复杂度。基于[一致性哈希](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)的分片算法可以减少这种情况。
- 联结多个分片的数据操作更复杂。
- 分片需要更多的硬件和额外的复杂度。
#### 来源及延伸阅读:分片
- [分片时代来临](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)
- [数据库分片架构](https://en.wikipedia.org/wiki/Shard_(database_architecture))
- [一致性哈希](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)
#### 非规范化
非规范化试图以写入性能为代价来换取读取性能。在多个表中冗余数据副本,以避免高成本的联结操作。一些关系型数据库,比如 [PostgreSQL](https://en.wikipedia.org/wiki/PostgreSQL) 和 Oracle 支持[物化视图](https://en.wikipedia.org/wiki/Materialized_view),可以处理冗余信息存储和保证冗余副本一致。
当数据使用诸如[联合](#联合)和[分片](#分片)等技术被分割,进一步提高了处理跨数据中心的联结操作复杂度。非规范化可以规避这种复杂的联结操作。
在多数系统中,读取操作的频率远高于写入操作,比例可达到 100:1甚至 1000:1。需要复杂的数据库联结的读取操作成本非常高在磁盘操作上消耗了大量时间。
##### 不利之处:非规范化
- 数据会冗余。
- 约束可以帮助冗余的信息副本保持同步,但这样会增加数据库设计的复杂度。
- 非规范化的数据库在高写入负载下性能可能比规范化的数据库差。
##### 来源及延伸阅读:非规范化
- [非规范化](https://en.wikipedia.org/wiki/Denormalization)
#### SQL 调优
SQL 调优是一个范围很广的话题,有很多相关的[](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning)可以作为参考。
利用**基准测试**和**性能分析**来模拟和发现系统瓶颈很重要。
- **基准测试** - 用 [ab](http://httpd.apache.org/docs/2.2/programs/ab.html) 等工具模拟高负载情况。
- **性能分析** - 通过启用如[慢查询日志](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)等工具来辅助追踪性能问题。
基准测试和性能分析可能会指引你到以下优化方案。
##### 改进模式
- 为了实现快速访问MySQL 在磁盘上用连续的块存储数据。
- 使用 `CHAR` 类型存储固定长度的字段,不要用 `VARCHAR`
- `CHAR` 在快速、随机访问时效率很高。如果使用 `VARCHAR`,如果你想读取下一个字符串,不得不先读取到当前字符串的末尾。
- 使用 `TEXT` 类型存储大块的文本,例如博客正文。`TEXT` 还允许布尔搜索。使用 `TEXT` 字段需要在磁盘上存储一个用于定位文本块的指针。
- 使用 `INT` 类型存储高达 2^32 或 40 亿的较大数字。
- 使用 `DECIMAL` 类型存储货币可以避免浮点数表示错误。
- 避免使用 `BLOBS` 存储实际对象,而是用来存储存放对象的位置。
- `VARCHAR(255)` 是以 8 位数字存储的最大字符数,在某些关系型数据库中,最大限度地利用字节。
- 在适用场景中设置 `NOT NULL` 约束来[提高搜索性能](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)。
##### 使用正确的索引
- 你正查询(`SELECT``GROUP BY``ORDER BY``JOIN`)的列如果用了索引会更快。
- 索引通常表示为自平衡的 [B 树](https://en.wikipedia.org/wiki/B-tree),可以保持数据有序,并允许在对数时间内进行搜索,顺序访问,插入,删除操作。
- 设置索引,会将数据存在内存中,占用了更多内存空间。
- 写入操作会变慢,因为索引需要被更新。
- 加载大量数据时,禁用索引再加载数据,然后重建索引,这样也许会更快。
##### 避免高成本的联结操作
- 有性能需要,可以进行非规范化。
##### 分割数据表
- 将热点数据拆分到单独的数据表中,可以有助于缓存。
##### 调优查询缓存
- 在某些情况下,[查询缓存](http://dev.mysql.com/doc/refman/5.7/en/query-cache)可能会导致[性能问题](https://www.percona.com/blog/2014/01/28/10-mysql-performance-tuning-settings-after-installation/)。
##### 来源及延伸阅读
- [MySQL 查询优化小贴士](http://20bits.com/article/10-tips-for-optimizing-mysql-queries-that-dont-suck)
- [为什么 VARCHAR(255) 很常见?](http://stackoverflow.com/questions/1217466/is-there-a-good-reason-i-see-varchar255-used-so-often-as-opposed-to-another-l)
- [Null 值是如何影响数据库性能的?](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)
- [慢查询日志](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)
### NoSQL
NoSQL 是**键-值数据库**、**文档型数据库**、**列型数据库**或**图数据库**的统称。数据库是非规范化的,表联结大多在应用程序代码中完成。大多数 NoSQL 无法实现真正符合 ACID 的事务,支持[最终一致](#最终一致性)。
**BASE** 通常被用于描述 NoSQL 数据库的特性。相比 [CAP 理论](#cap-理论)BASE 强调可用性超过一致性。
- **基本可用** - 系统保证可用性。
- **软状态** - 即使没有输入,系统状态也可能随着时间变化。
- **最终一致性** - 经过一段时间之后,系统最终会变一致,因为系统在此期间没有收到任何输入。
除了在 [SQL 还是 NoSQL](#sql-还是-nosql) 之间做选择,了解哪种类型的 NoSQL 数据库最适合你的用例也是非常有帮助的。我们将在下一节中快速了解下 **键-值存储**、**文档型存储**、**列型存储**和**图存储**数据库。
#### 键-值存储
> 抽象模型:哈希表
键-值存储通常可以实现 O(1) 时间读写,用内存或 SSD 存储数据。数据存储可以按[字典顺序](https://en.wikipedia.org/wiki/Lexicographical_order)维护键,从而实现键的高效检索。键-值存储可以用于存储元数据。
键-值存储性能很高,通常用于存储简单数据模型或频繁修改的数据,如存放在内存中的缓存。键-值存储提供的操作有限,如果需要更多操作,复杂度将转嫁到应用程序层面。
键-值存储是如文档存储,在某些情况下,甚至是图存储等更复杂的存储系统的基础。
#### 来源及延伸阅读
- [键-值数据库](https://en.wikipedia.org/wiki/Key-value_database)
- [键-值存储的劣势](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
- [Redis 架构](http://qnimate.com/overview-of-redis-architecture/)
- [Memcached 架构](https://adayinthelifeof.nl/2011/02/06/memcache-internals/)
#### 文档类型存储
> 抽象模型:将文档作为值的键-值存储
文档类型存储以文档XML、JSON、二进制文件等为中心文档存储了指定对象的全部信息。文档存储根据文档自身的内部结构提供 API 或查询语句来实现查询。请注意,许多键-值存储数据库有用值存储元数据的特性,这也模糊了这两种存储类型的界限。
基于底层实现,文档可以根据集合、标签、元数据或者文件夹组织。尽管不同文档可以被组织在一起或者分成一组,但相互之间可能具有完全不同的字段。
MongoDB 和 CouchDB 等一些文档类型存储还提供了类似 SQL 语言的查询语句来实现复杂查询。DynamoDB 同时支持键-值存储和文档类型存储。
文档类型存储具备高度的灵活性,常用于处理偶尔变化的数据。
#### 来源及延伸阅读:文档类型存储
- [面向文档的数据库](https://en.wikipedia.org/wiki/Document-oriented_database)
- [MongoDB 架构](https://www.mongodb.com/mongodb-architecture)
- [CouchDB 架构](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/)
- [Elasticsearch 架构](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)
#### 列型存储
<p align="center">
<img src="images/n16iOGk.png">
<br/>
<strong><a href="http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html">资料来源: SQL 和 NoSQL一个简短的历史</a></strong>
</p>
> 抽象模型:嵌套的 `ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>` 映射
类型存储的基本数据单元是列(名/值对)。列可以在列族(类似于 SQL 的数据表)中被分组。超级列族再分组普通列族。你可以使用行键独立访问每一列,具有相同行键值的列组成一行。每个值都包含版本的时间戳用于解决版本冲突。
Google 发布了第一个列型存储数据库 [Bigtable](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf),它影响了 Hadoop 生态系统中活跃的开源数据库 [HBase](https://www.mapr.com/blog/in-depth-look-hbase-architecture) 和 Facebook 的 [Cassandra](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html)。像 BigTableHBase 和 Cassandra 这样的存储系统将键以字母顺序存储,可以高效地读取键列。
列型存储具备高可用性和高可扩展性。通常被用于大数据相关存储。
##### 来源及延伸阅读:列型存储
- [SQL 与 NoSQL 简史](http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html)
- [BigTable 架构](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)
- [Hbase 架构](https://www.mapr.com/blog/in-depth-look-hbase-architecture)
- [Cassandra 架构](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html)
#### 图数据库
<p align="center">
<img src="images/fNcl65g.png">
<br/>
<strong><a href="https://en.wikipedia.org/wiki/File:GraphDatabase_PropertyGraph.png"/>资料来源:图数据库</a></strong>
</p>
> 抽象模型: 图
在图数据库中,一个节点对应一条记录,一个弧对应两个节点之间的关系。图数据库被优化用于表示外键繁多的复杂关系或多对多关系。
图数据库为存储复杂关系的数据模型,如社交网络,提供了很高的性能。它们相对较新,尚未广泛应用,查找开发工具或者资源相对较难。许多图只能通过 [REST API](#表述性状态转移rest) 访问。
##### 相关资源和延伸阅读:图
- [图数据库](https://en.wikipedia.org/wiki/Graph_database)
- [Neo4j](https://neo4j.com/)
- [FlockDB](https://blog.twitter.com/2010/introducing-flockdb)
#### 来源及延伸阅读NoSQL
- [数据库术语解释](http://stackoverflow.com/questions/3342497/explanation-of-base-terminology)
- [NoSQL 数据库 - 调查及决策指南](https://medium.com/baqend-blog/nosql-databases-a-survey-and-decision-guidance-ea7823a822d#.wskogqenq)
- [可扩展性](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
- [NoSQL 介绍](https://www.youtube.com/watch?v=qI_g07C_Q5I)
- [NoSQL 模式](http://horicky.blogspot.com/2009/11/nosql-patterns.html)
### SQL 还是 NoSQL
<p align="center">
<img src="images/wXGqG5f.png">
<br/>
<strong><a href="https://www.infoq.com/articles/Transition-RDBMS-NoSQL/">资料来源:从 RDBMS 转换到 NoSQL</a></strong>
</p>
选取 **SQL** 的原因:
- 结构化数据
- 严格的模式
- 关系型数据
- 需要复杂的联结操作
- 事务
- 清晰的扩展模式
- 既有资源更丰富:开发者、社区、代码库、工具等
- 通过索引进行查询非常快
选取 **NoSQL** 的原因:
- 半结构化数据
- 动态或灵活的模式
- 非关系型数据
- 不需要复杂的联结操作
- 存储 TB (甚至 PB级别的数据
- 高数据密集的工作负载
- IOPS 高吞吐量
适合 NoSQL 的示例数据:
- 埋点数据和日志数据
- 排行榜或者得分数据
- 临时数据,如购物车
- 频繁访问的(“热”)表
- 元数据/查找表
##### 来源及延伸阅读SQL 或 NoSQL
- [扩展你的用户数到第一个千万](https://www.youtube.com/watch?v=w95murBkYmU)
- [SQL 和 NoSQL 的不同](https://www.sitepoint.com/sql-vs-nosql-differences/)
## 缓存
<p align="center">
<img src="images/Q6z24La.png">
<br/>
<strong><a href="http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html">资料来源:可扩展的系统设计模式</a></strong>
</p>
缓存可以提高页面加载速度,并可以减少服务器和数据库的负载。在这个模型中,分发器先查看请求之前是否被响应过,如果有则将之前的结果直接返回,来省掉真正的处理。
数据库分片均匀分布的读取是最好的。但是热门数据会让读取分布不均匀,这样就会造成瓶颈,如果在数据库前加个缓存,就会抹平不均匀的负载和突发流量对数据库的影响。
### 客户端缓存
缓存可以位于客户端(操作系统或者浏览器),[服务端](#反向代理web-服务器)或者不同的缓存层。
### CDN 缓存
[CDN](#内容分发网络cdn) 也被视为一种缓存。
### Web 服务器缓存
[反向代理](#反向代理web-服务器)和缓存(比如 [Varnish](https://www.varnish-cache.org/)可以直接提供静态和动态内容。Web 服务器同样也可以缓存请求,返回相应结果而不必连接应用服务器。
### 数据库缓存
数据库的默认配置中通常包含缓存级别,针对一般用例进行了优化。调整配置,在不同情况下使用不同的模式可以进一步提高性能。
### 应用缓存
基于内存的缓存比如 Memcached 和 Redis 是应用程序和数据存储之间的一种键值存储。由于数据保存在 RAM 中它比存储在磁盘上的典型数据库要快多了。RAM 比磁盘限制更多,所以例如 [least recently used (LRU)](https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used) 的[缓存无效算法](https://en.wikipedia.org/wiki/Cache_algorithms)可以将「热门数据」放在 RAM 中,而对一些比较「冷门」的数据不做处理。
Redis 有下列附加功能:
- 持久性选项
- 内置数据结构比如有序集合和列表
有多个缓存级别,分为两大类:**数据库查询**和**对象**
- 行级别
- 查询级别
- 完整的可序列化对象
- 完全渲染的 HTML
一般来说,你应该尽量避免基于文件的缓存,因为这使得复制和自动缩放很困难。
### 数据库查询级别的缓存
当你查询数据库的时候,将查询语句的哈希值与查询结果存储到缓存中。这种方法会遇到以下问题:
- 很难用复杂的查询删除已缓存结果。
- 如果一条数据比如表中某条数据的一项被改变,则需要删除所有可能包含已更改项的缓存结果。
### 对象级别的缓存
将您的数据视为对象,就像对待你的应用代码一样。让应用程序将数据从数据库中组合到类实例或数据结构中:
- 如果对象的基础数据已经更改了,那么从缓存中删掉这个对象。
- 允许异步处理workers 通过使用最新的缓存对象来组装对象。
建议缓存的内容:
- 用户会话
- 完全渲染的 Web 页面
- 活动流
- 用户图数据
### 何时更新缓存
由于你只能在缓存中存储有限的数据,所以你需要选择一个适用于你用例的缓存更新策略。
#### 缓存模式
<p align="center">
<img src="images/ONjORqk.png">
<br/>
<strong><a href="http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast">资料来源:从缓存到内存数据网格</a></strong>
</p>
应用从存储器读写。缓存不和存储器直接交互,应用执行以下操作:
- 在缓存中查找记录,如果所需数据不在缓存中
- 从数据库中加载所需内容
- 将查找到的结果存储到缓存中
- 返回所需内容
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
[Memcached](https://memcached.org/) 通常用这种方式使用。
添加到缓存中的数据读取速度很快。缓存模式也称为延迟加载。只缓存所请求的数据,这避免了没有被请求的数据占满了缓存空间。
##### 缓存的缺点:
- 请求的数据如果不在缓存中就需要经过三个步骤来获取数据,这会导致明显的延迟。
- 如果数据库中的数据更新了会导致缓存中的数据过时。这个问题需要通过设置 TTL 强制更新缓存或者直写模式来缓解这种情况。
- 当一个节点出现故障的时候,它将会被一个新的节点替代,这增加了延迟的时间。
#### 直写模式
<p align="center">
<img src="images/0vBc0hN.png">
<br/>
<strong><a href="http://www.slideshare.net/jboner/scalability-availability-stability-patterns/">资料来源:可扩展性、可用性、稳定性、模式</a></strong>
</p>
应用使用缓存作为主要的数据存储,将数据读写到缓存中,而缓存负责从数据库中读写数据。
- 应用向缓存中添加/更新数据
- 缓存同步地写入数据存储
- 返回所需内容
应用代码:
```
set_user(12345, {"foo":"bar"})
```
缓存代码:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
由于存写操作所以直写模式整体是一种很慢的操作,但是读取刚写入的数据很快。相比读取数据,用户通常比较能接受更新数据时速度较慢。缓存中的数据不会过时。
##### 直写模式的缺点:
- 由于故障或者缩放而创建的新的节点,新的节点不会缓存,直到数据库更新为止。缓存应用直写模式可以缓解这个问题。
- 写入的大多数数据可能永远都不会被读取,用 TTL 可以最小化这种情况的出现。
#### 回写模式
<p align="center">
<img src="images/rgSrvjG.png">
<br/>
<strong><a href="http://www.slideshare.net/jboner/scalability-availability-stability-patterns/">资料来源:可扩展性、可用性、稳定性、模式</a></strong>
</p>
在回写模式中,应用执行以下操作:
- 在缓存中增加或者更新条目
- 异步写入数据,提高写入性能。
##### 回写模式的缺点:
- 缓存可能在其内容成功存储之前丢失数据。
- 执行直写模式比缓存或者回写模式更复杂。
#### 刷新
<p align="center">
<img src="images/kxtjqgE.png">
<br/>
<strong><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>资料来源:从缓存到内存数据网格</a></strong>
</p>
你可以将缓存配置成在到期之前自动刷新最近访问过的内容。
如果缓存可以准确预测将来可能请求哪些数据,那么刷新可能会导致延迟与读取时间的降低。
##### 刷新的缺点:
- 不能准确预测到未来需要用到的数据可能会导致性能不如不使用刷新。
### 缓存的缺点:
- 需要保持缓存和真实数据源之间的一致性,比如数据库根据[缓存无效](https://en.wikipedia.org/wiki/Cache_algorithms)。
- 需要改变应用程序比如增加 Redis 或者 memcached。
- 无效缓存是个难题,什么时候更新缓存是与之相关的复杂问题。
### 相关资源和延伸阅读
- [从缓存到内存数据](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
- [可扩展系统设计模式](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
- [可缩放系统构架介绍](http://lethain.com/introduction-to-architecting-systems-for-scale/)
- [可扩展性,可用性,稳定性和模式](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
- [可扩展性](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
- [AWS ElastiCache 策略](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
- [维基百科](https://en.wikipedia.org/wiki/Cache_(computing))
## 异步
<p align="center">
<img src="images/54GYsSx.png">
<br/>
<strong><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>资料来源:可缩放系统构架介绍</a></strong>
</p>
异步工作流有助于减少那些原本顺序执行的请求时间。它们可以通过提前进行一些耗时的工作来帮助减少请求时间,比如定期汇总数据。
### 消息队列
消息队列接收,保留和传递消息。如果按顺序执行操作太慢的话,你可以使用有以下工作流的消息队列:
- 应用程序将作业发布到队列,然后通知用户作业状态
- 一个 worker 从队列中取出该作业,对其进行处理,然后显示该作业完成
不去阻塞用户操作,作业在后台处理。在此期间,客户端可能会进行一些处理使得看上去像是任务已经完成了。例如,如果要发送一条推文,推文可能会马上出现在你的时间线上,但是可能需要一些时间才能将你的推文推送到你的所有关注者那里去。
**Redis** 是一个令人满意的简单的消息代理,但是消息有可能会丢失。
**RabbitMQ** 很受欢迎但是要求你适应「AMQP」协议并且管理你自己的节点。
**Amazon SQS** 是被托管的,但可能具有高延迟,并且消息可能会被传送两次。
### 任务队列
任务队列接收任务及其相关数据,运行它们,然后传递其结果。 它们可以支持调度,并可用于在后台运行计算密集型作业。
**Celery** 支持调度,主要是用 Python 开发的。
### 背压
如果队列开始明显增长,那么队列大小可能会超过内存大小,导致高速缓存未命中,磁盘读取,甚至性能更慢。[背压](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)可以通过限制队列大小来帮助我们,从而为队列中的作业保持高吞吐率和良好的响应时间。一旦队列填满,客户端将得到服务器忙或者 HTTP 503 状态码,以便稍后重试。客户端可以在稍后时间重试该请求,也许是[指数退避](https://en.wikipedia.org/wiki/Exponential_backoff)。
### 异步的缺点:
- 简单的计算和实时工作流等用例可能更适用于同步操作,因为引入队列可能会增加延迟和复杂性。
### 相关资源和延伸阅读
- [这是一个数字游戏](https://www.youtube.com/watch?v=1KRYH75wgy4)
- [超载时应用背压](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
- [利特尔法则](https://en.wikipedia.org/wiki/Little%27s_law)
- [消息队列与任务队列有什么区别?](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)
## 通讯
<p align="center">
<img src="images/5KeocQs.jpg">
<br/>
<strong><a href=http://www.escotal.com/osilayer.html>资料来源OSI 7层模型</a></strong>
</p>
### 超文本传输协议HTTP
HTTP 是一种在客户端和服务器之间编码和传输数据的方法。它是一个请求/响应协议客户端和服务端针对相关内容和完成状态信息的请求和响应。HTTP 是独立的,允许请求和响应流经许多执行负载均衡,缓存,加密和压缩的中间路由器和服务器。
一个基本的 HTTP 请求由一个动词(方法)和一个资源(端点)组成。 以下是常见的 HTTP 动词:
| 动词 | 描述 | *幂等 | 安全性 | 可缓存 |
| ------ | -------------- | ---- | ---- | -------------- |
| GET | 读取资源 | Yes | Yes | Yes |
| POST | 创建资源或触发处理数据的进程 | No | No | Yes如果回应包含刷新信息 |
| PUT | 创建或替换资源 | Yes | No | No |
| PATCH | 部分更新资源 | No | No | Yes如果回应包含刷新信息 |
| DELETE | 删除资源 | Yes | No | No |
**多次执行不会产生不同的结果**
HTTP 是依赖于较低级协议(如 **TCP****UDP**)的应用层协议。
#### 来源及延伸阅读HTTP
* [README](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol) +
* [HTTP 是什么?](https://www.nginx.com/resources/glossary/http/)
* [HTTP 和 TCP 的区别](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)
* [PUT 和 PATCH的区别](https://laracasts.com/discuss/channels/general-discussion/whats-the-differences-between-put-and-patch?page=1)
### 传输控制协议TCP
<p align="center">
<img src="images/JdAsdvG.jpg">
<br/>
<strong><a href="http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/">资料来源:如何制作多人游戏</a></strong>
</p>
TCP 是通过 [IP 网络](https://en.wikipedia.org/wiki/Internet_Protocol)的面向连接的协议。 使用[握手](https://en.wikipedia.org/wiki/Handshaking)建立和断开连接。 发送的所有数据包保证以原始顺序到达目的地,用以下措施保证数据包不被损坏:
- 每个数据包的序列号和[校验码](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation)。
- [确认包](https://en.wikipedia.org/wiki/Acknowledgement_(data_networks))和自动重传
如果发送者没有收到正确的响应它将重新发送数据包。如果多次超时连接就会断开。TCP 实行[流量控制](https://en.wikipedia.org/wiki/Flow_control_(data))和[拥塞控制](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control)。这些确保措施会导致延迟,而且通常导致传输效率比 UDP 低。
为了确保高吞吐量Web 服务器可以保持大量的 TCP 连接,从而导致高内存使用。在 Web 服务器线程间拥有大量开放连接可能开销巨大,消耗资源过多,也就是说,一个 [memcached](#memcached) 服务器。[连接池](https://en.wikipedia.org/wiki/Connection_pool) 可以帮助除了在适用的情况下切换到 UDP。
TCP 对于需要高可靠性但时间紧迫的应用程序很有用。比如包括 Web 服务器数据库信息SMTPFTP 和 SSH。
以下情况使用 TCP 代替 UDP
- 你需要数据完好无损。
- 你想对网络吞吐量自动进行最佳评估。
### 用户数据报协议UDP
<p align="center">
<img src="images/yzDrJtA.jpg">
<br/>
<strong><a href="http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1">资料来源:如何制作多人游戏</a></strong>
</p>
UDP 是无连接的。数据报类似于数据包只在数据报级别有保证。数据报可能会无序的到达目的地也有可能会遗失。UDP 不支持拥塞控制。虽然不如 TCP 那样有保证,但 UDP 通常效率更高。
UDP 可以通过广播将数据报发送至子网内的所有设备。这对 [DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) 很有用,因为子网内的设备还没有分配 IP 地址,而 IP 对于 TCP 是必须的。
UDP 可靠性更低但适合用在网络电话、视频聊天,流媒体和实时多人游戏上。
以下情况使用 UDP 代替 TCP
* 你需要低延迟
* 相对于数据丢失更糟的是数据延迟
* 你想实现自己的错误校正方法
#### 来源及延伸阅读TCP 与 UDP
* [游戏编程的网络](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)
* [TCP 与 UDP 的关键区别](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)
* [TCP 与 UDP 的不同](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
* [传输控制协议](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)
* [用户数据报协议](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [Memcache 在 Facebook 的扩展](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)
### 远程过程调用协议RPC
<p align="center">
<img src="images/iF4Mkb5.png">
<br/>
<strong><a href="http://www.puncsky.com/blog/2016/02/14/crack-the-system-design-interview">Source: Crack the system design interview</a></strong>
</p>
在 RPC 中,客户端会去调用另一个地址空间(通常是一个远程服务器)里的方法。调用代码看起来就像是调用的是一个本地方法,客户端和服务器交互的具体过程被抽象。远程调用相对于本地调用一般较慢而且可靠性更差,因此区分两者是有帮助的。热门的 RPC 框架包括 [Protobuf](https://developers.google.com/protocol-buffers/)、[Thrift](https://thrift.apache.org/) 和 [Avro](https://avro.apache.org/docs/current/)。
RPC 是一个“请求-响应”协议:
* **客户端程序** ── 调用客户端存根程序。就像调用本地方法一样,参数会被压入栈中。
* **客户端 stub 程序** ── 将请求过程的 id 和参数打包进请求信息中。
* **客户端通信模块** ── 将信息从客户端发送至服务端。
* **服务端通信模块** ── 将接受的包传给服务端存根程序。
* **服务端 stub 程序** ── 将结果解包,依据过程 id 调用服务端方法并将参数传递过去。
RPC 调用示例:
```
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
```
RPC 专注于暴露方法。RPC 通常用于处理内部通讯的性能问题,这样你可以手动处理本地调用以更好的适应你的情况。
当以下情况时选择本地库(也就是 SDK
* 你知道你的目标平台。
* 你想控制如何访问你的“逻辑”。
* 你想对发生在你的库中的错误进行控制。
* 性能和终端用户体验是你最关心的事。
遵循 **REST** 的 HTTP API 往往更适用于公共 API。
#### 缺点RPC
* RPC 客户端与服务实现捆绑地很紧密。
* 一个新的 API 必须在每一个操作或者用例中定义。
* RPC 很难调试。
* 你可能没办法很方便的去修改现有的技术。举个例子,如果你希望在 [Squid](http://www.squid-cache.org/) 这样的缓存服务器上确保 [RPC 被正确缓存](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)的话可能需要一些额外的努力了。
### 表述性状态转移REST
REST 是一种强制的客户端/服务端架构设计模型,客户端基于服务端管理的一系列资源操作。服务端提供修改或获取资源的接口。所有的通信必须是无状态和可缓存的。
RESTful 接口有四条规则:
* **标志资源HTTP 里的 URI** ── 无论什么操作都使用同一个 URI。
* **表示的改变HTTP 的动作)** ── 使用动作, headers 和 body。
* **可自我描述的错误信息HTTP 中的 status code** ── 使用状态码,不要重新造轮子。
* **[HATEOAS](http://restcookbook.com/Basics/hateoas/)HTTP 中的HTML 接口)** ── 你的 web 服务器应该能够通过浏览器访问。
REST 请求的例子:
```
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
```
REST 关注于暴露数据。它减少了客户端/服务端的耦合程度,经常用于公共 HTTP API 接口设计。REST 使用更通常与规范化的方法来通过 URI 暴露资源,[通过 header 来表述](https://github.com/for-GET/know-your-http-well/blob/master/headers.md)并通过 GET、POST、PUT、DELETE 和 PATCH 这些动作来进行操作。因为无状态的特性REST 易于横向扩展和隔离。
#### 缺点REST
* 由于 REST 将重点放在暴露数据,所以当资源不是自然组织的或者结构复杂的时候它可能无法很好的适应。举个例子,返回过去一小时中与特定事件集匹配的更新记录这种操作就很难表示为路径。使用 REST可能会使用 URI 路径,查询参数和可能的请求体来实现。
* REST 一般依赖几个动作GET、POST、PUT、DELETE 和 PATCH但有时候仅仅这些没法满足你的需要。举个例子将过期的文档移动到归档文件夹里去这样的操作可能没法简单的用上面这几个 verbs 表达。
* 为了渲染单个页面,获取被嵌套在层级结构中的复杂资源需要客户端,服务器之间多次往返通信。例如,获取博客内容及其关联评论。对于使用不确定网络环境的移动应用来说,这些多次往返通信是非常麻烦的。
* 随着时间的推移,更多的字段可能会被添加到 API 响应中,较旧的客户端将会接收到所有新的数据字段,即使是那些它们不需要的字段,结果它会增加负载大小并引起更大的延迟。
### RPC 与 REST 比较
| 操作 | RPC | REST |
| ----------- | ---------------------------------------- | ---------------------------------------- |
| 注册 | **POST** /signup | **POST** /persons |
| 注销 | **POST** /resign<br/>{<br/>"personid": "1234"<br/>} | **DELETE** /persons/1234 |
| 读取用户信息 | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| 读取用户物品列表 | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| 向用户物品列表添加一项 | **POST** /addItemToUsersItemsList<br/>{<br/>"personid": "1234";<br/>"itemid": "456"<br/>} | **POST** /persons/1234/items<br/>{<br/>"itemid": "456"<br/>} |
| 更新一个物品 | **POST** /modifyItem<br/>{<br/>"itemid": "456";<br/>"key": "value"<br/>} | **PUT** /items/456<br/>{<br/>"key": "value"<br/>} |
| 删除一个物品 | **POST** /removeItem<br/>{<br/>"itemid": "456"<br/>} | **DELETE** /items/456 |
<p align="center">
<strong><a href="https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc">资料来源:你真的知道你为什么更喜欢 REST 而不是 RPC 吗</a></strong>
</p>
#### 来源及延伸阅读REST 与 RPC
* [你真的知道你为什么更喜欢 REST 而不是 RPC 吗](https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/)
* [什么时候 RPC 比 REST 更合适?](http://programmers.stackexchange.com/a/181186)
* [REST vs JSON-RPC](http://stackoverflow.com/questions/15056878/rest-vs-json-rpc)
* [揭开 RPC 和 REST 的神秘面纱](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)
* [使用 REST 的缺点是什么](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)
* [破解系统设计面试](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Thrift](https://code.facebook.com/posts/1468950976659943/)
* [为什么在内部使用 REST 而不是 RPC](http://arstechnica.com/civis/viewtopic.php?t=1190508)
## 安全
这一部分需要更多内容。[一起来吧](#贡献)
安全是一个宽泛的话题。除非你有相当的经验、安全方面背景或者正在申请的职位要求安全知识,你不需要了解安全基础知识以外的内容:
* 在运输和等待过程中加密
* 对所有的用户输入和从用户那里发来的参数进行处理以防止 [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) 和 [SQL 注入](https://en.wikipedia.org/wiki/SQL_injection)。
* 使用参数化的查询来防止 SQL 注入。
* 使用[最小权限原则](https://en.wikipedia.org/wiki/Principle_of_least_privilege)。
### 来源及延伸阅读
* [为开发者准备的安全引导](https://github.com/FallibleInc/security-guide-for-developers)
* [OWASP top ten](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
## 附录
一些时候你会被要求做出保守估计。比如,你可能需要估计从磁盘中生成 100 张图片的缩略图需要的时间或者一个数据结构需要多少的内存。**2 的次方表**和**每个开发者都需要知道的一些时间数据**译注OSChina 上有这篇文章的[译文](https://www.oschina.net/news/30009/every-programmer-should-know))都是一些很方便的参考资料。
### 2 的次方表
```
Power Exact Value Approx Value Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
```
#### 来源及延伸阅读
* [2 的次方](https://en.wikipedia.org/wiki/Power_of_two)
### 每个程序员都应该知道的延迟数
```
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from disk 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
```
基于上述数字的指标:
* 从磁盘以 30 MB/s 的速度顺序读取
* 以 100 MB/s 从 1 Gbps 的以太网顺序读取
* 从 SSD 以 1 GB/s 的速度读取
* 以 4 GB/s 的速度从主存读取
* 每秒能绕地球 6-7 圈
* 数据中心内每秒有 2,000 次往返
#### 延迟数可视化
![](https://web.archive.org/web/20200702021143im_/https://camo.githubusercontent.com/77f72259e1eb58596b564d1ad823af1853bc60a3/687474703a2f2f692e696d6775722e636f6d2f6b307431652e706e67)
#### 来源及延伸阅读
* [每个程序员都应该知道的延迟数 — 1](https://gist.github.com/jboner/2841832)
* [每个程序员都应该知道的延迟数 — 2](https://gist.github.com/hellerbarde/2843375)
* [关于建设大型分布式系统的的设计方案、课程和建议](http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf)
* [关于建设大型可拓展分布式系统的软件工程咨询](https://static.googleusercontent.com/media/research.google.com/en//people/jeff/stanford-295-talk.pdf)
### 其它的系统设计面试题
> 常见的系统设计面试问题,给出了如何解决的方案链接
| 问题 | 引用 |
| ----------------------- | ---------------------------------------- |
| 设计类似于 Dropbox 的文件同步服务 | [youtube.com](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| 设计类似于 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) |
| 设计类似于 Google 的可扩展网络爬虫 | [quora.com](https://www.quora.com/How-can-I-build-a-web-crawler-from-scratch) |
| 设计 Google 文档 | [code.google.com](https://code.google.com/p/google-mobwrite/)<br/>[neil.fraser.name](https://neil.fraser.name/writing/sync/) |
| 设计类似 Redis 的键值存储 | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| 设计类似 Memcached 的缓存系统 | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| 设计类似亚马逊的推荐系统 | [hulu.com](http://tech.hulu.com/blog/2011/09/19/recommendation-system.html)<br/>[ijcai13.org](http://ijcai13.org/files/tutorial_slides/td3.pdf) |
| 设计类似 Bitly 的短链接系统 | [n00tc0d3r.blogspot.com](http://n00tc0d3r.blogspot.com/) |
| 设计类似 WhatsApp 的聊天应用 | [highscalability.com](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| 设计类似 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) |
| 设计 Facebook 的新闻推荐方法 | [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) |
| 设计 Facebook 的时间线系统 | [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) |
| 设计 Facebook 的聊天系统 | [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) |
| 设计类似 Facebook 的图表搜索系统 | [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) |
| 设计类似 CloudFlare 的内容传递网络 | [cmu.edu](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci) |
| 设计类似 Twitter 的热门话题系统 | [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/) |
| 设计一个随机 ID 生成系统 | [blog.twitter.com](https://blog.twitter.com/2010/announcing-snowflake)<br/>[github.com](https://github.com/twitter/snowflake/) |
| 返回一定时间段内次数前 k 高的请求 | [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) |
| 设计一个数据源于多个数据中心的服务系统 | [highscalability.com](http://highscalability.com/blog/2009/8/24/how-google-serves-data-from-multiple-datacenters.html) |
| 设计一个多人网络卡牌游戏 | [indieflashblog.com](https://web.archive.org/web/20180929181117/http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)<br/>[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| 设计一个垃圾回收系统 | [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) |
| 添加更多的系统设计问题 | [贡献](#贡献) |
### 真实架构
> 关于现实中真实的系统是怎么设计的文章。
<p align="center">
<img src="images/TcUo2fw.png">
<br/>
<strong><a href="https://www.infoq.com/presentations/Twitter-Timeline-Scalability">Source: Twitter timelines at scale</a></strong>
</p>
**不要专注于以下文章的细节,专注于以下方面:**
* 发现这些文章中的共同的原则、技术和模式。
* 学习每个组件解决哪些问题,什么情况下使用,什么情况下不适用
* 复习学过的文章
| 类型 | 系统 | 引用 |
| --------------- | ---------------------------------------- | ---------------------------------------- |
| Data processing | **MapReduce** - Google的分布式数据处理 | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/mapreduce-osdi04.pdf) |
| Data processing | **Spark** - Databricks 的分布式数据处理 | [slideshare.net](http://www.slideshare.net/AGrishchenko/apache-spark-architecture) |
| Data processing | **Storm** - Twitter 的分布式数据处理 | [slideshare.net](http://www.slideshare.net/previa/storm-16094009) |
| | | |
| Data store | **Bigtable** - Google 的列式数据库 | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) |
| Data store | **HBase** - Bigtable 的开源实现 | [slideshare.net](http://www.slideshare.net/alexbaranau/intro-to-hbase) |
| Data store | **Cassandra** - Facebook 的列式数据库 | [slideshare.net](http://www.slideshare.net/planetcassandra/cassandra-introduction-features-30103666) |
| Data store | **DynamoDB** - Amazon 的文档数据库 | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) |
| Data store | **MongoDB** - 文档数据库 | [slideshare.net](http://www.slideshare.net/mdirolf/introduction-to-mongodb) |
| Data store | **Spanner** - Google 的全球分布数据库 | [research.google.com](http://research.google.com/archive/spanner-osdi2012.pdf) |
| Data store | **Memcached** - 分布式内存缓存系统 | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| Data store | **Redis** - 能够持久化及具有值类型的分布式内存缓存系统 | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| | | |
| File system | **Google File System (GFS)** - 分布式文件系统 | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/gfs-sosp2003.pdf) |
| File system | **Hadoop File System (HDFS)** - GFS 的开源实现 | [apache.org](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html) |
| | | |
| Misc | **Chubby** - Google 的分布式系统的低耦合锁服务 | [research.google.com](http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/archive/chubby-osdi06.pdf) |
| Misc | **Dapper** - 分布式系统跟踪基础设施 | [research.google.com](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf) |
| Misc | **Kafka** - LinkedIn 的发布订阅消息系统 | [slideshare.net](http://www.slideshare.net/mumrah/kafka-talk-tri-hug) |
| Misc | **Zookeeper** - 集中的基础架构和协调服务 | [slideshare.net](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) |
| | 添加更多 | [贡献](#贡献) |
### 公司的系统架构
| Company | Reference(s) |
| -------------- | ---------------------------------------- |
| Amazon | [Amazon 的架构](http://highscalability.com/amazon-architecture) |
| Cinchcast | [每天产生 1500 小时的音频](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html) |
| DataSift | [每秒实时挖掘 120000 条 tweet](http://highscalability.com/blog/2011/11/29/datasift-architecture-realtime-datamining-at-120000-tweets-p.html) |
| DropBox | [我们如何缩放 Dropbox](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| ESPN | [每秒操作 100000 次](http://highscalability.com/blog/2013/11/4/espns-architecture-at-scale-operating-at-100000-duh-nuh-nuhs.html) |
| Google | [Google 的架构](http://highscalability.com/google-architecture) |
| Instagram | [1400 万用户,达到兆级别的照片存储](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html)<br/>[是什么在驱动 Instagram](http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances) |
| Justin.tv | [Justin.Tv 的直播广播架构](http://highscalability.com/blog/2010/3/16/justintvs-live-video-broadcasting-architecture.html) |
| Facebook | [Facebook 的可扩展 memcached](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/key-value/fb-memcached-nsdi-2013.pdf)<br/>[TAO: Facebook 社交图的分布式数据存储](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/data-store/tao-facebook-distributed-datastore-atc-2013.pdf)<br/>[Facebook 的图片存储](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf) |
| Flickr | [Flickr 的架构](http://highscalability.com/flickr-architecture) |
| Mailbox | [在 6 周内从 0 到 100 万用户](http://highscalability.com/blog/2013/6/18/scaling-mailbox-from-0-to-one-million-users-in-6-weeks-and-1.html) |
| Pinterest | [从零到每月数十亿的浏览量](http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html)<br/>[1800 万访问用户10 倍增长12 名员工](http://highscalability.com/blog/2012/5/21/pinterest-architecture-update-18-million-visitors-10x-growth.html) |
| Playfish | [月用户量 5000 万并在不断增长](http://highscalability.com/blog/2010/9/21/playfishs-social-gaming-architecture-50-million-monthly-user.html) |
| PlentyOfFish | [PlentyOfFish 的架构](http://highscalability.com/plentyoffish-architecture) |
| Salesforce | [他们每天如何处理 13 亿笔交易](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html) |
| Stack Overflow | [Stack Overflow 的架构](http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html) |
| TripAdvisor | [40M 访问者200M 页面浏览量30TB 数据](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.html) |
| Tumblr | [每月 150 亿的浏览量](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/>[每天使用 MySQL 存储2.5亿条 tweet](http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html)<br/>[150M 活跃用户300K QPS22 MB/S 的防火墙](http://highscalability.com/blog/2013/7/8/the-architecture-twitter-uses-to-deal-with-150m-active-users.html)<br/>[可扩展时间表](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)<br/>[Twitter 的大小数据](https://www.youtube.com/watch?v=5cKTP36HVgI)<br/>[Twitter 的行为:规模超过 1 亿用户](https://www.youtube.com/watch?v=z8LU0Cj6BOU) |
| Uber | [Uber 如何扩展自己的实时化市场](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html) |
| WhatsApp | [Facebook 用 190 亿美元购买 WhatsApp 的架构](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| YouTube | [YouTube 的可扩展性](https://www.youtube.com/watch?v=w5WVu624fY8)<br/>[YouTube 的架构](http://highscalability.com/youtube-architecture) |
### 公司工程博客
> 你即将面试的公司的架构
>
> 你面对的问题可能就来自于同样领域
* [Airbnb Engineering](http://nerds.airbnb.com/)
* [Atlassian Developers](https://developer.atlassian.com/blog/)
* [Autodesk Engineering](http://cloudengineering.autodesk.com/blog/)
* [AWS Blog](https://aws.amazon.com/blogs/aws/)
* [Bitly Engineering Blog](http://word.bitly.com/)
* [Box Blogs](https://www.box.com/blog/engineering/)
* [Cloudera Developer Blog](http://blog.cloudera.com/blog/)
* [Dropbox Tech Blog](https://tech.dropbox.com/)
* [Engineering at Quora](http://engineering.quora.com/)
* [Ebay Tech Blog](http://www.ebaytechblog.com/)
* [Evernote Tech Blog](https://blog.evernote.com/tech/)
* [Etsy Code as Craft](http://codeascraft.com/)
* [Facebook Engineering](https://www.facebook.com/Engineering)
* [Flickr Code](http://code.flickr.net/)
* [Foursquare Engineering Blog](http://engineering.foursquare.com/)
* [GitHub Engineering Blog](https://github.blog/category/engineering)
* [Google Research Blog](http://googleresearch.blogspot.com/)
* [Groupon Engineering Blog](https://engineering.groupon.com/)
* [Heroku Engineering Blog](https://engineering.heroku.com/)
* [Hubspot Engineering Blog](http://product.hubspot.com/blog/topic/engineering)
* [High Scalability](http://highscalability.com/)
* [Instagram Engineering](http://instagram-engineering.tumblr.com/)
* [Intel Software Blog](https://software.intel.com/en-us/blogs/)
* [Jane Street Tech Blog](https://blogs.janestreet.com/category/ocaml/)
* [LinkedIn Engineering](http://engineering.linkedin.com/blog)
* [Microsoft Engineering](https://engineering.microsoft.com/)
* [Microsoft Python Engineering](https://blogs.msdn.microsoft.com/pythonengineering/)
* [Netflix Tech Blog](http://techblog.netflix.com/)
* [Paypal Developer Blog](https://devblog.paypal.com/category/engineering/)
* [Pinterest Engineering Blog](http://engineering.pinterest.com/)
* [Quora Engineering](https://engineering.quora.com/)
* [Reddit Blog](http://www.redditblog.com/)
* [Salesforce Engineering Blog](https://developer.salesforce.com/blogs/engineering/)
* [Slack Engineering Blog](https://slack.engineering/)
* [Spotify Labs](https://labs.spotify.com/)
* [Stripe Engineering Blog](https://stripe.com/blog/engineering)
* [Twilio Engineering Blog](http://www.twilio.com/engineering)
* [Twitter Engineering](https://engineering.twitter.com/)
* [Uber Engineering Blog](http://eng.uber.com/)
* [Yahoo Engineering Blog](http://yahooeng.tumblr.com/)
* [Yelp Engineering Blog](http://engineeringblog.yelp.com/)
* [Zynga Engineering Blog](https://www.zynga.com/blogs/engineering)
#### 来源及延伸阅读
* [kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)
## 正在完善中
有兴趣加入添加一些部分或者帮助完善某些部分吗?[加入进来吧](#贡献)
* 使用 MapReduce 进行分布式计算
* 一致性哈希
* 直接存储器访问DMA控制器
* [贡献](#贡献)
## 致谢
整个仓库都提供了证书和源
特别鸣谢:
* [Hired in tech](http://www.hiredintech.com/system-design/the-system-design-process/)
* [Cracking the coding interview](https://www.amazon.com/dp/0984782850/)
* [High scalability](http://highscalability.com/)
* [checkcheckzz/system-design-interview](https://github.com/checkcheckzz/system-design-interview)
* [shashank88/system_design](https://github.com/shashank88/system_design)
* [mmcgrana/services-engineering](https://github.com/mmcgrana/services-engineering)
* [System design cheat sheet](https://gist.github.com/vasanthk/485d1c25737e8e72759f)
* [A distributed systems reading list](http://dancres.github.io/Pages/)
* [Cracking the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
## 联系方式
欢迎联系我讨论本文的不足、问题或者意见。
可以在我的 [GitHub 主页](https://github.com/donnemartin)上找到我的联系方式
## 许可
Creative Commons Attribution 4.0 International License (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/

1787
docs/README-zh-TW.md Normal file
View File

@@ -0,0 +1,1787 @@
*[English](README.md) ∙ [日本語](README-ja.md) ∙ [简体中文](README-zh-Hans.md) ∙ [繁體中文](README-zh-TW.md) ∙ [العَرَبِيَّة‎](README-ar.md) ∙ [বাংলা](https://github.com/donnemartin/system-design-primer/issues/220) ∙ [Português do Brasil](https://github.com/donnemartin/system-design-primer/issues/40) ∙ [Deutsch](https://github.com/donnemartin/system-design-primer/issues/186) ∙ [ελληνικά](https://github.com/donnemartin/system-design-primer/issues/130) ∙ [עברית](https://github.com/donnemartin/system-design-primer/issues/272) ∙ [Italiano](https://github.com/donnemartin/system-design-primer/issues/104) ∙ [한국어](https://github.com/donnemartin/system-design-primer/issues/102) ∙ [فارسی](https://github.com/donnemartin/system-design-primer/issues/110) ∙ [Polski](https://github.com/donnemartin/system-design-primer/issues/68) ∙ [русский язык](https://github.com/donnemartin/system-design-primer/issues/87) ∙ [Español](https://github.com/donnemartin/system-design-primer/issues/136) ∙ [ภาษาไทย](https://github.com/donnemartin/system-design-primer/issues/187) ∙ [Türkçe](https://github.com/donnemartin/system-design-primer/issues/39) ∙ [tiếng Việt](https://github.com/donnemartin/system-design-primer/issues/127) ∙ [Français](https://github.com/donnemartin/system-design-primer/issues/250) | [Add Translation](https://github.com/donnemartin/system-design-primer/issues/28)*
# 系統設計入門
<p align="center">
<img src="images/jj3A5N8.png">
<br/>
</p>
## 動機
> 學習如何設計大型系統。
>
> 準備系統設計的面試。
### 學習如何設計大型系統
學習如何設計可擴展的系統會幫助你成為一個更好的工程師。
系統設計是一個廣泛的主題。在網路上,關於**系統設計的資源也是不計其數**。
本專案將**許多資源進行分門別類**,幫助你學習如何建構可擴展的系統。
### 從開放原始碼社群中學習
這是一個早期、持續不斷更新的開放原始碼專案。
[任何貢獻](#如何貢獻) 都相當歡迎!
### 準備系統設計的面試
除了程式的面試外,系統設計在許多科技公司的**面試流程**中都是**必要**的一環。
**練習常見的系統設計問題**,並且將你的設計結果和**參考答案**進行**比對**:討論、程式碼和圖表。
關於面試的其他主題:
* [學習指南](#學習指南)
* [如何解決一個系統設計的面試題目](#如何解決一個系統設計的面試題目)
* [系統設計面試問題與**解答**](#系統設計面試問題與解答)
* [物件導向設計問題與**解答**](#物件導向設計面試問題與解答)
* [其他的系統設計面試問題](#其他的系統設計面試問題)
## 學習單字卡
<p align="center">
<img src="images/zdCAkB3.png">
<br/>
</p>
底下提供的[學習單字卡](https://apps.ankiweb.net/)以每隔一段時間間隔出現的方式,幫助你學習系統設計的概念。
* [系統設計單字卡](resources/flash_cards/System%20Design.apkg)
* [系統設計練習單字卡](resources/flash_cards/System%20Design%20Exercises.apkg)
* [物件導向設計練習單字卡](resources/flash_cards/OO%20Design.apkg)
這些是非常棒的學習資源,隨時都可以使用。
### 程式設計學習資源:互動式程式學習設計
你正在尋找資源來面對[**程式語言面試**](https://github.com/donnemartin/interactive-coding-challenges)嗎?
<p align="center">
<img src="images/b4YtAEN.png">
<br/>
</p>
請參考 [**互動程式語言學習挑戰**](https://github.com/donnemartin/interactive-coding-challenges),當中還包含了底下的學習單字卡:
* [程式語言學習單卡](https://github.com/donnemartin/interactive-coding-challenges/tree/master/anki_cards/Coding.apkg)
## 如何貢獻
> 從社群中學習
隨時歡迎提交 Pull Request
* 修正錯誤
* 改善章節內容
* 增加新的章節
* [翻譯](https://github.com/donnemartin/system-design-primer/issues/28)
某些還需要再完善的章節放在 [修正中](#仍在進行中)。
請參考 [貢獻指南](CONTRIBUTING.md)。
## 系統設計主題的索引
> 底下是數個系統設計的主題,包含了優點及缺點。**要記得,每一個系統設計的考量都包含著某種取捨**。
>
> 每一章節都包含更深入資源的連結。
<p align="center">
<img src="images/jrUBAF7.png">
<br/>
</p>
* [系統設計主題:從這裡開始](#系統設計主題從這裡開始)
* [第一步:複習關於可擴展性的影片講座](#第一步複習關於可擴展性的影片講座)
* [第二步:複習關於可擴展性的文章](#第二步複習關於可擴展性的文章)
* [下一步](#下一步)
* [效能與可擴展性](#效能與可擴展性)
* [延遲與吞吐量](#延遲與吞吐量)
* [可用性與一致性](#可用性與一致性)
* [CAP 理論](#cap-理論)
* [CP-一致性與部分容錯性](#cp-一致性與部分容錯性)
* [AP-可用性與部分容錯性](#ap-可用性與部分容錯性)
* [一致性模式](#一致性模式)
* [弱一致性](#弱一致性)
* [最終一致性](#最終一致性)
* [強一致性](#強一致性)
* [可用性模式](#可用性模式)
* [容錯轉移](#容錯轉移)
* [複寫機制](#複寫機制)
* [域名系統](#域名系統)
* [內容傳遞網路(CDN)](#內容傳遞網路cdn)
* [推送式 CDNs](#推送式-cdns)
* [拉取式 CDNs](#拉取式-cdns)
* [負載平衡器](#負載平衡器)
* [主動到備用切換模式(AP Mode)](#主動到備用切換模式ap-mode)
* [雙主動切換模式(AA Mode)](#雙主動切換模式aa-mode)
* [第四層負載平衡](#第四層負載平衡)
* [第七層負載平衡](#第七層負載平衡)
* [水平擴展](#水平擴展)
* [反向代理(網頁伺服器)](#反向代理網頁伺服器)
* [負載平衡器與反向代理伺服器](#負載平衡器與反向代理伺服器)
* [應用層](#應用層)
* [微服務](#微服務)
* [服務發現](#服務發現)
* [資料庫](#資料庫)
* [關連式資料庫管理系統(RDBMS)](#關連式資料庫管理系統rdbms)
* [主從複寫](#主從複寫)
* [主動模式複寫](#主動模式複寫)
* [聯邦式資料庫](#聯邦式資料庫)
* [分片](#分片)
* [反正規化](#反正規化)
* [SQL 優化](#sql-優化)
* [NoSQL](#nosql)
* [鍵-值對的資料庫](#鍵-值對的資料庫)
* [文件類型資料庫](#文件類型資料庫)
* [列儲存型資料庫](#列儲存型資料庫)
* [圖形資料庫](#圖形資料庫)
* [SQL 或 NoSQL](#sql-或-nosql)
* [快取](#快取)
* [客戶端快取](#客戶端快取)
* [CDN 快取](#cdn-快取)
* [網站伺服器快取](#網站伺服器快取)
* [資料庫快取](#資料庫快取)
* [應用程式快取](#應用程式快取)
* [資料庫查詢級別的快取](#資料庫查詢級別的快取)
* [物件級別的快取](#物件級別的快取)
* [什麼時候要更新快取](#什麼時候要更新快取)
* [快取模式](#快取模式)
* [寫入模式](#寫入模式)
* [事後寫入(回寫)](#事後寫入回寫)
* [更新式快取](#更新式快取)
* [非同步機制](#非同步機制)
* [訊息佇列](#訊息佇列)
* [工作佇列](#工作佇列)
* [背壓機制](#背壓機制)
* [通訊](#通訊)
* [傳輸控制通訊協定(TCP)](#傳輸控制通訊協定tcp)
* [使用者資料流通訊協定 (UDP)](#使用者資料流通訊協定-udp)
* [遠端程式呼叫 (RPC)](#遠端程式呼叫-rpc)
* [具象狀態轉移 (REST)](#具象狀態轉移-rest)
* [資訊安全](#資訊安全)
* [附錄](#附錄)
* [2 的次方表](#2-的次方表)
* [每個開發者都應該知道的延遲數量級](#每個開發者都應該知道的延遲數量級)
* [其他的系統設計面試問題](#其他的系統設計面試問題)
* [真實世界的架構](#真實世界的架構)
* [公司的系統架構](#公司的系統架構)
* [公司的工程部落格](#公司的工程部落格)
* [仍在進行中](#仍在進行中)
* [致謝](#致謝)
* [聯絡資訊](#聯絡資訊)
* [授權](#授權)
## 學習指南
> 基於你面試的時間 (短、中、長) 來複習這些建議的主題。
![Imgur](images/OfVllex.png)
**Q: 對於面試者來說,我需要知道這裡所有的知識嗎?**
**A: 不,如果是為了面試,你不需要知道這裡所有的知識**
在一場面試中,你會被問到什麼問題取決於以下幾點:
* 你有多少經驗
* 你的技術背景
* 你面試什麼職位
* 你面試什麼公司
* 你的幸運程度
越有經驗的面試者通常被期望瞭解更多系統設計的知識。如果是架構師或團隊負責人則被預期瞭解更多除了個人貢獻以外的知識。頂尖的科技公司通常也會有一次或多次的系統設計面試。
面試時,會很廣泛地展開,並在幾個特定領域深入探討。這裡會幫助你了解一些系統設計不同的主題,基於你面試的時間、經驗、職位和公司來調整你所需要涉獵的知識內容。
* **短期** - 以系統設計的**廣度**為目標。通過解決**一些**面試題目來練習。
* **中期** - 以系統設計的**廣度**和**初級深度**為目標。通過解決**很多**面試題目來練習。
* **長期** - 以系統設計主題的**廣度**和**高級深度**為目標。通過解決**大部分**面試題目來練習。
| | 短期 | 中期 | 長期 |
|---------------------------------------------------------------------------------|------|------|--------|
| 閱讀 [系統設計主題的索引](#系統設計主題的索引) 來取得關於系統如何運作的廣泛知識 | :+1: | :+1: | :+1: |
| 閱讀一些你要面試的 [公司的工程部落格](#公司的工程部落格) 文章 | :+1: | :+1: | :+1: |
| 閱讀關於 [真實世界的架構](#真實世界的架構) | :+1: | :+1: | :+1: |
| 複習 [如何解決一個系統設計的面試題目](#如何解決一個系統設計的面試題目) | :+1: | :+1: | :+1: |
| 完成 [系統設計面試題目與解答](#系統設計面試問題與解答) | 一些 | 很多 | 大部分 |
| 完成 [物件導向設計與解答](#物件導向設計面試問題與解答) | 一些 | 很多 | 大部分 |
| 複習 [其他的系統設計面試問題](#其他的系統設計面試問題) | 一些 | 很多 | 大部分 |
## 如何解決一個系統設計的面試題目
> 如何面對一個系統設計的面試題目
系統設計是一個**開放式的對話過程**,面試官會期望由你來主導這個對話。
你可以使用下面的步驟來引導整個討論過程。為了鞏固這個流程,請使用下面的步驟完成 [系統設計面試題目與解答](#系統設計面試問題與解答) 這個章節。
### 第一步:描述使用的場景、限制及假設
把問題的需求和範圍等資訊搜集起來。詢問以下問題,讓我們可以明確的定義使用場景和限制,對於提出的假設進行討論:
* 誰會使用這個系統?
* 他們怎麼使用系統?
* 有多少使用者?
* 系統的作用是什麼?
* 系統的輸入和輸出是什麼?
* 我們預期希望處理多少資料?
* 我們希望每秒處理多少請求?
* 預期的讀、寫比例為何?
### 第二步:建立一個高階的設計
使用重要的元件來建立一個高階的設計。
* 畫出主要的元件與其相互連接情況
* 證明你的想法
### 第三步: 設計核心的元件
對每一個核心元件進行深入的分析。舉例來說, 如果你被問到 [設計一個短網址的服務](solutions/system_design/pastebin/README.md) ,可以開始討論以下內容:
* 產生並儲存一個完整網址的 Hash
* [MD5](solutions/system_design/pastebin/README.md) 和 [Base62](solutions/system_design/pastebin/README.md)
* Hash 碰撞
* SQL 或 NoSQL
* 資料庫的模型
* 將一個 hash 過後的網址轉換為完整的網址
* 資料庫查詢
* API 和物件導向設計
### 第四步:評估你的設計
確認及指出你的設計的瓶頸與限制,舉例來說,你需要底下幾個元件來擴展你的設計嗎?
* 負載平衡
* 水平擴展
* 快取
* 資料庫切片
針對你的設計討論可能的解決方法與代價。每個設計都有取捨。使用 [可擴展的設計原則](#系統設計主題:從這裡開始) 來處理系統瓶頸。
### 快速有效的進行估算
你可能被要求針對你的設計進行一些估算,可以參考 [附錄](#附錄) 的一些資源:
* [使用快速估算法](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
* [2 的次方表](#2-的次方表)
* [每個開發者都應該知道的延遲數量級](#每個開發者都應該知道的延遲數量級)
### 相關資源與延伸閱讀
查看以下的連結獲得更好的做法:
* [如何在系統設計的面試中勝出](https://web.archive.org/web/20210505130322/https://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)
* [系統設計的面試](http://www.hiredintech.com/system-design)
* [系統架構與設計的面試介紹](https://www.youtube.com/watch?v=ZgdS0EUmn70)
## 系統設計面試問題與解答
> 常見的系統設計面試問題與相關範例的討論、程式碼以及圖表。
>
> 相關的解答位於 `solutions/` 的資料夾中。
| 問題 | |
|-----------------------------------------------------------------------------------------------------|--------------------------------------------------------|
| 設計 Pastebin.com (或 Bit.ly) | [解答](solutions/system_design/pastebin/README.md) |
| 設計一個像是 Twitter 的 timeline (或 Facebook feed)設計一個 Twitter 搜尋功能 (or Facebook 搜尋功能) | [解答](solutions/system_design/twitter/README.md) |
| 設計一個爬蟲系統 | [解答](solutions/system_design/web_crawler/README.md) |
| 設計 Mint.com 網站 | [解答](solutions/system_design/mint/README.md) |
| 設計一個社交網站的資料結構 | [解答](solutions/system_design/social_graph/README.md) |
| 設計一個搜尋引擎使用的鍵值儲存資料結構 | [解答](solutions/system_design/query_cache/README.md) |
| 設計一個根據產品分類的亞馬遜銷售排名 | [解答](solutions/system_design/sales_rank/README.md) |
| 在 AWS 上設計一個百萬用戶等級的系統 | [解答](solutions/system_design/scaling_aws/README.md) |
| 增加一個系統設計的問題 | [貢獻](#如何貢獻) |
### 設計 Pastebin.com (或 Bit.ly)
[閱讀練習與解答](solutions/system_design/pastebin/README.md)
![Imgur](images/4edXG0T.png)
### 設計一個像是 Twitter 的 timeline (或 Facebook feed)設計一個 Twitter 搜尋功能 (or Facebook 搜尋功能)
[閱讀練習與解答](solutions/system_design/twitter/README.md)
![Imgur](images/jrUBAF7.png)
### 設計一個爬蟲系統
[閱讀練習與解答](solutions/system_design/web_crawler/README.md)
![Imgur](images/bWxPtQA.png)
### 設計 Mint.com 網站
[閱讀練習與解答](solutions/system_design/mint/README.md)
![Imgur](images/V5q57vU.png)
### 設計一個社交網站的資料結構
[閱讀練習與解答](solutions/system_design/social_graph/README.md)
![Imgur](images/cdCv5g7.png)
### 設計一個搜尋引擎使用的鍵值儲存資料結構
[閱讀練習與解答](solutions/system_design/query_cache/README.md)
![Imgur](images/4j99mhe.png)
### 設計一個根據產品分類的亞馬遜銷售排名
[閱讀練習與解答](solutions/system_design/sales_rank/README.md)
![Imgur](images/MzExP06.png)
### 在 AWS 上設計一個百萬用戶等級的系統
[閱讀練習與解答](solutions/system_design/scaling_aws/README.md)
![Imgur](images/jj3A5N8.png)
## 物件導向設計面試問題與解答
> 常見的物件導向面試問題與案例探討、程式碼與圖表。
>
> 相關的答案位於 `solutions/` 目錄中。
>**注意: 本章節仍在完善內容中**
| 問題 | |
|--------------------------|----------------------------------------------------------------------------|
| 設計一個 hash map | [解答](solutions/object_oriented_design/hash_table/hash_map.ipynb) |
| 設計一個 LRU 快取 | [解答](solutions/object_oriented_design/lru_cache/lru_cache.ipynb) |
| 設計一個客服系統 | [解答](solutions/object_oriented_design/call_center/call_center.ipynb) |
| 設計一副牌 | [解答](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| 設計一個停車場 | [解答](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| 設計一個環形陣列 | [如何貢獻](#如何貢獻) |
| 增加一個物件導向設計問題 | [如何貢獻](#如何貢獻) |
## 系統設計主題:從這裡開始
你是系統設計的新手嗎?
首先,你需要對於基本的原則有一定的認識,知道他們是什麼,如何使用,以及他們的優缺點。
### 第一步:複習關於可擴展性的影片講座
[哈佛大學可擴展性的影片](https://www.youtube.com/watch?v=-W9F__D3oY4)
* 包含以下主題:
* 垂直擴展
* 水平擴展
* 快取
* 負載平衡
* 資料庫複寫
* 資料庫分割
### 第二步:複習關於可擴展性的文章
[可擴展性](https://lecloud.tumblr.com/tagged/scalability)
* 包含以下主題:
* [複製](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [資料庫](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [快取](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [非同步](https://lecloud.tumblr.com/post/9699762917/scalability-for-dummies-part-4-asynchronism)
### 下一步
接下來,我們需要看看某些取捨:
* **效能** vs **可擴展性**
* **延遲** vs **吞吐量**
* **可用性** vs **一致性**
記住,任何設計都是取捨。
接著,我們將會深入更具體的主題,包含 DNS、CDN 和負載平衡。
## 效能與可擴展性
如果服務**性能**的增加和資源的投入是成正比時,代表服務是可擴展的。一般來說,增加性能代表服務更多的工作單元,也可以處理更多的資料。<sup><a href="http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html">1</a></sup>
從另一方面來看看性能與可擴展性:
* 如果你的系統存在**性能**問題時,對單一使用者來說的感覺是慢的。
* 如果你的系統存在**可擴展性**問題時,對於單一使用者來說感覺較快,但在高負載的時候就會變慢。
### 來源及延伸閱讀
* [簡談可擴展性](http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)
* [可擴展性、可用性、穩定性與相關模式](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
## 延遲與吞吐量
**延遲** 指執行一個操作或運算結果所花費的時間。
**吞吐量** 指單位時間內執行此類型操作或運算的數量。
一般來說,你應該以**可接受的延遲**數量下的**最大化吞吐量**為設計目標。
### 來源及延伸閱讀
* [了解延遲與吞吐量](https://community.cadence.com/cadence_blogs_8/b/sd/archive/2010/09/13/understanding-latency-vs-throughput)
## 可用性與一致性
### CAP 理論
<p align="center">
<img src="images/bgLMI2u.png">
<br/>
<i><a href=http://robertgreiner.com/2014/08/cap-theorem-revisited>來源:再看 CAP 理論</a></i>
</p>
在一個分散式系統中,只能滿足以下三個項目的任兩項:
* **一致性** - 每次讀取都可以得到最新的資料,但偶爾會拿到錯誤
* **可用性** - 每次讀取都可以得到非錯誤的回應,但不能保證可以得到最新的資料
* **部分容錯性** - 在任意分區的網路故障情況下,系統仍然能夠持續運行
*網路是不可靠的,你的設計必須要確保部分容錯性,所以你只能夠在一致性與可用性中做出取捨。*
#### CP-一致性與部分容錯性
等待分區的節點回覆可能會導致超時錯誤如果你的系統的需求是需要保證原子讀寫時CP 是一個不錯的選擇。
#### AP-可用性與部分容錯性
每個進行回覆的節點中的最新版本可能不是最新的,當分區節點解析完畢後,寫入的操作可能需要一些時間來傳播資料。
當你的系統需求需要保證 [最終一致性](#最終一致性) 或當外部系統故障時系統要能夠繼續運作時AP 是一個不錯的選擇。
### 來源及延伸閱讀
* [複習 CAP 理論](http://robertgreiner.com/2014/08/cap-theorem-revisited/)
* [簡單的介紹 CAP 理論](http://ksat.me/a-plain-english-introduction-to-cap-theorem)
* [CAP 問與答](https://github.com/henryr/cap-faq)
## 一致性模式
當你的資料有多個副本時,要考慮怎麼同步他們,以便讓使用者有一致的資料顯示。想想 [CAP 理論](#cap-理論) 中的一致性定律 - 每次的訪問都可以得到最新的資料,但可能也會收到錯誤的回應。
### 弱一致性
在寫入之後,任何的存取不一定可以拿到資料,弱一致性將盡力確保能存取到最新的資料。
這種方式可以在 memcached 等系統中看到。弱一致性可以在 VoIP、視訊聊天或其他即時多人線上遊戲中看到相關的使用案例。比方說如果你在通話中遺失幾秒鐘時間的資料再重新連接後你是無法聽到這幾秒鐘的內容。
### 最終一致性
在寫入後的讀取操作最終可以看到被寫入的資料(通常在數毫秒內)。資料透過非同步的方式被複製。
DNS 或是電子郵件系統使用的就是這種方式,最終一致性在高可用的系統中效果很好。
### 強一致性
在寫入後,讀取將立刻取得資料,資料是透過同步的方式寫入。
檔案系統或資料庫系統就是使用這種方式,強一致性在需要紀錄的系統中表現很好。
### 來源及延伸閱讀
* [資料中心的記錄行為](http://snarfed.org/transactions_across_datacenters_io.html)
## 可用性模式
關於可用性有兩種模式:**容錯轉移** 和 **複寫**
### 容錯轉移
#### 主動到備用切換模式(AP Mode)
在這個模式下heartbeat 訊號會在主動和備用的機器中發送,當 heartbeat 中斷時,備用的機器就會切換為主動機器的 IP 位置接替服務。
當機的時間取決於備用的機器是在「熱」待機狀態還是「冷」待機狀態。只有處於主動的機器會處理使用者來的流量。
這個模式的切換也被稱為主從的切換模式。
#### 雙主動切換模式(AA Mode)
在此模式下,兩台伺服器都會負責處理流量,流量會在他們之間進行分散負載。
如果是外部網路的伺服器DNS 需要知道兩台機器的 IP 位置,如果是內部網路的伺服器,應用程式邏輯需要知道這兩台機器。
雙主動切換模式也被稱為 master-master 切換。
### 缺點:容錯轉移
* 容錯轉移會需要增加額外的硬體與複雜度。
* 如果在新寫入的資料被複製到備用的機器前系統就發生故障,那有可能會遺失資料。
### 複寫機制
#### 主動到備用複寫與雙主動複寫
這一個主題進一步討論了 [資料庫](#資料庫) 部分:
* [主動到備用複寫](#主動到備用複寫)
* [雙主動複寫](#雙主動複寫)
## 域名系統
<p align="center">
<img src="images/IOyLj4i.jpg">
<br/>
<i><a href=http://www.slideshare.net/srikrupa5/dns-security-presentation-issa>資料來源DNS 安全介紹</a></i>
</p>
DNS 是將域名轉換為 IP 地址的系統。
DNS 是階層式的架構,一部分的 DNS 伺服器位於頂層,當查詢域名時,你的路由器或 ISP 業者會提供連接到 DNS 伺服器的資訊。較底層的 DNS 伺服器會快取查詢的結果,而這些快取資訊會因為 DNS 的傳遞而逐漸更新。DNS 的結果可以暫存在瀏覽器或操作系統中一段時間,時間的長短取決於 [存活時間(TTL)](https://en.wikipedia.org/wiki/Time_to_live) 的設定。
* **NS 記錄 (域名伺服器)** - 指定解析域名或子域名的 DNS 伺服器。
* **MX 記錄 (電子郵件交換伺服器)** - 指定接收電子郵件的伺服器。
* **A 記錄 (地址)** - 指向要對應的 IP 位置。
* **CNAME (別名)** - 從一個域名指向另外一個域名,或是 `CNAME` (example.com 指向 www.example.com) 或指向一個 `A` 記錄。
[CloudFlare](https://www.cloudflare.com/dns/) 和 [Route 53](https://aws.amazon.com/route53/) 提供了 DNS 的服務。而這些 DNS 服務商透過以下幾種方式來決定流量如何被分派:
* [加權輪詢](https://www.jscape.com/blog/load-balancing-algorithms)
* 防止流量進入正在維修中的伺服器
* 在不同大小的集群中進行負載平衡
* A/B 測試
* 基於延遲來路由請求
* 基於地理位置來路由請求
### DNS 的缺點
* 儘管可以透過快取來減輕 DNS 的延遲,但連接 DNS 伺服器還是帶來了些許的延遲。
* DNS 伺服器的管理是複雜的,儘管他通常由 [政府、ISP 業者或大公司](http://superuser.com/questions/472695/who-controls-the-dns-servers/472729) 來處理。
* DNS 伺服器會有 [DDoS 攻擊](http://dyn.com/blog/dyn-analysis-summary-of-friday-october-21-attack/) ,讓不知道 Twitter IP 的使用者無法訪問 Twitter 網站。
### 來源及延伸閱讀
* [DNS 架構](https://technet.microsoft.com/en-us/library/dd197427(v=ws.10).aspx)
* [維基百科](https://en.wikipedia.org/wiki/Domain_Name_System)
* [DNS 文章](https://support.dnsimple.com/categories/dns/)
## 內容傳遞網路(CDN)
<p align="center">
<img src="images/h9TAuGI.jpg">
<br/>
<i><a href=https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/>來源:為什麼要使用 CDN</a></i>
</p>
內容傳遞網路(CDN)是一種全球性的分散式代理伺服器,它透過靠近使用者的伺服器來提供檔案。通常 HTML/CSS/JS、圖片、影片或靜態檔案等......會透過 CDN 來提供,儘管 Amazon 的 CloudFront 也支援了動態內容的 CDN 服務。而 CDN 的 DNS 服務會告知使用者要連接哪一台伺服器。
透過 CDN 來取得檔案可以大幅度地增加請求的效率,因為:
* 從靠近使用者的伺服器來拿檔案
* 透過 CDN 來回應使用者,你的原始伺服器不需要處理請求
### 推送式 CDNs
當你的伺服器有檔案變動時,推送 CDN 會接收到新的變動內容,並重寫 URL 位置指向新的內容。你可以設定檔案內容什麼時候過期以及何時更新,檔案內容只有在變更或新增的時候才會推送,最小化流量,但最大化儲存。
流量較小的網站,或是內容不是經常更新的網站使用推送式的 CDN 相當適合,因為內容會被經常放置在 CDN 內,而不是常常需要重新抓取新檔案。
### 拉取式 CDNs
拉取式的 CDN 指的是當地一個使用者來請求該資源時,才從伺服器上抓取對應檔案。將檔案留在伺服器上並且重寫指向 CDN 的 URL直到檔案被快取在 CDN 上為止,請求都會比較慢。
[存活時間 (TTL)](https://en.wikipedia.org/wiki/Time_to_live) 決定檔案要被緩存多久的時間。拉取式 CDN 可以節省儲存空間,但在過期的文件被更新之前,則會導致多餘的流量。
拉取式的 CDN 適合高流量的網站,因為檔案會被平均的分散在各個結點伺服器中。
### CDN 的缺點
* CDN 的成本取決於流量,在權衡評估後,你可能會因為成本而放棄使用。
* 如果在 TTL 過期之前就更新內容CDN 的緩存內容可能會過期。
* 需要改變靜態內容的網址來指向 CDN。
### 來源及延伸閱讀
* [全球性的 CDN](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci)
* [拉取式和推拉式 CDN 的差別](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)
* [維基百科](https://en.wikipedia.org/wiki/Content_delivery_network)
## 負載平衡器
<p align="center">
<img src="images/h81n9iK.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>來源:可擴展的系統設計模式</a></i>
</p>
負載平衡將使用者的請求分發到後端伺服器和資料庫,不管是哪種情況,負載平衡器會將回應返回給對應的使用者。而負載平衡器之所以有效在於以下幾點:
* 避免請求被轉到非正常運作的伺服器
* 避免資源過載
* 避免單點失敗
負載平衡器可以透過硬體(較昂貴)或 HAProxy 等軟體來實現。
其餘額外的好處有:
* **SSL 終結** - 將傳入的請求解密,並且加密伺服器的回應,如此一來後端伺服器就不需要進行這些高度消耗資源的運算
* 不需要在每一台機器上安裝 [X.509 憑證](https://en.wikipedia.org/wiki/X.509)。
* **Session 保存** - 發行 cookie並將特定使用者的請求路由到同樣的後端伺服器上。
為了避免故障,通常會採用 [主動到備用切換模式](#主動到備用切換模式(AP Mode)) 或 [雙主動切換模式](#雙主動切換模式(AA Mode)) 這樣多個負載平衡器的模式。
負載平衡器會基於多種方法來路由請求:
* 隨機
* 最少負載
* Session/cookies
* [輪詢調度或加權輪詢調度](http://g33kinfo.com/info/archives/2657)
* [第四層負載平衡](#第四層負載平衡)
* [第七層負載平衡](#第七層負載平衡)
### 第四層負載平衡
第四層的負載平衡器會監看 [傳輸層](#傳輸層) 的資訊來決定如何分發請求。一般來說,這包含了來源、目標 IP 位置,以及在 header 中的 port但不包含資料本身的內容。第四層的負載平衡器會透過 [網路地址轉換(NAT)](https://www.geeksforgeeks.org/network-address-translation-nat/) 來向上游的伺服器轉發資料。
### 第七層負載平衡
第七層的負載平衡器會監看 [應用層](#應用層) 來決定如何分發請求。這包含了請求的 header、訊息和 cookies。這種負載平衡器會終結網路的流量、讀取訊息並做出如何轉發訊息的決定並把流量轉往對應的伺服器。舉例來說一個第七層的負載平衡器可以將影音的流量轉往負責影音流量的伺服器而將更敏感的使用者帳單的請求轉往安全性更強的伺服器。
第四層的負載平衡比起第七層的所要花費的時間和計算資源更低,雖然這對於現代商用硬體的性能影響已經微乎其微了。
### 水平擴展
負載平衡器一樣可以幫助水平擴展,提高性能與可用性。使用這種方式的擴展比起在單一機器的**垂直擴展**來說性價比更高,同時,聘請商用硬體的人才比起特定企業級系統人才來的更加容易。
#### 水平擴展的缺點
* 水平擴展會增加複雜性,同時也涉及了多台伺服器的議題
* 伺服器應該是無狀態的:不應該包括像是 session 或資料圖片等和使用者相關的內容
* Session 可以集中儲存在資料庫或 [快取](#快取)(Redis、Memcached) 等資料儲存中。
* 快取伺服器或資料庫需要隨著伺服器的增加而進行擴展,以便處理更多的請求。
### 負載平衡器的缺點
* 當負載平衡器資源不夠或沒有正確設定時,他可能會成為效能的瓶頸
* 使用負載平衡器來避免單點失敗會增加架構的複雜性
* 只有一台負載平衡器時,一樣有單點失敗的問題。而多台的負載平衡器一樣增加了架構的複雜性。
### 來源及延伸閱讀
* [NGINX 架構](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy 架構指南](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [可擴展性](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [維基百科](https://en.wikipedia.org/wiki/Load_balancing_(computing))
* [第四層負載平衡](https://www.nginx.com/resources/glossary/layer-4-load-balancing/)
* [第七層負載平衡](https://www.nginx.com/resources/glossary/layer-7-load-balancing/)
* [ELB 監聽器設定](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html)
## 反向代理(網頁伺服器)
<p align="center">
<img src="images/n41Azff.png">
<br/>
<i><a href=https://upload.wikimedia.org/wikipedia/commons/6/67/Reverse_proxy_h2g2bob.svg>來源:維基百科</a></i>
<br/>
</p>
反向代理伺服器是一個集中內部服務,並提供統一個介面給公開使用者的伺服器。來自客戶端的請求會先被反向代理伺服器轉發到可以接收服務的伺服器,然後再由代理伺服器將結果返回給客戶端。
這樣做的好處有:
* **增加安全性** - 隱藏後端伺服器的資訊、可以設定 IP 的黑名單、限制每個客戶端的連線數量等。
* **增加可擴展性與靈活性** - 客戶端只會看到反向代理伺服器的 IP 或域名,這樣你就可以增加背後伺服器的數量或設定而不影響客戶端。
* **SSL 終止** - 解密傳入的請求、加密伺服器的回應,這樣後端伺服器就不需要進行這些高成本的操作
* 不需要在每一台伺服器安裝 [X.509 憑證](https://en.wikipedia.org/wiki/X.509)。
* **壓縮** - 壓縮伺服器的回應
* **快取** - 直接在代理伺服器回應命中快取的結果
* **靜態檔案** - 直接提供靜態內容
* HTML/CSS/JS
* 圖片
* 影片
* 等等
### 負載平衡器與反向代理伺服器
* 當有多台伺服器時,使用負載平衡非常有用,一般來說,負載平衡器會將流量路由給一組功能相同的伺服器上。
* 即使只有一台伺服器或應用伺服器,反向代理也是有用的。可以參考上述的好處。
* Nginx 或 HAProxy 等解決方案可以同時支援第七層的反向代理與負載平衡
### 反向代理伺服器的缺點
* 引入反向代理伺服器會增加系統複雜度。
* 只有一台反向代理伺服器會有單點失效的問題,而設定多台的反向代理伺服器(如 [故障轉移](https://en.wikipedia.org/wiki/Failover) )同樣會增加系統複雜度。
### 來源與延伸閱讀
* [反向代理伺服器與負載平衡](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)
* [NGINX 架構](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy 架構指南](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [維基百科](https://en.wikipedia.org/wiki/Reverse_proxy)
## 應用層
<p align="center">
<img src="images/yB5SYwm.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>資料來源:可縮放式系統架構介紹</a></i>
</p>
將 Web 服務層與應用層(也被稱為平台層)分離,如此一來這兩層就可以獨立縮放與設定,增加新的 API 服務只需要增加應用伺服器,而不需要增加額外的 Web 伺服器。
**單一職責原則**鼓勵小型、自治的服務與共同合作,小型團隊透過提供小型的服務可以更有效率地讓計畫成長。
在應用層中的工作程式可以實作 [非同步機制](#非同步機制)
### 微服務
相關的主題還有 [微服務](https://en.wikipedia.org/wiki/Microservices) ,指的是可以獨立運作、小型的模組化服務。每個服務會透過明確定義好的輕量級溝通機制,運作在一個獨立的流程中來共同實現一個目標。<sup><a href=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
舉例來說Pinterest 可能有以下這些微服務使用者資料、跟隨者、Feed、搜尋、照片上傳等等。
### 服務發現
[Consul](https://www.consul.io/docs/index.html)、[Etcd](https://coreos.com/etcd/docs/latest), 或是 [Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) 等系統可以透過註冊的名稱、位置、Port 等資訊來幫助各個服務發現彼此。[Health checks](https://www.consul.io/intro/getting-started/checks.html) 可以幫助確認服務的完整性以及是否經常使用一個 [HTTP](#hypertext-transfer-protocol-http) 的路徑。[鍵-值對的資料庫](#鍵-值對的資料庫) 則用來儲存設定的資訊與其他共享的資料。
### 應用層的缺點
* 設計多個鬆耦合微服務所組成的應用層,必須從架構、維運、流程等多個面向來考量,相對於單系統而言會非常不同。
* 微服務會增加部署與維運的複雜度。
### 來源與延伸閱讀
* [可擴展式系統架構介紹](http://lethain.com/introduction-to-architecting-systems-for-scale)
* [破解系統設計面試](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [面向服務架構](https://en.wikipedia.org/wiki/Service-oriented_architecture)
* [Zookeeper 介紹](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper)
* [建構微服務系統你所需要知道的一切](https://cloudncode.wordpress.com/2016/07/22/msa-getting-started/)
## 資料庫
<p align="center">
<img src="images/Xkm5CXz.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=vg5onp8TU6Q>來源:擴展你的使用者數量到第一個一千萬量級</a></i>
</p>
### 關連式資料庫管理系統(RDBMS)
像 SQL 這種關連式資料庫是以一組表格的形式存在的資料集合。
**ACID** 是用來描述資料庫 [事務](https://en.wikipedia.org/wiki/Database_transaction) 的特性。
* **原子性** - 每一個資料庫事務操作要不就是全部完成,要不就是全部不完成。
* **一致性** - 任何一個資料庫事務操作都會讓資料庫從一個有效的狀態轉換到另外一個有效狀態。
* **隔離性** - 併發執行資料庫事務操作的結果會和循序執行的結果一致。
* **持久性** - 一旦一個事務被資料庫執行後,他的結果與影響是擁永久保存的。
要針對關聯式資料庫系統進行擴展有許多方法: **主從複寫**, **主動模式複寫**, **聯邦式資料庫**, **分片**, **反正規化**, 和 **SQL 優化**.
#### 主從複寫
主資料庫負責讀和寫,並且將寫入的資料複寫至一或多個從屬資料庫中,從屬資料庫只負責讀取。而從屬資料庫可以再將寫入複製到更多以樹狀結構的其他資料庫中。如果主資料庫離線了,系統可以以只讀模式運行,直到某個從屬資料庫被提升為主資料庫,或有新的主資料庫出現。
<p align="center">
<img src="images/C9ioGtn.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>來源: 可擴展性、可用性、穩定性及其模式</a></i>
</p>
##### 主從複寫的缺點
* 需要額外的處理邏輯來將從屬資料庫提升為主要資料庫。
* 參考 [複寫的缺點](#複寫的缺點) 章節,你可以看到主動模式複寫與主從模式**共同**的缺點。
#### 主動模式複寫
兩個主要的資料庫都負責讀取和寫入,並且兩者互相協調。如果其中一個主要資料庫離線,系統可以繼續運作。
<p align="center">
<img src="images/krAHLGg.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>來源: 可擴展性、可用性、穩定性及其模式</a></i>
</p>
##### 主動模式的缺點
* 你需要一個負載平衡器來或是在你的應用程式邏輯中做修改來決定要寫入哪個資料庫。
* 大多數的主動模式資料庫無法保證一致性(違反 ACID),或是會因為同步而產生了寫入延遲。
* 隨著更多寫入節點的增加和延遲的提高,如何解決衝突就顯得更加重要。
* 參考 [複寫的缺點](#複寫的缺點) 章節,你可以看到主動模式複寫與主從模式**共同**的缺點。
##### 複寫的缺點
* 如果在主要資料庫複製到其他結點前系統就失效,則會有資料丟失的可能。
* 當有過多寫入時,讀取的資料庫可能會因為過多寫入操作而被阻塞,導致讀取功能異常。
* 當讀取的資料庫越多時,需要複寫的資料越多,將會導致較為嚴重的延遲。
* 在某些資料庫系統中,寫入主資料庫的操作可以用多執行緒來並行寫入,但讀取的資料庫只支援單一執行緒來循序寫入。
* 複寫意味著更多的硬體以及更高的複雜度。
##### 來源及延伸閱讀
* [可擴展性、可用性、穩定性及其模式](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [多主要資料庫複寫](https://en.wikipedia.org/wiki/Multi-master_replication)
#### 聯邦式資料庫
<p align="center">
<img src="images/U3qV33e.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=vg5onp8TU6Q>來源:擴展你的使用者數量到第一個一千萬量級</a></i>
</p>
聯邦式資料庫(或是指功能式切分)是將資料庫按照對應的功能進行分割。例如:你可以三個資料庫,分別是:**論壇**、**使用者**和**產品**,而不僅僅是單一資料庫。這樣會減少每個資料庫寫入與讀取的流量,進而降低複製的延遲。較少的資料意味者更多適合放入記憶體中的資料,進而增加快取命中率。因為沒有循序寫入的中央式主資料庫,你可以並行寫入以增加吞吐量。
##### 聯邦式資料庫的缺點
* 如果你的資料表需要大量的功能和資料表,聯邦式資料庫的效率並不好。
* 需要更新應用程式的邏輯來決定如何讀取和寫入到哪個資料庫。
* 透過 [server link](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers) 從兩個資料庫中關資料更加複雜。
* 聯邦式資料庫需要更多的硬體和額外的複雜度。
##### 來源及延伸閱讀
* [來源:擴展你的使用者數量到第一個一千萬量級](https://www.youtube.com/watch?v=vg5onp8TU6Q)
#### 分片
<p align="center">
<img src="images/wU8x5Id.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>來源: 可擴展性、可用性、穩定性及其模式</a></i>
</p>
分片是指將資料分配在不同的資料庫上,使每個資料庫只管理整個資料的部分子集。以使用者資料庫為例,隨著使用者數量的增加,越來越多的分片會被加入到群集當中。
類似於 [聯邦式資料庫](#聯邦式資料庫) 的優點,分片可以減少讀取和寫入的流量、減少複製並提高快取命中率。索引的容量也會減少,如此一來可以改善查詢的效能。當一個分片出現問題時,其餘的仍然可以正常運作,而為了避免資料遺失,你可能需要思考其他複寫的機制。如同聯邦式資料庫,分片的機制並沒有中央式的資料庫,你可以並行寫入以增加吞吐量。
以使用者資料庫為例,常見的做法是用使用者姓氏的部首或使用者地理問位置來區隔使用者資料表。
##### 分片的缺點
* 你需要修改應用程式的邏輯來實作分片,這可能會導致 SQL 變得複雜。
* 不合理的分片可能會導致資料負載不均,例如,頻繁被訪問的使用者資料如果被放置在同一個分片中,會導致該分片負載相對較高。
* 再平衡會需要額外的複雜度。基於 [一致性 hash](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html) 的分片演算法可以減少這種情形。
* 從多個分片中操作資料會很複雜。
* 分片需要額外的硬體和複雜度。
##### 來源及延伸閱讀
* [分片時代來臨](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)
* [分片資料庫架構](https://en.wikipedia.org/wiki/Shard_(database_architecture))
* [一致性 hashing](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)
#### 反正規化
反正規化嘗試以寫入的性能作為代價來改善讀取性能。透過在不同資料表中的重複資料來避免高成本的 Join 操作。
某些關連式資料庫,例如 [PostgreSQL](https://en.wikipedia.org/wiki/PostgreSQL) 和 Oracle 支援 [materialized views](https://en.wikipedia.org/wiki/Materialized_view) ,可以用來處理重複資料的儲存,以及保證這些資料的一致性。
一旦資料使用如 [聯合](#聯合) 或 [切片](#切片) 等技術被分割,處理跨資料中心 Join 操作的複雜度。反正規化可以避免這種複雜的操作。
在多數系統中,讀取的操作頻率會遠高於寫入的頻率,比例可能會到 100:1 甚至 1000:1。進行複雜讀取操作的成本很高會在硬碟上消耗大量的時間。
##### 反正規化的缺點
* 資料會重複存取
* Constraints 的機制可以讓重複的資料保持同步,但這樣會增加資料庫設計的複雜度。
* 反正規化的資料庫在大量寫入負載的情況下,性能表現可能會比正規化的資料庫差。
###### 來源及延伸閱讀
* [反正規化](https://en.wikipedia.org/wiki/Denormalization)
#### SQL 優化
SQL 優化是一個涵蓋範圍很廣的主題,有許多相關的 [參考書籍](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning) 可以做為參考。
透過 **效能測試****效能分析** 來模擬並發現系統的瓶頸是很重要的。
* **效能測試** - 透過 [ab](http://httpd.apache.org/docs/2.2/programs/ab.html) 等工具來測試高負載的情況。
* **效能分析** - 使用 [slow query log](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html) 等工具來追蹤性能問題。
效能測試和效能分析可能會引導你到以下的優化方案。
##### 使用較為精準的 schema
* 為了加快存取速度MySQL 會在硬碟上使用連續的 block 來儲存資料。
* 使用 `CHAR` 來儲存固定長度的資料,不要使用 `VARCHAR`
* `CHAR` 在快速、隨機存取時效率很高。如果使用 `VARCHAR`,想要讀取下一個字元時,需要先讀取到目前字元的尾端。
* 使用 `TEXT` 來儲存大量的文字,例如部落格文章。`TEXT` 還可以使用布林搜尋。使用 `TEXT` 時,會在硬碟上保存一個指向硬碟區塊的指標。
* 使用 `INT` 來儲存數量級達到 2^32 或 40 億等較大的數字。
* 使用 `DECIMAL` 來儲存貨幣資料可以避免浮點數表達錯誤。
* 避免儲存龐大的 `BLOBS`,取而代之的,應該儲存存放該對象的位置。
* `VARCHAR(255)` 是使用 8 位數來儲存時的最大表示法,在某些關連式資料庫中,要最大限度地使用它。
* 在適用的情況下設定 `NOT NULL` 來 [提高搜尋性能](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)。
##### 使用正確的索引
* 當你使用 (`SELECT`, `GROUP BY`, `ORDER BY`, `JOIN`) 這些操作的對應欄位如果有使用索引就會查詢更快。
* 索引通常是使用平衡 [B 樹](https://en.wikipedia.org/wiki/B-tree) 表示,這樣可以保證資料是有序的,並允許在對數時間內進行搜尋、循序訪問以及插入、刪除等操作。
* 設定索引時,會將資料放置於記憶體中,會佔用更多記憶體空間。
* 寫入操作會變慢,因為索引會需要更新。
* 當讀取大量資料時,禁用索引再讀取,之後再重新建立索引,這樣也許會更快。
##### 避免高成本的 Join 操作
* 有性能需求時,可以進行 [反正規化](#反正規化)。
##### 分割資料表
* 將熱門的資料拆分到單獨的資料表中可以增加快取。
##### 調整查詢的快取
* 在某些情況下,[查詢快取](http://dev.mysql.com/doc/refman/5.7/en/query-cache) 可能會導致 [性能問題](https://www.percona.com/blog/2014/01/28/10-mysql-performance-tuning-settings-after-installation/)。
##### 來源及延伸閱讀
* [MySQL 查詢優化小提示](http://20bits.com/article/10-tips-for-optimizing-mysql-queries-that-dont-suck)
* [為什麼使用 VARCHAR(255) 很常見](http://stackoverflow.com/questions/1217466/is-there-a-good-reason-i-see-varchar255-used-so-often-as-opposed-to-another-l)
* [Null 值是如何影響資料庫性能](http://stackoverflow.com/questions/1017239/how-do-null-values-affect-performance-in-a-database-search)
* [慢 SQL log 查詢](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)
### NoSQL
NoSQL 指的是 **鍵-值對的資料庫**、**文件類型資料庫**、**列儲存型資料庫** 和 **圖形資料庫** 等的統稱。資料是非正規化的Join 大部分在應用端完成。大多數的 NoSQL 資料庫無法真正實現 ACID 的 transaction他們通常會支援 [最終一致性](#最終一致性)。
**BASE** 通常被用來描述 NoSQL 資料庫的特性。 跟 [CAP 理論](#cap 理論) 相比BASE 強調可用性而非一致性。
* **基本可用** - 系統保證可用性。
* **軟狀態** - 系統的狀態可能隨著時間改變,即使在沒有輸入的情況下也是如此。
* **最終一致性** - 經過一段時間之後,在沒有收到任何輸入的情況下,系統最終會達到一致。
除了在 [SQL 或 NoSQL](#sql-或-nosql) 之間做選擇,了解哪種類型的 NoSQL 資料庫最適合你的需求也是很有幫助的。我們會在下一節中快速瞭解一下 **鍵-值對的資料庫**、**文件類型資料庫**、**列儲存型資料庫** 和 **圖形資料庫** 等資料庫。
#### 鍵-值對的資料庫
> 抽象模型hash table
一個鍵值對的資料庫通常可以實現 O(1) 時間內的讀寫,同時,它的背後通常使用記憶體或 SSD 當作儲存媒介。資料在儲存時,可以按照 [字典順序](https://en.wikipedia.org/wiki/Lexicographical_order) 來維護鍵的數值,進而實踐鍵數值的高效率檢索。鍵值對的資料庫也可以用來儲存值的 metadata。
鍵值對資料庫的效能很好,通常用來儲存簡單的資料模型或是頻繁修改的資料,如放在記憶體中的快取層。鍵值對資料庫所提供的操作有限,如果要進行更多操作,會將其放在應用端進行。
鍵值對的資料庫在某些情況下,是更複雜系統的基礎,例如圖形資料庫或是文件類型的資料庫。
##### 來源及延伸閱讀
* [鍵值對資料庫](https://en.wikipedia.org/wiki/Key-value_database)
* [鍵值對資料庫的缺點](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
* [Redis 架構](http://qnimate.com/overview-of-redis-architecture/)
* [Memcached 架構](https://adayinthelifeof.nl/2011/02/06/memcache-internals/)
#### 文件類型資料庫
> 抽象模型:將文件當做值的鍵值對資料庫
文件類型的資料庫是以文件 (XML、JSON、二進制檔案等) 為核心,文件本身儲存了對應物件的所有資訊。這種類型的資料庫提供了 API 或相關的查詢方法來根據儲存物件本身的特性來實現查詢功能。請注意,許多鍵值對資料庫有儲存 metadata 的特性,這也模糊了這兩種資料庫之間的界線。
根據底層實作的不同文件資料庫可以根據集合、標籤、metadata 或目錄等來組織而成。儘管不同的文件可以被組織在一起或是分成一組,但彼此之間可能具有完全不同的內容。
某些文件型資料庫,例如 [MongoDB](https://www.mongodb.com/mongodb-architecture) 和 [CouchDB](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/) 同樣提供了類似於 SQL 查詢語句的功能來實現複雜的查詢。[DynamoDB](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf)則同時支援了鍵值對儲存和文件類型儲存的功能。
文件類型的資料庫具備高度靈活性,通常用於處理偶爾變化的資料。
##### 延伸閱讀
* [文件類型的資料庫](https://en.wikipedia.org/wiki/Document-oriented_database)
* [MongoDB 架構](https://www.mongodb.com/mongodb-architecture)
* [CouchDB 架構](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/)
* [Elasticsearch 架構](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)
#### 列儲存型資料庫
<p align="center">
<img src="images/n16iOGk.png">
<br/>
<i><a href=http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html>來源SQL 和 NoSQL簡短的歷史介紹</a></i>
</p>
> 抽象模型: 巢狀的 Map `ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>`
列儲存型資料庫的基本單元是一列 (名稱/值為一組)。每一列可以被分到一個列的族群中(類似於 SQL 中的資料表)。而每個列族群之上還可以有一個超級列群。你可以透過列的鍵值來存取每一列,每個值都有一個時間戳記來解決版本問題。
Google 發表了第一個列儲存型資料庫 [Bigtable](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf),這影響了用於 Hadoop 系統中開源的 [HBase](https://www.mapr.com/blog/in-depth-look-hbase-architecture) often-used in the Hadoop ecosystem, 和 Facebook 的 [Cassandra](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html)。這些資料庫的儲存系統把鍵值利用字母順序來儲存,可以有效率的來讀取。
列儲存型態的資料的提供了高可用和高擴展性,通常被用在大量資料的儲存上。
##### 來源及延伸閱讀
* [SQL 和 NoSQL 歷史簡介](http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html)
* [Bigtable 架構](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)
* [HBase 架構](https://www.mapr.com/blog/in-depth-look-hbase-architecture)
* [Cassandra 架構](http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architectureIntro_c.html)
#### 圖形資料庫
<p align="center">
<img src="images/fNcl65g.png">
<br/>
<i><a href=https://en.wikipedia.org/wiki/File:GraphDatabase_PropertyGraph.png>來源: 圖形化資料庫</a></i>
</p>
> 抽象模型:圖
在圖形資料庫中,每一個節點會對應一條紀錄,而每個邊描述兩個節點之間的關係。圖形資料庫針對表示外來鍵(Foreign Key)眾多的複雜關聯或多對多關聯進行優化。
圖形資料庫為了儲存複雜的資料結構,例如社群網路,提供了很高的性能。他們相對較新,尚未被廣泛使用,查詢工具或資源比較難取得,許多這種類型的資料庫只能透過 [REST API](#representational-state-transfer-rest) 來存取。
##### 來源及延伸閱讀
* [圖形資料庫](https://en.wikipedia.org/wiki/Graph_database)
* [Neo4j](https://neo4j.com/)
* [FlockDB](https://blog.twitter.com/2010/introducing-flockdb)
#### 來源及延伸閱讀NoSQL
* [資料庫術語解釋](http://stackoverflow.com/questions/3342497/explanation-of-base-terminology)
* [NoSQL 資料庫:調查與決策指南](https://medium.com/baqend-blog/nosql-databases-a-survey-and-decision-guidance-ea7823a822d#.wskogqenq)
* [可擴展性](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [NoSQL 介紹](https://www.youtube.com/watch?v=qI_g07C_Q5I)
* [NoSQL 模式](http://horicky.blogspot.com/2009/11/nosql-patterns.html)
### SQL 或 NoSQL
<p align="center">
<img src="images/wXGqG5f.png">
<br/>
<i><a href=https://www.infoq.com/articles/Transition-RDBMS-NoSQL/>來源:從 RDBMS 轉換到 NoSQL</a></i>
</p>
選擇 **SQL** 的原因:
* 結構化資料
* 嚴格的 schema
* 關連式資料
* 需要複雜的 join
* 事務
* 清晰的擴展模式
* 既有資源更豐富:開發者、社群、原始碼、工具等
* 透過索引查詢很快
選擇 **NoSQL** 的原因:
* 半結構化資料
* 動態或具有彈性的 schema
* 非關連式資料
* 不需要複雜的 joins
* 儲存 TB (或 PB) 等級的資料
* 高資料密集量的工作負載
* IOPS 的高吞吐量
適合使用 NoSQL 的範例:
* 快速地得到點擊的日誌資料
* 排行榜或得分資料
* 暫時性的資料,像是購物車
* 經常頻繁存取的資料表
* Metadata 或 查找資料表
##### 來源及延伸閱讀: SQL 或 NoSQL
* [擴展你的使用者到第一個一千萬等級](https://www.youtube.com/watch?v=vg5onp8TU6Q)
* [SQL 和 NoSQL 的不同](https://www.sitepoint.com/sql-vs-nosql-differences/)
## 快取
<p align="center">
<img src="images/Q6z24La.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>來源:可擴展的系統設計模式</a></i>
</p>
快取可以提高頁面讀取速度,並且減少伺服器和資料庫的負載。在這種模型中,分派器會先檢查該次請求之前是否曾經被回應過,如果有的話,則直接拿之前的結果返回,避免真正執行處理的程序。
資料庫在資料均勻分布的情況下,讀取和寫入的效能是最好的。但是熱門的資料會讓讀取分佈不均,如此一來就會造成效能瓶頸。在資料庫前增加一個快取,就可以減少負載不均和突發流量所造成的影響。
### 客戶端快取
快取可以在客戶端(作業系統或瀏覽器)、[伺服器端](#反向代理伺服器) 或不同的緩存層等。
### CDN 快取
[內容傳遞網路(CDN)](#內容傳遞網路(CDN)) 也被視為一種快取。
### 網站伺服器快取
[反向代理](#反向代理網站伺服器) 以及像是 [Varnish](https://www.varnish-cache.org/) 等的快取服務可以提供靜態和動態內容。網站伺服器也可以快取使用者請求,返回結果,而不需要真正的處理這些請求。
### 資料庫快取
資料庫的預設設定中通常包含了快取的級別,針對一般的使用進行了優化。你可以針對不同的情況調整這些設定來進一步提高效能。
### 應用程式快取
基於記憶體的快取,像是 Memcached 和 Redis 是一種在應用層和資料庫之間的鍵值對快取。由於資料保存在記憶體中,比起存放在硬碟中的資料庫在存取上要快得多。記憶體的限制也比硬碟更多,所以像是 [least recently used (LRU)](https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used) 的 [cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms) 方法可以讓 '熱門資料' 放在記憶體中,而比較 '冷門' 的資料在記憶體中失效。
Redis 還有以下額外的功能:
* 持久性的設定
* 內建一些資料結構,像是 Set 或 List
你可以快取的級別有好幾種,大致上分為兩類:**資料庫查詢** 和 **物件**
* 記錄級別
* 查詢級別
* 完整的可序列化物件
* 完整的 HTML
一般來說,你應該避免文件檔案的快取,因為這會讓複製和自動擴展變得困難。
### 資料庫查詢級別的快取
當你將查詢資料庫的查詢語句的 hash 值和查詢結果儲存到快取中時,這種方法會遇到以下問題:
* 當你的查詢很複雜時,很難刪除快取內容
* 如果某個資料表中的某個欄位值改變時,需要刪除所有可能包含該欄位值的快取結果。
### 物件級別的快取
將資料視為物件,就像對待你的程式碼一樣。讓應用程式將資料從資料庫中組合到類別實例或資料結構中:
* 如果物件內的基本資料已經改變,那應該要從快取中刪除這個物件
* 允許異步處理workers 透過使用最新的快取來組裝物件
建議快取的資料:
* 使用者 sessions
* 完整渲染的頁面
* 活動資訊
* 使用者資料圖表
### 什麼時候要更新快取
由於你只能在快取中儲存有限的資料,所以你需要選擇一個適用的快取策略。
#### 快取模式
<p align="center">
<img src="images/ONjORqk.png">
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>資料來源:從快取到記憶體資料網格</a></i>
</p>
應用程式負責從儲存裝置中進行讀取及寫入。快取不直接和儲存裝置進行互動,應用程式會執行以下操作:
* 從快取中尋找紀錄,如果所需要的紀錄在快取中找不到時
* 從資料庫中讀取紀錄
* 將該筆記錄儲存到快取
* 將資料返回
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
[Memcached](https://memcached.org/) 通常被用在快取上。
加入快取中的資料讀取速度很快,快取的模式也被稱為延遲讀取。只有被請求過的資料會被加入到快取中,避免沒有被請求的資料佔滿了快取空間。
##### 快取的缺點
* 當請求的資料不在快取中時,就需要經過三個步驟來獲得資料,這會導致明顯的延遲。
* 如果資料庫中的資料被更新了,會導致快取中的資料過時,這需要透過設定 TTL 強制更新快取,或透過直接更新模式來解決這種問題。
* 當快取的某個節點發生故障時,會需要被一個新的節點取代,這會導致延遲。
#### 寫入模式
<p align="center">
<img src="images/0vBc0hN.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>資料來源:可獲展性、可用性、穩定性與模式</a></i>
</p>
應用程式使用快取當作主要的資料儲存服務,將資料寫入/讀取到快取中,由快取服務負責向資料庫讀寫資料。
* 應用程式向快取寫入/讀取資料
* 快取同步的將資料寫到資料庫進行儲存
* 返回所需要的內容
應用程式程式碼:
```
set_user(12345, {"foo":"bar"})
```
快取程式碼:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
直寫模式因為寫入操作的緣故,是一種較慢的操作,但讀取剛剛寫入的資料會很快,使用者通常比較能接受更新較慢,但讀取快速的情況。在快取中的資料不會過時。
##### 寫入模式的缺點
* 當發生故障或因為水平擴展而產生新的節點時,新的節點中將不會有快取資料,直到資料庫更新為止。將快取模式和寫入模式一起使用可以減緩這種現象。
* 被寫入多數的資料可能永遠都不會被讀取,你可以設定 TTL 來解決這種問題。
#### 事後寫入(回寫)
<p align="center">
<img src="images/rgSrvjG.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>資料來源:可獲展性、可用性、穩定性與模式</a></i>
</p>
在事後寫入的模式中,應用程式會執行以下步驟:
* 在快取中新增/更新資料
* 非同步的寫入資料到資料儲存單元,提高寫入的性能
##### 事後寫入的缺點
* 快取可能在資料成功寫入到儲存單元前就丟失
* 事後寫入比起快取模式或是直寫模式在實作上更為複雜
#### 更新式快取
<p align="center">
<img src="images/kxtjqgE.png">
<br/>
<i><a href=http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast>來源:從快取到記憶體資料網格技術</a></i>
</p>
你可以將快取設定為在到期之前就自動更新為最新存取的內容。
如果快取可以準確的預測將來可能會存取哪些資料,那自動更新可以降低讀取的延遲。
##### 更新式快取的缺點
* 無法準確預測未來會使用的資料時,會導致性能降低,還不如使用其他模式。
### 快取的缺點
* 需要保持快取和資料庫之間資料的一致性,比如說要如何設定 [快取無效](https://en.wikipedia.org/wiki/Cache_algorithms)。
* 需要更改應用程式程式碼來支援像是 Redis 或 Memcached 等快取服務。
* 快取的無效性是個難題,而什麼時候要更新快取就是個對應的複雜問題。
### 來源及延伸閱讀
* [從快取到記憶體資料網格技術](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
* [可擴展的系統設計模式](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
* [可擴展的系統架構介紹](http://lethain.com/introduction-to-architecting-systems-for-scale/)
* [可擴展性、可用性、穩定性與模式](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [可擴展性](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [AWS ElastiCache 策略](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
* [維基百科](https://en.wikipedia.org/wiki/Cache_(computing))
## 非同步機制
<p align="center">
<img src="images/54GYsSx.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>資料來源:可縮放性系統架構介紹</a></i>
</p>
非同步的工作流程有助於減少原本按照同步順序進行請求的時間,透過提前進行一些耗時操作來將降低整體請求時間,比如說:定期的彙整資料。
### 訊息佇列
訊息佇列用來接收、保留以及傳遞訊息。如果一個操作按照順序執行太慢的時候,你可以透過訊息佇列和以下的流程搭配來完成此工作:
* 應用程式將訊息發送到佇列中,並通知使用者對應的狀態
* 一個 worker 從佇列中拿出該訊息並進行處理,然後完成後顯示對應資訊
這樣的工作流程,使用者不會被阻塞,同時工作會在背景完成。在這段期間,客戶端可以進行一些處理讓此任務看起來已經完成了。例如,當你要發送一則推文訊息時,此訊息可以馬上出現在你的時間軸上,但可能需要一段時間才會發送到你的追蹤者上面。
**Redis** 是一個簡單且令人滿意的訊息佇列服務,但訊息有可能會丟失。
**RabbitMQ** 很受歡迎,但你必須要使用 AMQP 通訊協定,並且要自己管理節點。
**Amazon SQS** 是一個被 AWS 託管的服務,但可能會有高延遲,並且訊息可能會被傳送兩次。
### 工作佇列
工作佇列會接收工作和對應的資料,執行它們,並且傳送其結果。他們可以支援排程,並且可以在背景運作計算密集型的工作。
**Celery** 支援排程,主要是使用 Python 開發。
### 背壓機制
當佇列開始明顯成長時,佇列的大小可能會超過記憶體,這會導致無法命中快取,降低整體效能。[背壓](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html) 可以用來限制佇列的大小,讓佇列保持高吞吐率和良好的回應時間。一旦佇列滿了,客戶端將會得到 HTTP 503 的回應碼,以便讓他們在稍後重新嘗試。客戶端可以透過 [指數後退演算法](https://en.wikipedia.org/wiki/Exponential_backoff) 這種方式來進行重試。
### 非同步的缺點
* 簡單的運算和需要即時的工作可能更適合使用同步運算,導入佇列可能會增加延遲或系統複雜度。
### 來源及延伸閱讀
* [這是一個數字遊戲](https://www.youtube.com/watch?v=1KRYH75wgy4)
* [當過載時,使用背壓](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
* [利特爾法則](https://en.wikipedia.org/wiki/Little%27s_law)
* [訊息佇列和工作佇列有什麼不同?](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)
## 通訊
<p align="center">
<img src="images/5KeocQs.jpg">
<br/>
<i><a href=http://www.escotal.com/osilayer.html>來源OSI 七層模型</a></i>
</p>
### 超文件通訊協定 (HTTP)
HTTP 是一種在客戶端和伺服器端傳輸資料和定義編碼的方法。它是基於請求/回應的協議客戶端發出請求而伺服器端則針對請求內容完成對應的行為並進行回應。HTTP 是獨立的,它允許請求和回應經過許多負載平衡、快取、加密和壓縮的中間路由器和伺服器。
一個基本的 HTTP 請求是由一個動詞(方法)和一個資源(端點)所組成。以下是常見的 HTTP 動詞:
| 動詞 | 描述 | 冪等* | 安全性 | 可快取性 |
|--------|----------------------------------|-------|--------|-----------------------------------------|
| GET | 讀取資源 | Yes | Yes | Yes |
| POST | 建立資源,或是驅動處理資料的流程 | No | No | Yes如果回應包含更新的資訊 |
| PUT | 建立或更新資源 | Yes | No | No |
| PATCH | 更新部分資料 | No | No | Yes if response contains freshness info |
| DELETE | 刪除資料 | Yes | No | No |
*指的是當進行多次相同請求時,結果是相同的。
HTTP 是依賴於較底層的協議(例如:**TCP** 和 **UDP**) 的應用層協議。
#### 來源及延伸閱讀
* [什麼是 HTTP?](https://www.nginx.com/resources/glossary/http/)
* [HTTP 和 TCP 的差別](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)
* [PUT 和 PATCH 的差別](https://laracasts.com/discuss/channels/general-discussion/whats-the-differences-between-put-and-patch?page=1)
### 傳輸控制通訊協定(TCP)
<p align="center">
<img src="images/JdAsdvG.jpg">
<br/>
<i><a href=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>來源:如何開發多人遊戲</a></i>
</p>
TCP 是透過 [IP 網路](https://en.wikipedia.org/wiki/Internet_Protocol) 面向連線的通訊協定。連線是透過 [握手](https://en.wikipedia.org/wiki/Handshaking) 的方式來建立和斷開連接,所有發送的資料在接收時會保證順序,另外透過以下的機制來保證資料不會損毀:
* 每個資料的序列號碼和 [校驗碼](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation)
* [確認訊息](https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)) 和自動重傳
如果發送端沒有收到正確的回應會重新發送資料如果有多次的逾期時連線就會斷開。TCP 實作了 [流量控制](https://en.wikipedia.org/wiki/Flow_control_(data)) 和 [阻塞控制](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control),這些機制會導致延遲,而且通常傳輸的效率會比 UDP 來得低。
為了確保高吞吐量Web 伺服器會保持大量的 TCP 連線,進而導致記憶體用量變大。在 Web 伺服器之間使用大量的開放連線可能是昂貴的,更別說是在 memcached 快取中做這些事情。[連線池](https://en.wikipedia.org/wiki/Connection_pool) 可以幫助在適合的情況下切換到 UDP。
TCP 對於需要高可靠、低時間急迫性的應用來說很有用比如說Web 伺服器、資料庫、SMTP、FTP 和 SSH。
以下的情況請使用 TCP 而不是 UDP
* 你需要資料完整無缺
* 你想要自動地對網路的流量進行最佳評估
### 使用者資料流通訊協定 (UDP)
<p align="center">
<img src="images/yzDrJtA.jpg">
<br/>
<i><a href=http://www.wildbunny.co.uk/blog/2012/10/09/how-to-make-a-multi-player-game-part-1/>資料來源:如何製作多人遊戲</a></i>
</p>
UDP 是非連線型的通訊協定。資料流(類似於封包)只在資料流級別進行確保。資料可能會不按照順序地到達目的地也可能會遺失。UDP 並不支援阻塞處理,儘管 UDP 不像 TCP 一樣可靠,但通常效率更好。
UDP 可以透過廣播來傳送資料流到所有子網路中的所有裝置,這對於 [DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) 來說很有用,因為所有子網路中的設備還沒有分配到 IP 位置,而對 TCP 來說IP 是必須的。
UDP 的可靠性較低,但適合用在像是網路電話、視訊聊天、串流和多人線上即時遊戲中。
針對以下的案例,請使用 UDP 來代替 TCP
* 你需要低延遲
* 資料延遲的成本比資料遺失還高
* 你想要自己實作錯誤校正方法
#### 來源及延伸閱讀
* [遊戲程式撰寫的網路架構](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)
* [TCP 和 UDP 的關鍵區別](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)
* [TCP 和 UDP 的差別](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
* [傳輸控制協議(TCP)](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)
* [使用者資料流協議(UDP)](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [Memcache 在 Facebook 中的可擴展性設計](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)
### 遠端程式呼叫 (RPC)
<p align="center">
<img src="images/iF4Mkb5.png">
<br/>
<i><a href=http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview>資料來源:破解系統設計面試</a></i>
</p>
在一個 RPC 中,客戶端會去呼叫另外一個位置空間(通常是在遠端的伺服器)的方法。呼叫的方式就像是呼叫本地端的一個方法一樣,客戶端和伺服器溝通的具體過程被抽象化,而遠端呼叫相較於本地端呼叫來說一般較慢,而且可靠性較差,因此了解如何區別這兩種方法是必要的。熱門的 RPC 框架包含了 [Protobuf](https://developers.google.com/protocol-buffers/)、[Thrift](https://thrift.apache.org/) 和 [Avro](https://avro.apache.org/docs/current/)。
RPC 是一個請求-回應的通訊協定:
* **客戶端程序** - 呼叫客戶端的 stub 程序,就像呼叫本地端方法一樣,參數會被放入堆疊當中
* **客戶端 stub 程序** - 將請求過程的 id 和參數打包放入請求資訊中
* **客戶端通訊模組** - 作業系統將資訊從客戶端發送到伺服器端
* **伺服器端通訊模組** - 作業系統將收到的資訊傳送到伺服器端的 stub 程序
* **伺服器端 stub 程序** - 將結果解開後,依照過程中的 ID 來呼叫伺服器
* 伺服器回覆的順序會按照以上相反的順序來回覆
RPC 使用範例:
```
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
```
RPC 專注於揭露行為,它通常用來處理內部通訊的效能問題,通常你可以手動處理本地端的呼叫來更加符合你的使用案例。
當遇到以下情況時,使用本地端函式庫(也就是 SDK
* 你知道你的目標平台
* 你想要控制如何訪問你的 "邏輯"
* 當你的函式庫發生錯誤時,你想要進行控制
* 效能和使用者體驗是你最關注的事情
遵守 **REST** 規範的 HTTP API 往往更適合用在公用的 API。
#### RPC 的缺點
* RPC 的客戶端會變得和伺服器的實作綁得更死
* 一個新的 API 必須在每個操作或使用案例中進行定義
* RPC 很難抓錯誤
* 你很難方便的修改現有的技術,舉例來說,如果你希望在 [Squid](http://www.squid-cache.org/) 這樣的快取伺服器上確保 [RPC 呼叫被正確的快取](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/),你可以需要多費額外的努力了。
### 具象狀態轉移 (REST)
REST 是一個規範客戶端/伺服器端架構設計的模型。客戶端基於伺服器管理的系列操作,伺服器提供修改或取得資源的介面,所有的通訊必須是無狀態、可快取的。
Restful 的設計有四個原則:
* **標示資源 (HTTP 中的 URI)** - 無論任何操作都使用相同的 URI
* **表示層的改變 (HTTP 中的動作)** - 使用 HTTP 動詞、Headers 和 body
* **可自我描述的錯誤訊息 (HTTP 中的狀態碼)** - 使用狀態碼,不要重複造輪子
* **[HATEOAS](http://restcookbook.com/Basics/hateoas/) (HTTP 中的 HTML 介面)** - 你的 Web 伺服器應該要能夠透過瀏覽器訪問
REST 請求範例:
```
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
```
REST 關注於揭露資料,減少客戶端/伺服器之間耦合的程度,並且經常用在公共的 HTTP API 設計上。REST 使用更通用和受規範的方法來透過 URI 來揭露資源,[透過 Headers 來描述](https://github.com/for-GET/know-your-http-well/blob/master/headers.md),並透過 GET、POST、PUT、DELETE 和 PATCH 等動作來進行操作因為無狀態的特性REST 易於橫向擴展和分片。
#### REST 的缺點
* 因為 REST 的重點是放在如何揭露資料所以當資料不是以自然的形式組成時或是結構相當複雜時REST 可能無法很好的處理他們。舉個範例,回傳過去一小時中與特定事件吻合的更新操作就很難透過路徑來表示,使用 REST可能會使用 URI、查詢參數和請求本身來實現。
* REST 一般依賴於幾個動詞操作(GET、POST、PUT、DELETE 和 PATCH),但有時候這些操作無法滿足你的需求,舉個範例,將過期的文件移動到歸檔文件資料庫中這樣的操作,可能就沒辦法簡單的使用以上幾個動詞操作來完成。
* 對於那些多層複雜的資源來說,需要在客戶端和伺服器端進行多次請求,例如:獲得部落格頁面及相關評論,而對於網路環境較不穩定的行動端應用來說,這些多次往返的請求是非常麻煩的。
* 隨著時間的增加API 的回應中可能會增加更多的欄位,比較舊的客戶端還是會收到所有新的回應內容,即時他們不需要這些回應,這會造成他們的負擔,並且造成更大的延遲。
### RPC 和 REST 呼叫的比較
| 操作 | RPC | REST |
|----------------------------|-----------------------------------------------------------------------|-----------------------------------------------|
| 註冊 | **POST** /signup | **POST** /persons |
| 取消 | **POST** /resign{"personid": "1234"} | **DELETE** /persons/1234 |
| 讀取使用者資訊 | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| 讀取使用者物品清單 | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| 增加一個物品到使用者的清單 | **POST** /addItemToUsersItemsList{"personid": "1234";"itemid": "456"} | **POST** /persons/1234/items{"itemid": "456"} |
| 更新一個物品 | **POST** /modifyItem{"itemid": "456";"key": "value"} | **PUT** /items/456{"key": "value"} |
| 刪除一個物品 | **POST** /removeItem{"itemid": "456"} | **DELETE** /items/456 |
<p align="center">
<i><a href=https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/>資料來源:你真的知道為什麼你更喜歡 REST 而不是 RPC 嗎?</a></i>
</p>
#### 來源及延伸閱讀
* [你真的知道為什麼你更喜歡 REST 而不是 RPC 嗎?](https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/)
* [什麼時候 RPC 比 REST 更適合](http://programmers.stackexchange.com/a/181186)
* [REST 和 JSON-RPC](http://stackoverflow.com/questions/15056878/rest-vs-json-rpc)
* [揭開 RPC 和 REST 的神秘面紗](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)
* [使用 REST 的缺點](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)
* [破解系統設計面試](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Thrift](https://code.facebook.com/posts/1468950976659943/)
* [為什麼在內部要使用 REST 而不是 RPC](http://arstechnica.com/civis/viewtopic.php?t=1190508)
## 資訊安全
這一章節需要更多的貢獻,一起[加入](#如何貢獻)吧!
資訊安全是一個廣泛的議題,除非你有相當的經驗、資訊安全的背景或正在申請相關的職位要求對應的知識,否則了解以下的基礎內容即可:
*在傳輸和等待的過程中進行加密
* 對所有使用者輸入和從使用者得到的參數進行處理,以避免 [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) 和 [SQL injection](https://en.wikipedia.org/wiki/SQL_injection)
* 使用參數化輸入來避免 SQL injection
* 使用 [最小權限原則](https://en.wikipedia.org/wiki/Principle_of_least_privilege)
### 來源及延伸閱讀
* [為開發者準備的資訊安全指南](https://github.com/FallibleInc/security-guide-for-developers)
* [OWASP top ten](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
## 附錄
某些時候你可能會被要求做一些保守估計,比如說,你可能需要預估從硬碟中生成 100 張圖片約略需要多少時間,或一個資料結構需要多少記憶體等。**2 的次方表** 和 **每個開發者都需要知道的一些時間資料** 都是一些很方便的參考料。
### 2 的次方表
```
次方 實際值 近似值 位元組
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
```
#### 來源及延伸閱讀
* [2 的次方](https://en.wikipedia.org/wiki/Power_of_two)
### 每個開發者都應該知道的延遲數量級
```
延遲比較數量級
--------------------------
L1 快取參考數量級 0.5 ns
Branch mispredict 5 ns
L2 快取參考數量級 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
主記憶體參考數量級 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from disk 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
```
一些基於上述數字的指標:
* 循序的從硬碟讀取資料大約 30 MB/s
* 循序的從 1 Gbps 坪寬的乙太網路讀取約 100 MB/s
* 循序的從 SSD 讀取大約 1 GB/s
* 循序的從主記憶體中讀取大約 4 GB/s
* 每秒大約可以繞地球 6-7 圈
* 資料中心內每秒約有 2000 次的往返
#### 視覺化延遲數
![](https://web.archive.org/web/20200702021143im_/https://camo.githubusercontent.com/77f72259e1eb58596b564d1ad823af1853bc60a3/687474703a2f2f692e696d6775722e636f6d2f6b307431652e706e67)
#### 來源及延伸閱讀
* [每個程式設計師都應該知道的延遲數量級 - 1](https://gist.github.com/jboner/2841832)
* [每個程式設計師都應該知道的延遲數量級 - 2](https://gist.github.com/hellerbarde/2843375)
* [關於建置大型分散式系統所需要知道的設計方案、課程和建議](http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf)
* [從軟體工程師的角度來看建置大型分散式系統](https://static.googleusercontent.com/media/research.google.com/en//people/jeff/stanford-295-talk.pdf)
### 其他的系統設計面試問題
> 常見的系統設計問題,同時提供如何解決該問題的連結
| 問題 | 來源 |
|----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 設計一個類似於 Dropbox 的文件同步系統 | [youtube.com](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| 設計一個類似於 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) |
| 設計一個像 Google 一樣可擴展的網路爬蟲 | [quora.com](https://www.quora.com/How-can-I-build-a-web-crawler-from-scratch) |
| 設計一個 Google Docs | [code.google.com](https://code.google.com/p/google-mobwrite/)<br/>[neil.fraser.name](https://neil.fraser.name/writing/sync/) |
| 設計一個像 Redis 一樣的鍵值對系統 | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| 設計一個像 Memcached 的快取系統 | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| 設計一個像 Amazon 一樣的推薦系統 | [hulu.com](http://tech.hulu.com/blog/2011/09/19/recommendation-system.html)[ijcai13.org](http://ijcai13.org/files/tutorial_slides/td3.pdf) |
| 設計一個像 Bitly 一樣的短網址服務 | [n00tc0d3r.blogspot.com](http://n00tc0d3r.blogspot.com/) |
| 設計一個像 WhatsApp 一樣的即時訊息系統 | [highscalability.com](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| 設計一個像 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) |
| 設計一個像 Facebook 的新聞推薦方法 | [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) |
| 設計一個 Facebook 時間軸功能 | [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) |
| 設計 Facebook 的聊天功能 | [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) |
| 設計一個像 Facebook 的圖形化搜尋系統 | [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) |
| 設計一個像 CloudFlare 的內容傳輸網路 | [cmu.edu](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci) |
| 設計一個像 Twitter 的微網誌服務 | [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/) |
| 設計一個隨機 ID 生成系統 | [blog.twitter.com](https://blog.twitter.com/2010/announcing-snowflake)<br/>[github.com](https://github.com/twitter/snowflake/) |
| 給定一段時間,回傳次數排名前 K 的請求 | [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) |
| 設計一個資料來源在多個資料中心的系統 | [highscalability.com](http://highscalability.com/blog/2009/8/24/how-google-serves-data-from-multiple-datacenters.html) |
| 設計一個線上多人卡牌遊戲 | [indieflashblog.com](https://web.archive.org/web/20180929181117/http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)<br/>[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| 設計一個垃圾回收系統 | [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) |
| 貢獻更多系統設計問題 | [Contribute](#如何貢獻) |
### 真實世界的架構
> 底下是關於真實世界的系統架構是如何設計的文章
<p align="center">
<img src="images/TcUo2fw.png">
<br/>
<i><a href=https://www.infoq.com/presentations/Twitter-Timeline-Scalability>資料來源:可擴展式的 Twitter 時間軸設計</a></i>
</p>
**不要關注以下文章的細節,而是注意以下幾點:**
* 找到這些文章中共通的原則、技術和模式
* 學習每個元件負責解決哪些問題、在什麼情況下使用、什麼情況下不適用
* 複習學習過的文章
| 種類 | 系統 | 參考來源 |
|----------|----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|
| 資料處理 | **MapReduce** - Google 的分散式資料處理 | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/mapreduce-osdi04.pdf) |
| 資料處理 | **Spark** - Databricks 的分散式資料處理 | [slideshare.net](http://www.slideshare.net/AGrishchenko/apache-spark-architecture) |
| 資料處理 | **Storm** - Twitter 的分散式資料處理 | [slideshare.net](http://www.slideshare.net/previa/storm-16094009) |
| | | |
| 資料儲存 | **Bigtable** - Google 的列式資料庫 | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) |
| 資料儲存 | **HBase** - Bigtable 的開放原始碼解決方案 | [slideshare.net](http://www.slideshare.net/alexbaranau/intro-to-hbase) |
| 資料儲存 | **Cassandra** - Facebook 的列式資料庫 | [slideshare.net](http://www.slideshare.net/planetcassandra/cassandra-introduction-features-30103666) |
| 資料儲存 | **DynamoDB** - Amazon 的文件式資料庫 | [harvard.edu](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) |
| 資料儲存 | **MongoDB** - 文件式資料庫 | [slideshare.net](http://www.slideshare.net/mdirolf/introduction-to-mongodb) |
| 資料儲存 | **Spanner** - Google 的全球分散式資料庫 | [research.google.com](http://research.google.com/archive/spanner-osdi2012.pdf) |
| 資料儲存 | **Memcached** - 分散式的記憶體快取系統 | [slideshare.net](http://www.slideshare.net/oemebamo/introduction-to-memcached) |
| 資料儲存 | **Redis** - 具有持久化及值型別的分散式快取系統 | [slideshare.net](http://www.slideshare.net/dvirsky/introduction-to-redis) |
| | | |
| 檔案系統 | **Google File System (GFS)** - 分散式的檔案系統 | [research.google.com](http://static.googleusercontent.com/media/research.google.com/zh-CN/us/archive/gfs-sosp2003.pdf) |
| 檔案系統 | **Hadoop File System (HDFS)** - GFS 的開放原始碼解決方案 | [apache.org](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html) |
| | | |
| 其他 | **Chubby** - Google 的分散式系統低耦合鎖服務 | [research.google.com](http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/archive/chubby-osdi06.pdf) |
| 其他 | **Dapper** - 分散式系統監控基礎設施 | [research.google.com](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf) |
| 其他 | **Kafka** - LinkedIn 的 pub/sub 訊息佇列服務 | [slideshare.net](http://www.slideshare.net/mumrah/kafka-talk-tri-hug) |
| 其他 | **Zookeeper** - 集中式的基礎架構和協調服務 | [slideshare.net](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) |
| | 貢獻更多架構 | [Contribute](#如何貢獻) |
### 公司的系統架構
| 公司 | 參考 |
|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Amazon | [Amazon 的架構](http://highscalability.com/amazon-architecture) |
| Cinchcast | [每天產生 1,500 小時的音樂](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html) |
| DataSift | [每秒探勘 120,000 則 tweet](http://highscalability.com/blog/2011/11/29/datasift-architecture-realtime-datamining-at-120000-tweets-p.html) |
| DropBox | [我們如何擴展 Dropbox](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| ESPN | [每秒操作 100,000 次 duh nuh nuhs](http://highscalability.com/blog/2013/11/4/espns-architecture-at-scale-operating-at-100000-duh-nuh-nuhs.html) |
| Google | [Google 的架構](http://highscalability.com/google-architecture) |
| Instagram | [一千四百萬個使用者TB 等級的照片儲存](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html)<br/>[什麼驅動著 Instagram](http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances) |
| Justin.tv | [Justin.Tv 的即時影片廣播架構](http://highscalability.com/blog/2010/3/16/justintvs-live-video-broadcasting-architecture.html) |
| Facebook | [Facebook 可擴展的 memcached 架構](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/key-value/fb-memcached-nsdi-2013.pdf)<br/>[TAO: Facebook 為了社交網路架構的分散式資料儲存](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/data-store/tao-facebook-distributed-datastore-atc-2013.pdf)<br/>[Facebook 的圖片儲存架構](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf) |
| Flickr | [Flickr 的架構](http://highscalability.com/flickr-architecture) |
| Mailbox | [在六週內從 0 到 100 萬個使用者](http://highscalability.com/blog/2013/6/18/scaling-mailbox-from-0-to-one-million-users-in-6-weeks-and-1.html) |
| Pinterest | [從零到每個月數十億次的瀏覽量](http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html)<br/>[1800 萬個訪問人次、10 倍成長、12 名員工](http://highscalability.com/blog/2012/5/21/pinterest-architecture-update-18-million-visitors-10x-growth.html) |
| Playfish | [月使用者量 5000 萬人次在成長](http://highscalability.com/blog/2010/9/21/playfishs-social-gaming-architecture-50-million-monthly-user.html) |
| PlentyOfFish | [PlentyOfFish 的架構](http://highscalability.com/plentyoffish-architecture) |
| Salesforce | [如何處理每天 13 億筆交易](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html) |
| Stack Overflow | [Stack Overflow 的架構](http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html) |
| TripAdvisor | [4000 萬的訪問人次、2 億次頁面瀏覽量、30 TB 的資料](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.html) |
| Tumblr | [每月 150 億的瀏覽量](http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html) |
| Twitter | [如何讓 Twitter 的速度成長 10000 倍](http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster)<br/>[使用 MySQL 儲存每天 2.5 億條 tweet](http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html)<br/>[1.5 億的活躍使用者、300K QPS、22 MB/S 的串流資料](http://highscalability.com/blog/2013/7/8/the-architecture-twitter-uses-to-deal-with-150m-active-users.html)<br/>[可擴展的 Timelines](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)<br/>[Twitter 的大大小小的資料](https://www.youtube.com/watch?v=5cKTP36HVgI)<br/>[Twitter 的運營:擴展超過一億個使用者](https://www.youtube.com/watch?v=z8LU0Cj6BOU) |
| Uber | [Uber 是如何擴展他們的及時行銷平台](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html) |
| WhatsApp | [讓 Facebook 用 $190 億購買下來的 WhatsApp 的架構](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| YouTube | [YouTube 的可擴展性](https://www.youtube.com/watch?v=w5WVu624fY8)[YouTube 的架構](http://highscalability.com/youtube-architecture) |
### 公司的工程部落格
> 你即將面試的公司的架構
>
> 你被問到的問題可能就來自於相同領域的問題
* [Airbnb Engineering](http://nerds.airbnb.com/)
* [Atlassian Developers](https://developer.atlassian.com/blog/)
* [Autodesk Engineering](http://cloudengineering.autodesk.com/blog/)
* [AWS Blog](https://aws.amazon.com/blogs/aws/)
* [Bitly Engineering Blog](http://word.bitly.com/)
* [Box Blogs](https://www.box.com/blog/engineering/)
* [Cloudera Developer Blog](http://blog.cloudera.com/blog/)
* [Dropbox Tech Blog](https://tech.dropbox.com/)
* [Engineering at Quora](http://engineering.quora.com/)
* [Ebay Tech Blog](http://www.ebaytechblog.com/)
* [Evernote Tech Blog](https://blog.evernote.com/tech/)
* [Etsy Code as Craft](http://codeascraft.com/)
* [Facebook Engineering](https://www.facebook.com/Engineering)
* [Flickr Code](http://code.flickr.net/)
* [Foursquare Engineering Blog](http://engineering.foursquare.com/)
* [GitHub Engineering Blog](https://github.blog/category/engineering)
* [Google Research Blog](http://googleresearch.blogspot.com/)
* [Groupon Engineering Blog](https://engineering.groupon.com/)
* [Heroku Engineering Blog](https://engineering.heroku.com/)
* [Hubspot Engineering Blog](http://product.hubspot.com/blog/topic/engineering)
* [High Scalability](http://highscalability.com/)
* [Instagram Engineering](http://instagram-engineering.tumblr.com/)
* [Intel Software Blog](https://software.intel.com/en-us/blogs/)
* [Jane Street Tech Blog](https://blogs.janestreet.com/category/ocaml/)
* [LinkedIn Engineering](http://engineering.linkedin.com/blog)
* [Microsoft Engineering](https://engineering.microsoft.com/)
* [Microsoft Python Engineering](https://blogs.msdn.microsoft.com/pythonengineering/)
* [Netflix Tech Blog](http://techblog.netflix.com/)
* [Paypal Developer Blog](https://devblog.paypal.com/category/engineering/)
* [Pinterest Engineering Blog](http://engineering.pinterest.com/)
* [Quora Engineering](https://engineering.quora.com/)
* [Reddit Blog](http://www.redditblog.com/)
* [Salesforce Engineering Blog](https://developer.salesforce.com/blogs/engineering/)
* [Slack Engineering Blog](https://slack.engineering/)
* [Spotify Labs](https://labs.spotify.com/)
* [Stripe Engineering Blog](https://stripe.com/blog/engineering)
* [Twilio Engineering Blog](http://www.twilio.com/engineering)
* [Twitter Engineering](https://engineering.twitter.com/)
* [Uber Engineering Blog](http://eng.uber.com/)
* [Yahoo Engineering Blog](http://yahooeng.tumblr.com/)
* [Yelp Engineering Blog](http://engineeringblog.yelp.com/)
* [Zynga Engineering Blog](https://www.zynga.com/blogs/engineering)
#### 來源及延伸閱讀
* [kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)
## 仍在進行中
有興趣增加一些內容,或幫忙完善某些部分嗎? [來貢獻吧](#如何貢獻)!
* 使用 MapReduce 進行分散式運算
* 一致性的 hashing
* 直接記憶體存取
* [貢獻](#如何貢獻)
## 致謝
在這個 Repository 中提供的任何來源和開放原始碼庫
特別感謝:
* [Hired in tech](http://www.hiredintech.com/system-design/the-system-design-process/)
* [Cracking the coding interview](https://www.amazon.com/dp/0984782850/)
* [High scalability](http://highscalability.com/)
* [checkcheckzz/system-design-interview](https://github.com/checkcheckzz/system-design-interview)
* [shashank88/system_design](https://github.com/shashank88/system_design)
* [mmcgrana/services-engineering](https://github.com/mmcgrana/services-engineering)
* [System design cheat sheet](https://gist.github.com/vasanthk/485d1c25737e8e72759f)
* [A distributed systems reading list](http://dancres.github.io/Pages/)
* [Cracking the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
## 聯絡資訊
隨時歡迎與我討論相關的問題或意見。
我的聯絡資訊可以在我的 [GitHub 主頁](https://github.com/donnemartin) 中找到。
## 授權
*我以開放原始碼授權的方式,提供你在此儲存庫中的程式碼和資源。因為這是我個人的儲存庫,所以你所收到的使用許可是來自於我,並非我的雇主(Facebook)*
Copyright 2017 Donne Martin
Creative Commons Attribution 4.0 International License (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/

1936
docs/README.md Normal file
View File

@@ -0,0 +1,1936 @@
*[English](README.md) ∙ [日本語](README-ja.md) ∙ [简体中文](README-zh-Hans.md) ∙ [繁體中文](README-zh-TW.md) | [العَرَبِيَّة‎](https://github.com/donnemartin/system-design-primer/issues/170) ∙ [বাংলা](https://github.com/donnemartin/system-design-primer/issues/220) ∙ [Português do Brasil](https://github.com/donnemartin/system-design-primer/issues/40) ∙ [Deutsch](https://github.com/donnemartin/system-design-primer/issues/186) ∙ [ελληνικά](https://github.com/donnemartin/system-design-primer/issues/130) ∙ [עברית](https://github.com/donnemartin/system-design-primer/issues/272) ∙ [Italiano](https://github.com/donnemartin/system-design-primer/issues/104) ∙ [한국어](https://github.com/donnemartin/system-design-primer/issues/102) ∙ [فارسی](https://github.com/donnemartin/system-design-primer/issues/110) ∙ [Polski](https://github.com/donnemartin/system-design-primer/issues/68) ∙ [русский язык](https://github.com/donnemartin/system-design-primer/issues/87) ∙ [Español](https://github.com/donnemartin/system-design-primer/issues/136) ∙ [ภาษาไทย](https://github.com/donnemartin/system-design-primer/issues/187) ∙ [Türkçe](https://github.com/donnemartin/system-design-primer/issues/39) ∙ [tiếng Việt](https://github.com/donnemartin/system-design-primer/issues/127) ∙ [Français](https://github.com/donnemartin/system-design-primer/issues/250) | [Add Translation](https://github.com/donnemartin/system-design-primer/issues/28)*
**Help [translate](TRANSLATIONS.md) this guide!**
# The System Design Primer
<p align="center">
<img src="images/jj3A5N8.png">
<br/>
</p>
## Motivation
> Learn how to design large-scale systems.
>
> Prep for the system design interview.
### Learn how to design large-scale systems
Learning how to design scalable systems will help you become a better engineer.
System design is a broad topic. There is a **vast amount of resources scattered throughout the web** on system design principles.
This repo is an **organized collection** of resources to help you learn how to build systems at scale.
### Learn from the open source community
This is a continually updated, open source project.
[Contributions](#contributing) are welcome!
### Prep for the system design interview
In addition to coding interviews, system design is a **required component** of the **technical interview process** at many tech companies.
**Practice common system design interview questions** and **compare** your results with **sample solutions**: discussions, code, and diagrams.
Additional topics for interview prep:
* [Study guide](#study-guide)
* [How to approach a system design interview question](#how-to-approach-a-system-design-interview-question)
* [System design interview questions, **with solutions**](#system-design-interview-questions-with-solutions)
* [Object-oriented design interview questions, **with solutions**](#object-oriented-design-interview-questions-with-solutions)
* [Low-level system design interview questions **with solutions**](https://github.com/prasadgujar/low-level-design-primer)
* [Additional system design interview questions](#additional-system-design-interview-questions)
* [System design interview questions](https://www.interviewbit.com/system-design-interview-questions/)
## Anki flashcards
<p align="center">
<img src="images/zdCAkB3.png">
<br/>
</p>
<p align="center">
<img src="images/screenshot.png">
<br/>
</p>
<p align="center">
<img src="images/screenshot_gif.gif">
<br/>
</p>
The provided [Anki flashcard decks](https://apps.ankiweb.net/) use spaced repetition to help you retain key system design concepts.
* [System design deck](https://github.com/donnemartin/system-design-primer/tree/master/resources/flash_cards/System%20Design.apkg)
* [System design exercises deck](https://github.com/donnemartin/system-design-primer/tree/master/resources/flash_cards/System%20Design%20Exercises.apkg)
* [Object oriented design exercises deck](https://github.com/donnemartin/system-design-primer/tree/master/resources/flash_cards/OO%20Design.apkg)
For an alternative collection of Anki decks tailored specifically to developers, check out [Ankicode by daveight](https://github.com/daveight/ankicode)—a powerful resource that offers curated flashcards covering programming, algorithms, and other technical topics.
Great for use while on-the-go.
### Coding Resource: Interactive Coding Challenges
Looking for resources to help you prep for the [**Coding Interview**](https://github.com/donnemartin/interactive-coding-challenges)?
<p align="center">
<img src="images/b4YtAEN.png">
<br/>
</p>
Check out the sister repo [**Interactive Coding Challenges**](https://github.com/donnemartin/interactive-coding-challenges), which contains an additional Anki deck:
* [Coding deck](https://github.com/donnemartin/interactive-coding-challenges/tree/master/anki_cards/Coding.apkg)
### Video Resources
* Watch [**20 System Design Concepts**](https://www.youtube.com/watch?v=i53Gi_K3o7I) to become familiar with the various topics within system design.
* Watch the [**System Design Course for Beginners**](https://www.youtube.com/watch?v=MbjObHmDbZo) for a free high level crash course on the system design concepts.
* To learn about specific System Design Concepts in greater detail, check out the [**System Design playlist**](https://www.youtube.com/playlist?list=PLCRMIe5FDPsd0gVs500xeOewfySTsmEjf)
## Contributing
> Learn from the community.
Feel free to submit pull requests to help:
* Fix errors
* Improve sections
* Add new sections
* [Translate](https://github.com/donnemartin/system-design-primer/issues/28)
Content that needs some polishing is placed [under development](#under-development).
Review the [Contributing Guidelines](CONTRIBUTING.md).
## Index of system design topics
> Summaries of various system design topics, including pros and cons. **Everything is a trade-off**.
>
> Each section contains links to more in-depth resources.
<p align="center">
<img src="images/jrUBAF7.png">
<br/>
</p>
* [System design topics: start here](#system-design-topics-start-here)
* [Step 1: Review the scalability video lecture](#step-1-review-the-scalability-video-lecture)
* [Step 2: Review the scalability article](#step-2-review-the-scalability-article)
* [Next steps](#next-steps)
* [Performance vs scalability](#performance-vs-scalability)
* [Latency vs throughput](#latency-vs-throughput)
* [Availability vs consistency](#availability-vs-consistency)
* [CAP theorem](#cap-theorem)
* [CP - consistency and partition tolerance](#cp---consistency-and-partition-tolerance)
* [AP - availability and partition tolerance](#ap---availability-and-partition-tolerance)
* [Consistency patterns](#consistency-patterns)
* [Weak consistency](#weak-consistency)
* [Eventual consistency](#eventual-consistency)
* [Strong consistency](#strong-consistency)
* [Availability patterns](#availability-patterns)
* [Fail-over](#fail-over)
* [Active-passive](#active-passive)
* [Active-active](#active-active)
* [Replication](#replication)
* [Availability in numbers](#availability-in-numbers)
* [Domain name system](#domain-name-system)
* [Content delivery network](#content-delivery-network)
* [Push CDNs](#push-cdns)
* [Pull CDNs](#pull-cdns)
* [Load balancer](#load-balancer)
* [Layer 4 load balancing](#layer-4-load-balancing)
* [Layer 7 load balancing](#layer-7-load-balancing)
* [Consistent Hashing](#consistent-hashing)
* [Horizontal scaling](#horizontal-scaling)
* [Reverse proxy (web server)](#reverse-proxy-web-server)
* [Load balancer vs reverse proxy](#load-balancer-vs-reverse-proxy)
* [Application layer](#application-layer)
* [Microservices](#microservices)
* [Service discovery](#service-discovery)
* [Database](#database)
* [Relational database management system (RDBMS)](#relational-database-management-system-rdbms)
* [Master-slave replication](#master-slave-replication)
* [Master-master replication](#master-master-replication)
* [Federation](#federation)
* [Sharding](#sharding)
* [Denormalization](#denormalization)
* [SQL tuning](#sql-tuning)
* [NoSQL](#nosql)
* [Key-value store](#key-value-store)
* [Document store](#document-store)
* [Wide column store](#wide-column-store)
* [Graph Database](#graph-database)
* [SQL or NoSQL](#sql-or-nosql)
* [Cache](#cache)
* [Client caching](#client-caching)
* [CDN caching](#cdn-caching)
* [Web server caching](#web-server-caching)
* [Database caching](#database-caching)
* [Application caching](#application-caching)
* [Caching at the database query level](#caching-at-the-database-query-level)
* [Caching at the object level](#caching-at-the-object-level)
* [When to update the cache](#when-to-update-the-cache)
* [Cache-aside](#cache-aside)
* [Write-through](#write-through)
* [Write-behind (write-back)](#write-behind-write-back)
* [Refresh-ahead](#refresh-ahead)
* [Asynchronism](#asynchronism)
* [Message queues](#message-queues)
* [Task queues](#task-queues)
* [Back pressure](#back-pressure)
* [Communication](#communication)
* [Hypertext transfer protocol (HTTP)](#hypertext-transfer-protocol-http)
* [Transmission control protocol (TCP)](#transmission-control-protocol-tcp)
* [User datagram protocol (UDP)](#user-datagram-protocol-udp)
* [Remote procedure call (RPC)](#remote-procedure-call-rpc)
* [Representational state transfer (REST)](#representational-state-transfer-rest)
* [Security](#security)
* [Appendix](#appendix)
* [Powers of two table](#powers-of-two-table)
* [Latency numbers every programmer should know](#latency-numbers-every-programmer-should-know)
* [Additional system design interview questions](#additional-system-design-interview-questions)
* [Real world architectures](#real-world-architectures)
* [Company architectures](#company-architectures)
* [Company engineering blogs](#company-engineering-blogs)
* [Under development](#under-development)
* [Credits](#credits)
* [Contact info](#contact-info)
* [License](#license)
## Study guide
> Suggested topics to review based on your interview timeline (short, medium, long).
![Imgur](images/OfVllex.png)
**Q: For interviews, do I need to know everything here?**
**A: No, you don't need to know everything here to prepare for the interview**.
What you are asked in an interview depends on variables such as:
* How much experience you have
* What your technical background is
* What positions you are interviewing for
* Which companies you are interviewing with
* Luck
More experienced candidates are generally expected to know more about system design. Architects or team leads might be expected to know more than individual contributors. Top tech companies are likely to have one or more design interview rounds.
Start broad and go deeper in a few areas. It helps to know a little about various key system design topics. Adjust the following guide based on your timeline, experience, what positions you are interviewing for, and which companies you are interviewing with.
* **Short timeline** - Aim for **breadth** with system design topics. Practice by solving **some** interview questions.
* **Medium timeline** - Aim for **breadth** and **some depth** with system design topics. Practice by solving **many** interview questions.
* **Long timeline** - Aim for **breadth** and **more depth** with system design topics. Practice by solving **most** interview questions.
| | Short | Medium | Long |
|---|---|---|---|
| Read through the [System design topics](#index-of-system-design-topics) to get a broad understanding of how systems work | :+1: | :+1: | :+1: |
| Read through a few articles in the [Company engineering blogs](#company-engineering-blogs) for the companies you are interviewing with | :+1: | :+1: | :+1: |
| Read through a few [Real world architectures](#real-world-architectures) | :+1: | :+1: | :+1: |
| Review [How to approach a system design interview question](#how-to-approach-a-system-design-interview-question) | :+1: | :+1: | :+1: |
| Work through [System design interview questions with solutions](#system-design-interview-questions-with-solutions) | Some | Many | Most |
| Work through [Object-oriented design interview questions with solutions](#object-oriented-design-interview-questions-with-solutions) | Some | Many | Most |
| Work through [Low-level system design interview questions with solutions](https://github.com/prasadgujar/low-level-design-primer) | Some | Many | Most |
| Review [Additional system design interview questions](#additional-system-design-interview-questions) | Some | Many | Most |
## How to approach a system design interview question
> How to tackle a system design interview question.
The system design interview is an **open-ended conversation**. You are expected to lead it.
You can use the following steps to guide the discussion. To help solidify this process, work through the [System design interview questions with solutions](#system-design-interview-questions-with-solutions) section using the following steps.
### Step 1: Outline use cases, constraints, and assumptions
Gather requirements and scope the problem. Ask questions to clarify use cases and constraints. Discuss assumptions:
* Who is going to use it?
* How are they going to use it?
* How many users are there?
* What does the system do?
* What are the inputs and outputs of the system?
* How much data do we expect to handle?
* How many requests per second do we expect?
* What is the expected read to write ratio?
* What is the peak traffic?
### Step 2: Create a high level design
Outline a high level design with all important components:
* Sketch the main components and connections
* Justify your ideas
### Step 3: Design core components
Dive into details for each core component. For example, if you were asked to [design a url shortening service](solutions/system_design/pastebin/README.md), discuss:
* Generating and storing a hash of the full url
* [MD5](solutions/system_design/pastebin/README.md) and [Base62](solutions/system_design/pastebin/README.md)
* Hash collisions
* SQL or NoSQL
* Database schema
* Translating a hashed url to the full url
* Database lookup
* API and object-oriented design
### Step 4: Scale the design
Identify and address bottlenecks, given the constraints. For example, do you need the following to address scalability issues?
* Load balancer
* Horizontal scaling
* Caching
* Database sharding
Discuss potential solutions and trade-offs. Everything is a trade-off. Address bottlenecks using [principles of scalable system design](#index-of-system-design-topics).
### Back-of-the-envelope calculations
You might be asked to do some estimates by hand. Refer to the [Appendix](#appendix) for the following resources:
* [Use back of the envelope calculations](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
* [Powers of two table](#powers-of-two-table)
* [Latency numbers every programmer should know](#latency-numbers-every-programmer-should-know)
* [Cheatsheet System Design Numbers and Approximations](https://github.com/bschauerte/System-Design-Numbers-and-Approximations)
### Source(s) and further reading
Check out the following links to get a better idea of what to expect:
* [8 Steps to acing your next system design interview](https://www.hackerearth.com/blog/developers/8-steps-to-acing-your-next-system-design-interview/)
* [How to ace a systems design interview (old)](https://web.archive.org/web/20210505130322/https://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)
* [The system design interview](http://www.hiredintech.com/system-design)
* [Intro to Architecture and Systems Design Interviews](https://www.youtube.com/watch?v=ZgdS0EUmn70)
* [System design template](https://leetcode.com/discuss/career/229177/My-System-Design-Template)
## System design interview questions with solutions
> Common system design interview questions with sample discussions, code, and diagrams.
>
> Solutions linked to content in the `solutions/` folder.
| Question | |
|---|---|
| Design Pastebin.com (or Bit.ly) | [Solution](solutions/system_design/pastebin/README.md) |
| Design the Twitter timeline and search (or Facebook feed and search) | [Solution](solutions/system_design/twitter/README.md) |
| Design a web crawler | [Solution](solutions/system_design/web_crawler/README.md) |
| Design Mint.com | [Solution](solutions/system_design/mint/README.md) |
| Design the data structures for a social network | [Solution](solutions/system_design/social_graph/README.md) |
| Design a key-value store for a search engine | [Solution](solutions/system_design/query_cache/README.md) |
| Design Amazon's sales ranking by category feature | [Solution](solutions/system_design/sales_rank/README.md) |
| Design a system that scales to millions of users on AWS | [Solution](solutions/system_design/scaling_aws/README.md) |
| Add a system design question | [Contribute](#contributing) |
You can practice a few sample questions and discuss solutions with the community on this [practice platform](https://workat.tech/system-design/practice).
### Design Pastebin.com (or Bit.ly)
[View exercise and solution](solutions/system_design/pastebin/README.md)
![Imgur](images/4edXG0T.png)
### Design the Twitter timeline and search (or Facebook feed and search)
[View exercise and solution](solutions/system_design/twitter/README.md)
![Imgur](images/jrUBAF7.png)
### Design a web crawler
[View exercise and solution](solutions/system_design/web_crawler/README.md)
![Imgur](images/bWxPtQA.png)
### Design Mint.com
[View exercise and solution](solutions/system_design/mint/README.md)
![Imgur](images/V5q57vU.png)
### Design the data structures for a social network
[View exercise and solution](solutions/system_design/social_graph/README.md)
![Imgur](images/cdCv5g7.png)
### Design a key-value store for a search engine
[View exercise and solution](solutions/system_design/query_cache/README.md)
![Imgur](images/4j99mhe.png)
### Design Amazon's sales ranking by category feature
[View exercise and solution](solutions/system_design/sales_rank/README.md)
![Imgur](images/MzExP06.png)
### Design a system that scales to millions of users on AWS
[View exercise and solution](solutions/system_design/scaling_aws/README.md)
![Imgur](images/jj3A5N8.png)
## Object-oriented design interview questions with solutions
> Common object-oriented design interview questions with sample discussions, code, and diagrams.
> Solutions linked to content in the `solutions/` folder.
>**Note: This section is under development**
| Question | |
|---|---|
| Design a hash map | [Solution](solutions/object_oriented_design/hash_table/hash_map.ipynb) |
| Design a least recently used cache | [Solution](solutions/object_oriented_design/lru_cache/lru_cache.ipynb) |
| Design a call center | [Solution](solutions/object_oriented_design/call_center/call_center.ipynb) |
| Design a deck of cards | [Solution](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| Design a parking lot | [Solution](solutions/object_oriented_design/parking_lot/parking_lot.ipynb) |
| Design a chat server | [Solution](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| Design a cab booking | [Solution](https://youtu.be/Yn7C0x5ozx4) |
| Design a circular array | [Contribute](#contributing) |
| Add an object-oriented design question | [Contribute](#contributing) |
**Stuck?** Watch this [quick video](https://www.youtube.com/watch?v=tv-_1er1mWI) on common [design patterns](https://roadmap.sh/guides/design-patterns-for-humans)
## System design topics: start here
New to system design?
First, you'll need a basic understanding of common principles, learning about what they are, how they are used, and their pros and cons.
### Step 1: Review the scalability video lecture
[Scalability Lecture at Harvard](https://www.youtube.com/watch?v=6PWTxRGh_dk)
* Topics covered:
* Vertical scaling
* Horizontal scaling
* Caching
* Load balancing
* Database replication
* Database partitioning
* High availability
### Step 2: Review the scalability article
[Scalability](https://lecloud.tumblr.com/tagged/scalability)
* Topics covered:
* [Clones](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [Databases](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [Caches](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [Asynchronism](https://lecloud.tumblr.com/post/9699762917/scalability-for-dummies-part-4-asynchronism)
### Next steps
Next, we'll look at high-level trade-offs:
* **Performance** vs **scalability**
* **Latency** vs **throughput**
* **Availability** vs **consistency**
Keep in mind that **everything is a trade-off**.
Then we'll dive into more specific topics such as DNS, CDNs, and load balancers.
## Performance vs scalability
A service is **scalable** if it results in increased **performance** in a manner proportional to resources added. Generally, increasing performance means serving more units of work, but it can also be to handle larger units of work, such as when datasets grow.<sup><a href=http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html>1</a></sup>
Another way to look at performance vs scalability:
* If you have a **performance** problem, your system is slow for a single user.
* If you have a **scalability** problem, your system is fast for a single user but slow under heavy load.
### Source(s) and further reading
* [A short masterclass on Scalability](https://open.substack.com/pub/devdesigndigest/p/scalability)
* [A word on scalability](http://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [The Scale Cube](https://microservices.io/articles/scalecube.html)
## Latency vs throughput
**Latency** is the time to perform some action or to produce some result.
**Throughput** is the number of such actions or results per unit of time.
Generally, you should aim for **maximal throughput** with **acceptable latency**.
### Source(s) and further reading
* [Understanding latency vs throughput](https://community.cadence.com/cadence_blogs_8/b/fv/posts/understanding-latency-vs-throughput)
* [Difference between latency and throughput and how to improve it](https://aws.amazon.com/compare/the-difference-between-throughput-and-latency/)
## Availability vs consistency
### CAP theorem
<p align="center">
<img src="images/1_2Ed1S7UUfLT21AeH0ymIwQ.png">
<br/>
<i><a href=https://medium.com/codenx/explaining-the-cap-theorem-and-its-limitations-e43f47f104c3>Source: medium.com explaining-the-cap-theorem-and-its-limitations</a></i>
</p>
In a distributed computer system, you can only support two of the following guarantees:
* **Consistency** - Every read receives the most recent write or an error
* **Availability** - Every request receives a response, without guarantee that it contains the most recent version of the information
* **Partition Tolerance** - The system continues to operate despite arbitrary partitioning due to network failures
*Networks aren't reliable, so you'll need to support partition tolerance. You'll need to make a software tradeoff between consistency and availability.*
#### CP - consistency and partition tolerance
Waiting for a response from the partitioned node might result in a timeout error. CP is a good choice if your business needs require atomic reads and writes.
#### AP - availability and partition tolerance
Responses return the most readily available version of the data available on any node, which might not be the latest. Writes might take some time to propagate when the partition is resolved.
AP is a good choice if the business needs to allow for [eventual consistency](#eventual-consistency) or when the system needs to continue working despite external errors.
### Source(s) and further reading
* [CAP theorem revisited](http://robertgreiner.com/2014/08/cap-theorem-revisited/)
* [A plain english introduction to CAP theorem](http://ksat.me/a-plain-english-introduction-to-cap-theorem)
* [CAP FAQ](https://github.com/henryr/cap-faq)
* [The CAP theorem](https://www.youtube.com/watch?v=k-Yaq8AHlFA)
## Consistency patterns
With multiple copies of the same data, we are faced with options on how to synchronize them so clients have a consistent view of the data. Recall the definition of consistency from the [CAP theorem](#cap-theorem) - Every read receives the most recent write or an error.
### Weak consistency
After a write, reads may or may not see it. A best effort approach is taken.
This approach is seen in systems such as memcached. Weak consistency works well in real time use cases such as VoIP, video chat, and realtime multiplayer games. For example, if you are on a phone call and lose reception for a few seconds, when you regain connection you do not hear what was spoken during connection loss.
### Eventual consistency
After a write, reads will eventually see it (typically within milliseconds). Data is replicated asynchronously.
This approach is seen in systems such as DNS and email. Eventual consistency works well in highly available systems.
### Strong consistency
After a write, reads will see it. Data is replicated synchronously.
This approach is seen in file systems and RDBMSes. Strong consistency works well in systems that need transactions.
### Source(s) and further reading
* [Transactions across data centers](http://snarfed.org/transactions_across_datacenters_io.html)
## Availability patterns
There are two complementary patterns to support high availability: **fail-over** and **replication**.
### Fail-over
#### Active-passive
With active-passive fail-over, heartbeats are sent between the active and the passive server on standby. If the heartbeat is interrupted, the passive server takes over the active's IP address and resumes service.
The length of downtime is determined by whether the passive server is already running in 'hot' standby or whether it needs to start up from 'cold' standby. Only the active server handles traffic.
Active-passive failover can also be referred to as master-slave failover.
#### Active-active
In active-active, both servers are managing traffic, spreading the load between them.
If the servers are public-facing, the DNS would need to know about the public IPs of both servers. If the servers are internal-facing, application logic would need to know about both servers.
Active-active failover can also be referred to as master-master failover.
### Disadvantage(s): failover
* Fail-over adds more hardware and additional complexity.
* There is a potential for loss of data if the active system fails before any newly written data can be replicated to the passive.
* A stateful system that does not have built-in support for Active-Passive failover will usually not work as expected if an external tool is used to facilitate failover.
### Replication
#### Master-slave and master-master
This topic is further discussed in the [Database](#database) section:
* [Master-slave replication](#master-slave-replication)
* [Master-master replication](#master-master-replication)
### Availability in numbers
Availability is often quantified by uptime (or downtime) as a percentage of time the service is available. Availability is generally measured in number of 9s--a service with 99.99% availability is described as having four 9s.
#### 99.9% availability - three 9s
| Duration | Acceptable downtime|
|---------------------|--------------------|
| Downtime per year | 8h 45min 57.6s |
| Downtime per month | 43m 49.8s |
| Downtime per week | 10m 4.8s |
| Downtime per day | 1m 26.4s |
#### 99.99% availability - four 9s
| Duration | Acceptable downtime|
|---------------------|--------------------|
| Downtime per year | 52min 35.8s |
| Downtime per month | 4m 23.0s |
| Downtime per week | 1m 0.5s |
| Downtime per day | 8.6s |
#### Availability in parallel vs in sequence
If a service consists of multiple components prone to failure, the service's overall availability depends on whether the components are in sequence or in parallel.
##### In sequence
Overall availability decreases when two components with availability < 100% are in sequence:
```text
Availability (Total) = Availability (Foo) * Availability (Bar)
```
If both `Foo` and `Bar` each had 99.9% availability, their total availability in sequence would be 99.8%.
##### In parallel
Overall availability increases when two components with availability < 100% are in parallel:
```text
Availability (Total) = 1 - (1 - Availability (Foo)) * (1 - Availability (Bar))
```
If both `Foo` and `Bar` each had 99.9% availability, their total availability in parallel would be 99.9999%.
## Domain name system
<p align="center">
<img src="images/IOyLj4i.jpg">
<br/>
<i><a href=http://www.slideshare.net/srikrupa5/dns-security-presentation-issa>Source: DNS security presentation</a></i>
</p>
A Domain Name System (DNS) translates a domain name such as <www.example.com> to an IP address.
DNS is hierarchical, with a few authoritative servers at the top level. Your router or ISP provides information about which DNS server(s) to contact when doing a lookup. Lower level DNS servers cache mappings, which could become stale due to DNS propagation delays. DNS results can also be cached by your browser or OS for a certain period of time, determined by the [time to live (TTL)](https://en.wikipedia.org/wiki/Time_to_live).
* **NS record (name server)** - Specifies the DNS servers for your domain/subdomain.
* **MX record (mail exchange)** - Specifies the mail servers for accepting messages.
* **A record (address)** - Points a name to an IP address.
* **CNAME (canonical)** - Points a name to another name or `CNAME` (example.com to <www.example.com>) or to an `A` record.
Services such as [CloudFlare](https://www.cloudflare.com/dns/) and [Route 53](https://aws.amazon.com/route53/) provide managed DNS services. Some DNS services can route traffic through various methods:
* [Weighted round robin](https://www.jscape.com/blog/load-balancing-algorithms)
* Prevent traffic from going to servers under maintenance
* Balance between varying cluster sizes
* A/B testing
* [Latency-based](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-latency.html)
* [Geolocation-based](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-geo.html)
### Disadvantage(s): DNS
* Accessing a DNS server introduces a slight delay, although mitigated by caching described above.
* DNS server management could be complex and is generally managed by [governments, ISPs, and large companies](http://superuser.com/questions/472695/who-controls-the-dns-servers/472729).
* DNS services have recently come under [DDoS attack](http://dyn.com/blog/dyn-analysis-summary-of-friday-october-21-attack/), preventing users from accessing websites such as Twitter without knowing Twitter's IP address(es).
### Source(s) and further reading
* [What happens when you type an URL in Browser](https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a)
* [DNS architecture](https://technet.microsoft.com/en-us/library/dd197427(v=ws.10).aspx)
* [Wikipedia](https://en.wikipedia.org/wiki/Domain_Name_System)
* [DNS articles](https://support.dnsimple.com/categories/dns/)
* [How DNS works](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)
## Content delivery network
<p align="center">
<img src="images/h9TAuGI.jpg">
<br/>
<i><a href=https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/>Source: Why use a CDN</a></i>
</p>
A content delivery network (CDN) is a globally distributed network of proxy servers, serving content from locations closer to the user. Generally, static files such as HTML/CSS/JS, photos, and videos are served from CDN, although some CDNs such as Amazon's CloudFront support dynamic content. The site's DNS resolution will tell clients which server to contact.
Serving content from CDNs can significantly improve performance in two ways:
* Users receive content from data centers close to them
* Your servers do not have to serve requests that the CDN fulfills
### Push CDNs
Push CDNs receive new content whenever changes occur on your server. You take full responsibility for providing content, uploading directly to the CDN and rewriting URLs to point to the CDN. You can configure when content expires and when it is updated. Content is uploaded only when it is new or changed, minimizing traffic, but maximizing storage.
Sites with a small amount of traffic or sites with content that isn't often updated work well with push CDNs. Content is placed on the CDNs once, instead of being re-pulled at regular intervals.
### Pull CDNs
Pull CDNs grab new content from your server when the first user requests the content. You leave the content on your server and rewrite URLs to point to the CDN. This results in a slower request until the content is cached on the CDN.
A [time-to-live (TTL)](https://en.wikipedia.org/wiki/Time_to_live) determines how long content is cached. Pull CDNs minimize storage space on the CDN, but can create redundant traffic if files expire and are pulled before they have actually changed.
Sites with heavy traffic work well with pull CDNs, as traffic is spread out more evenly with only recently-requested content remaining on the CDN.
### Disadvantage(s): CDN
* CDN costs could be significant depending on traffic, although this should be weighed with additional costs you would incur not using a CDN.
* Content might be stale if it is updated before the TTL expires it.
* CDNs require changing URLs for static content to point to the CDN.
### Source(s) and further reading
* [Globally distributed content delivery](https://figshare.com/articles/Globally_distributed_content_delivery/6605972)
* [The differences between push and pull CDNs](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)
* [Wikipedia](https://en.wikipedia.org/wiki/Content_delivery_network)
* [Akamai CDN](https://www.akamai.com/our-thinking/cdn/what-is-a-cdn)
## Load balancer
<p align="center">
<img src="images/h81n9iK.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Source: Scalable system design patterns</a></i>
</p>
Load balancers distribute incoming client requests to computing resources such as application servers and databases. In each case, the load balancer returns the response from the computing resource to the appropriate client. Load balancers are effective at:
* Preventing requests from going to unhealthy servers
* Preventing overloading resources
* Helping to eliminate a single point of failure
Load balancers can be implemented with hardware (expensive) or with software such as HAProxy.
Additional benefits include:
* **SSL termination** - Decrypt incoming requests and encrypt server responses so backend servers do not have to perform these potentially expensive operations
* Removes the need to install [X.509 certificates](https://en.wikipedia.org/wiki/X.509) on each server
* **Session persistence** - Issue cookies and route a specific client's requests to same instance if the web apps do not keep track of sessions
To protect against failures, it's common to set up multiple load balancers, either in [active-passive](#active-passive) or [active-active](#active-active) mode.
Load balancers can route traffic based on various metrics, including:
* Random
* Least loaded
* Session/cookies
* [Round robin or weighted round robin](https://www.g33kinfo.com/info/round-robin-vs-weighted-round-robin-lb)
* [Layer 4](#layer-4-load-balancing)
* [Layer 7](#layer-7-load-balancing)
* [Consistent Hashing](#consistent-hashing)
### Layer 4 load balancing
Layer 4 load balancers look at info at the [transport layer](#communication) to decide how to distribute requests. Generally, this involves the source, destination IP addresses, and ports in the header, but not the contents of the packet. Layer 4 load balancers forward network packets to and from the upstream server, performing [Network Address Translation (NAT)](https://www.geeksforgeeks.org/network-address-translation-nat/).
### Layer 7 load balancing
Layer 7 load balancers look at the [application layer](#communication) to decide how to distribute requests. This can involve contents of the header, message, and cookies. Layer 7 load balancers terminate network traffic, read the message, make a load-balancing decision, then open a connection to the selected server. For example, a layer 7 load balancer can direct video traffic to servers that host videos while directing more sensitive user billing traffic to security-hardened servers.
At the cost of flexibility, layer 4 load balancing requires less time and computing resources than layer 7, although the performance impact can be minimal on modern commodity hardware.
### Consistent Hashing
Consistent hashing is a technique used in load balancing to distribute requests evenly across multiple servers in a distributed system.
Here's how it works:
* <b>Hash Ring:</b> Imagine a virtual circle, called a hash ring. Each server and each incoming request is assigned a position on this circle based on a hash function. The hash function ensures that the same input (server ID or request data) always gets mapped to the same position on the ring.
* <b>Request Distribution:</b> When a request arrives, its data (often a unique identifier) is hashed to determine its position on the hash ring. The server responsible for handling the request is the one whose position on the ring comes after the hashed request data, continuing clockwise around the circle.
* <b>Scalability and Consistency:</b> The key benefit of consistent hashing is its scalability. If a server is added or removed, only requests that map to the immediate vicinity of the affected server will be re-routed. Most requests will continue to be directed to the same servers as before. This minimizes data re-caching and avoids creating hotspots where certain servers become overloaded
<p align="center">
<img src="images/jsjss.png">
<br/>
</p>
### Horizontal scaling
Load balancers can also help with horizontal scaling, improving performance and availability. Scaling out using commodity machines is more cost efficient and results in higher availability than scaling up a single server on more expensive hardware, called **Vertical Scaling**. It is also easier to hire for talent working on commodity hardware than it is for specialized enterprise systems.
#### Disadvantage(s): horizontal scaling
* Scaling horizontally introduces complexity and involves cloning servers
* Servers should be stateless: they should not contain any user-related data like sessions or profile pictures
* Sessions can be stored in a centralized data store such as a [database](#database) (SQL, NoSQL) or a persistent [cache](#cache) (Redis, Memcached)
* Downstream servers such as caches and databases need to handle more simultaneous connections as upstream servers scale out
### Disadvantage(s): load balancer
* The load balancer can become a performance bottleneck if it does not have enough resources or if it is not configured properly.
* Introducing a load balancer to help eliminate a single point of failure results in increased complexity.
* A single load balancer is a single point of failure, configuring multiple load balancers further increases complexity.
### Source(s) and further reading
* [NGINX architecture](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy architecture guide](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [Scalability](https://lecloud.tumblr.com/post/7295452622/scalability-for-dummies-part-1-clones)
* [Wikipedia](https://en.wikipedia.org/wiki/Load_balancing_(computing))
* [Layer 4 load balancing](https://www.nginx.com/resources/glossary/layer-4-load-balancing/)
* [Layer 7 load balancing](https://www.nginx.com/resources/glossary/layer-7-load-balancing/)
* [ELB listener config](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html)
## Reverse proxy (web server)
<p align="center">
<img src="images/n41Azff.png">
<br/>
<i><a href=https://upload.wikimedia.org/wikipedia/commons/6/67/Reverse_proxy_h2g2bob.svg>Source: Wikipedia</a></i>
<br/>
</p>
A reverse proxy is a web server that centralizes internal services and provides unified interfaces to the public. Requests from clients are forwarded to a server that can fulfill it before the reverse proxy returns the server's response to the client.
Additional benefits include:
* **Increased security** - Hide information about backend servers, blocklist IPs, limit number of connections per client
* **Increased scalability and flexibility** - Clients only see the reverse proxy's IP, allowing you to scale servers or change their configuration
* **SSL termination** - Decrypt incoming requests and encrypt server responses so backend servers do not have to perform these potentially expensive operations
* Removes the need to install [X.509 certificates](https://en.wikipedia.org/wiki/X.509) on each server
* **Compression** - Compress server responses
* **Caching** - Return the response for cached requests
* **Static content** - Serve static content directly
* HTML/CSS/JS
* Photos
* Videos
* Etc
* **Aggregates Requests** - aggregates multiple individual requests into a single request. This pattern applies when a single operation requires calls to multiple backend services. The client sends one request to the reverse proxy. The reverse proxy dispatches requests to the various backend services, and then aggregates the results and sends them back to the client. This helps to reduce chattiness between the client and the backend.
### Load balancer vs reverse proxy
* Deploying a load balancer is useful when you have multiple servers. Often, load balancers route traffic to a set of servers serving the same function.
* Reverse proxies can be useful even with just one web server or application server, opening up the benefits described in the previous section.
* Solutions such as NGINX and HAProxy can support both layer 7 reverse proxying and load balancing.
### Disadvantage(s): reverse proxy
* Introducing a reverse proxy results in increased complexity.
* A single reverse proxy is a single point of failure, configuring multiple reverse proxies (ie a [failover](https://en.wikipedia.org/wiki/Failover)) further increases complexity.
### Source(s) and further reading
* [Reverse proxy vs load balancer](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)
* [NGINX architecture](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)
* [HAProxy architecture guide](http://www.haproxy.org/download/1.2/doc/architecture.txt)
* [Wikipedia](https://en.wikipedia.org/wiki/Reverse_proxy)
* [API Gateways] (https://docs.microsoft.com/en-us/azure/architecture/microservices/design/gateway)
## Application layer
<p align="center">
<img src="images/yB5SYwm.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Source: Intro to architecting systems for scale</a></i>
</p>
Separating out the web layer from the application layer (also known as platform layer) allows you to scale and configure both layers independently. Adding new APIs results in adding application servers without necessarily adding additional web servers. The **single responsibility principle** advocates for small and autonomous services that work together. Small teams with small services can plan more aggressively for rapid growth.
Workers in the application layer also help enable [asynchronism](#asynchronism).
### Microservices
Related to this discussion are [microservices](https://en.wikipedia.org/wiki/Microservices), which can be described as a suite of independently deployable, small, modular services. Each service runs a unique process and communicates through a well-defined, lightweight mechanism to serve a business goal. <sup><a href=https://smartbear.com/learn/api-design/what-are-microservices>1</a></sup>
Pinterest, for example, could have the following microservices: user profile, follower, feed, search, photo upload, etc.
### Service Discovery
Systems such as [Consul](https://www.consul.io/docs/index.html), [Etcd](https://coreos.com/etcd/docs/latest), and [Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) can help services find each other by keeping track of registered names, addresses, and ports. [Health checks](https://www.consul.io/intro/getting-started/checks.html) help verify service integrity and are often done using an [HTTP](#hypertext-transfer-protocol-http) endpoint. Both Consul and Etcd have a built in [key-value store](#key-value-store) that can be useful for storing config values and other shared data.
### Disadvantage(s): application layer
* Adding an application layer with loosely coupled services requires a different approach from an architectural, operations, and process viewpoint (vs a monolithic system).
* Microservices can add complexity in terms of deployments and operations.
### Source(s) and further reading
* [Intro to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale)
* [Crack the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Service oriented architecture](https://en.wikipedia.org/wiki/Service-oriented_architecture)
* [Introduction to Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper)
* [Here's what you need to know about building microservices](https://cloudncode.wordpress.com/2016/07/22/msa-getting-started/)
## Database
<p align="center">
<img src="images/Xkm5CXz.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>Source: Scaling up to your first 10 million users</a></i>
</p>
### Relational database management system (RDBMS)
A relational database like SQL is a collection of data items organized in tables.
**ACID** is a set of properties of relational database [transactions](https://en.wikipedia.org/wiki/Database_transaction).
* **Atomicity** - Each transaction is all or nothing
* **Consistency** - Any transaction will bring the database from one valid state to another
* **Isolation** - Executing transactions concurrently has the same results as if the transactions were executed serially
* **Durability** - Once a transaction has been committed, it will remain so
There are many techniques to scale a relational database: **master-slave replication**, **master-master replication**, **federation**, **sharding**, **denormalization**, and **SQL tuning**.
#### Master-slave replication
The master serves reads and writes, replicating writes to one or more slaves, which serve only reads. Slaves can also replicate to additional slaves in a tree-like fashion. If the master goes offline, the system can continue to operate in read-only mode until a slave is promoted to a master or a new master is provisioned.
<p align="center">
<img src="images/C9ioGtn.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
##### Disadvantage(s): master-slave replication
* Additional logic is needed to promote a slave to a master.
* See [Disadvantage(s): replication](#disadvantages-replication) for points related to **both** master-slave and master-master.
#### Master-master replication
Both masters serve reads and writes and coordinate with each other on writes. If either master goes down, the system can continue to operate with both reads and writes.
<p align="center">
<img src="images/krAHLGg.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
##### Disadvantage(s): master-master replication
* You'll need a load balancer or you'll need to make changes to your application logic to determine where to write.
* Most master-master systems are either loosely consistent (violating ACID) or have increased write latency due to synchronization.
* Conflict resolution comes more into play as more write nodes are added and as latency increases.
* See [Disadvantage(s): replication](#disadvantages-replication) for points related to **both** master-slave and master-master.
##### Disadvantage(s): replication
* There is a potential for loss of data if the master fails before any newly written data can be replicated to other nodes.
* Writes are replayed to the read replicas. If there are a lot of writes, the read replicas can get bogged down with replaying writes and can't do as many reads.
* The more read slaves, the more you have to replicate, which leads to greater replication lag.
* On some systems, writing to the master can spawn multiple threads to write in parallel, whereas read replicas only support writing sequentially with a single thread.
* Replication adds more hardware and additional complexity.
##### Source(s) and further reading: replication
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [Multi-master replication](https://en.wikipedia.org/wiki/Multi-master_replication)
#### Federation
<p align="center">
<img src="images/U3qV33e.png">
<br/>
<i><a href=https://www.youtube.com/watch?v=kKjm4ehYiMs>Source: Scaling up to your first 10 million users</a></i>
</p>
Federation (or functional partitioning) splits up databases by function. For example, instead of a single, monolithic database, you could have three databases: **forums**, **users**, and **products**, resulting in less read and write traffic to each database and therefore less replication lag. Smaller databases result in more data that can fit in memory, which in turn results in more cache hits due to improved cache locality. With no single central master serializing writes you can write in parallel, increasing throughput.
##### Disadvantage(s): federation
* Federation is not effective if your schema requires huge functions or tables.
* You'll need to update your application logic to determine which database to read and write.
* Joining data from two databases is more complex with a [server link](http://stackoverflow.com/questions/5145637/querying-data-by-joining-two-tables-in-two-database-on-different-servers).
* Federation adds more hardware and additional complexity.
##### Source(s) and further reading: federation
* [Scaling up to your first 10 million users](https://www.youtube.com/watch?v=kKjm4ehYiMs)
#### Sharding
<p align="center">
<img src="images/wU8x5Id.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
Sharding distributes data across different databases such that each database can only manage a subset of the data. Taking a users database as an example, as the number of users increases, more shards are added to the cluster.
Similar to the advantages of [federation](#federation), sharding results in less read and write traffic, less replication, and more cache hits. Index size is also reduced, which generally improves performance with faster queries. If one shard goes down, the other shards are still operational, although you'll want to add some form of replication to avoid data loss. Like federation, there is no single central master serializing writes, allowing you to write in parallel with increased throughput.
Common ways to shard a table of users is either through the user's last name initial or the user's geographic location.
##### Disadvantage(s): sharding
* You'll need to update your application logic to work with shards, which could result in complex SQL queries.
* Data distribution can become lopsided in a shard. For example, a set of power users on a shard could result in increased load to that shard compared to others.
* Rebalancing adds additional complexity. A sharding function based on [consistent hashing](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html) can reduce the amount of transferred data.
* Joining data from multiple shards is more complex.
* Sharding adds more hardware and additional complexity.
##### Source(s) and further reading: sharding
* [The coming of the shard](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)
* [Shard database architecture](https://en.wikipedia.org/wiki/Shard_(database_architecture))
* [Consistent hashing](http://www.paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html)
#### Denormalization
Denormalization attempts to improve read performance at the expense of some write performance. Redundant copies of the data are written in multiple tables to avoid expensive joins. Some RDBMS such as [PostgreSQL](https://en.wikipedia.org/wiki/PostgreSQL) and Oracle support [materialized views](https://en.wikipedia.org/wiki/Materialized_view) which handle the work of storing redundant information and keeping redundant copies consistent.
Once data becomes distributed with techniques such as [federation](#federation) and [sharding](#sharding), managing joins across data centers further increases complexity. Denormalization might circumvent the need for such complex joins.
In most systems, reads can heavily outnumber writes 100:1 or even 1000:1. A read resulting in a complex database join can be very expensive, spending a significant amount of time on disk operations.
##### Disadvantage(s): denormalization
* Data is duplicated.
* Constraints can help redundant copies of information stay in sync, which increases complexity of the database design.
* A denormalized database under heavy write load might perform worse than its normalized counterpart.
###### Source(s) and further reading: denormalization
* [Denormalization](https://en.wikipedia.org/wiki/Denormalization)
* [Understand Denormalization with analogy](https://www.youtube.com/watch?v=T3cx09FINuU)
#### SQL tuning
SQL tuning is a broad topic and many [books](https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=sql+tuning) have been written as reference.
It's important to **benchmark** and **profile** to simulate and uncover bottlenecks.
* **Benchmark** - Simulate high-load situations with tools such as [ab](http://httpd.apache.org/docs/2.2/programs/ab.html).
* **Profile** - Enable tools such as the [slow query log](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html) to help track performance issues.
Benchmarking and profiling might point you to the following optimizations.
##### Tighten up the schema
* MySQL dumps to disk in contiguous blocks for fast access.
* In some old databases it was better to use `CHAR` instead of `VARCHAR` for fixed-length fields.
In those systems `CHAR` effectively allowed for fast, random access, whereas with `VARCHAR`, the system had to find the end of a string before moving onto the next one.
But im most modern DB not only that this is not true, but more over it sometimes the opposite, e.g. [Postgresql tip on datatype]https://www.postgresql.org/docs/current/datatype-character.html
* 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](https://dev.mysql.com/doc/refman/5.7/en/query-cache.html) could lead to [performance issues](https://www.percona.com/blog/2016/10/12/mysql-5-7-performance-tuning-immediately-after-installation/).
##### Source(s) and further reading: SQL tuning
* [Tips for optimizing MySQL queries](http://aiddroid.com/10-tips-optimizing-mysql-queries-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)
* [Slow query log](http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html)
### NoSQL
NoSQL is a collection of data items represented in a **key-value store**, **document store**, **wide column store**, or a **graph database**. Data is denormalized, and joins are generally done in the application code. Most NoSQL stores lack true ACID transactions and favor [eventual consistency](#eventual-consistency).
**BASE** is often used to describe the properties of NoSQL databases. In comparison with the [CAP Theorem](#cap-theorem), BASE chooses availability over consistency.
* **Basically available** - the system guarantees availability.
* **Soft state** - the state of the system may change over time, even without input.
* **Eventual consistency** - the system will become consistent over a period of time, given that the system doesn't receive input during that period.
In addition to choosing between [SQL or NoSQL](#sql-or-nosql), it is helpful to understand which type of NoSQL database best fits your use case(s). We'll review **key-value stores**, **document stores**, **wide column stores**, and **graph databases** in the next section.
#### Key-value store
> Abstraction: hash table
A key-value store generally allows for O(1) reads and writes and is often backed by memory or SSD. Data stores can maintain keys in [lexicographic order](https://en.wikipedia.org/wiki/Lexicographical_order), allowing efficient retrieval of key ranges. Key-value stores can allow for storing of metadata with a value.
Key-value stores provide high performance and are often used for simple data models or for rapidly-changing data, such as an in-memory cache layer. Since they offer only a limited set of operations, complexity is shifted to the application layer if additional operations are needed.
A key-value store is the basis for more complex systems such as a document store, and in some cases, a graph database.
##### Source(s) and further reading: key-value store
* [Key-value database](https://en.wikipedia.org/wiki/Key-value_database)
* [Disadvantages of key-value stores](http://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)
* [Redis architecture](https://architecturenotes.co/p/redis)
* [Memcached architecture](https://adayinthelifeof.nl/2011/02/06/memcache-internals/)
#### Document store
> Abstraction: key-value store with documents stored as values
A document store is centered around documents (XML, JSON, binary, etc), where a document stores all information for a given object. Document stores provide APIs or a query language to query based on the internal structure of the document itself. *Note, many key-value stores include features for working with a value's metadata, blurring the lines between these two storage types.*
Based on the underlying implementation, documents are organized by collections, tags, metadata, or directories. Although documents can be organized or grouped together, documents may have fields that are completely different from each other.
Some document stores like [MongoDB](https://www.mongodb.com/mongodb-architecture) and [CouchDB](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/) also provide a SQL-like language to perform complex queries. [DynamoDB](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/decandia07dynamo.pdf) supports both key-values and documents.
Document stores provide high flexibility and are often used for working with occasionally changing data.
##### Source(s) and further reading: document store
* [Document-oriented database](https://en.wikipedia.org/wiki/Document-oriented_database)
* [MongoDB architecture](https://www.mongodb.com/mongodb-architecture)
* [CouchDB architecture](https://blog.couchdb.org/2016/08/01/couchdb-2-0-architecture/)
* [Elasticsearch architecture](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)
#### Wide column store
<p align="center">
<img src="images/n16iOGk.png">
<br/>
<i><a href=http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html>Source: SQL & NoSQL, a brief history</a></i>
</p>
> Abstraction: nested map `ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>`
A wide column store's basic unit of data is a column (name/value pair). A column can be grouped in column families (analogous to a SQL table). Super column families further group column families. You can access each column independently with a row key, and columns with the same row key form a row. Each value contains a timestamp for versioning and for conflict resolution.
Google introduced [Bigtable](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf) as the first wide column store, which influenced the open-source [HBase](https://www.edureka.co/blog/hbase-architecture/) often-used in the Hadoop ecosystem, and [Cassandra](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html) from Facebook. Stores such as BigTable, HBase, and Cassandra maintain keys in lexicographic order, allowing efficient retrieval of selective key ranges.
Wide column stores offer high availability and high scalability. They are often used for very large data sets.
##### Source(s) and further reading: wide column store
* [SQL & NoSQL, a brief history](http://blog.grio.com/2015/11/sql-nosql-a-brief-history.html)
* [Bigtable architecture](http://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)
* [HBase architecture](https://www.edureka.co/blog/hbase-architecture/)
* [Cassandra architecture](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html)
#### Graph database
<p align="center">
<img src="images/fNcl65g.png">
<br/>
<i><a href=https://en.wikipedia.org/wiki/File:GraphDatabase_PropertyGraph.png>Source: Graph database</a></i>
</p>
> Abstraction: graph
In a graph database, each node is a record and each arc is a relationship between two nodes. Graph databases are optimized to represent complex relationships with many foreign keys or many-to-many relationships.
Graphs databases offer high performance for data models with complex relationships, such as a social network. They are relatively new and are not yet widely-used; it might be more difficult to find development tools and resources. Many graphs can only be accessed with [REST APIs](#representational-state-transfer-rest).
##### Source(s) and further reading: graph
* [Graph database](https://en.wikipedia.org/wiki/Graph_database)
* [Neo4j](https://neo4j.com/)
* [FlockDB](https://blog.twitter.com/2010/introducing-flockdb)
* [Dgraph](https://dgraph.io/)
#### Source(s) and further reading: NoSQL
* [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)
* [Scalability](https://lecloud.tumblr.com/post/7994751381/scalability-for-dummies-part-2-database)
* [Introduction to NoSQL](https://www.youtube.com/watch?v=qI_g07C_Q5I)
* [NoSQL patterns](http://horicky.blogspot.com/2009/11/nosql-patterns.html)
### SQL or NoSQL
<p align="center">
<img src="images/wXGqG5f.png">
<br/>
<i><a href=https://www.infoq.com/articles/Transition-RDBMS-NoSQL/>Source: Transitioning from RDBMS to NoSQL</a></i>
</p>
Reasons for **SQL**:
* Structured data
* Strict schema
* Relational data
* Need for complex joins
* Transactions
* Clear patterns for scaling
* More established: developers, community, code, tools, etc
* Lookups by index are very fast
Reasons for **NoSQL**:
* Semi-structured data
* Dynamic or flexible schema
* Non-relational data
* No need for complex joins
* Store many TB (or PB) of data
* Very data intensive workload
* Very high throughput for IOPS
Sample data well-suited for **NoSQL**:
* Rapid ingest of clickstream and log data
* Leaderboard or scoring data
* Temporary data, such as a shopping cart
* Frequently accessed ('hot') tables
* Metadata/lookup tables
#### Source(s) and further reading: SQL or NoSQL
* [Scaling up to your first 10 million users](https://www.youtube.com/watch?v=kKjm4ehYiMs)
* [SQL vs NoSQL differences](https://www.sitepoint.com/sql-vs-nosql-differences/)
## Cache
<p align="center">
<img src="images/Q6z24La.png">
<br/>
<i><a href=http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html>Source: Scalable system design patterns</a></i>
</p>
Caching improves page load times and can reduce the load on your servers and databases. In this model, the dispatcher will first lookup if the request has been made before and try to find the previous result to return, in order to save the actual execution.
Databases often benefit from a uniform distribution of reads and writes across its partitions. Popular items can skew the distribution, causing bottlenecks. Putting a cache in front of a database can help absorb uneven loads and spikes in traffic.
### Client caching
Caches can be located on the client side (OS or browser), [server side](#reverse-proxy-web-server), or in a distinct cache layer.
### CDN caching
[CDNs](#content-delivery-network) are considered a type of cache.
### Web server caching
[Reverse proxies](#reverse-proxy-web-server) and caches such as [Varnish](https://www.varnish-cache.org/) can serve static and dynamic content directly. Web servers can also cache requests, returning responses without having to contact application servers.
### Database caching
Your database usually includes some level of caching in a default configuration, optimized for a generic use case. Tweaking these settings for specific usage patterns can further boost performance.
### Application caching
In-memory caches such as Memcached and Redis are key-value stores between your application and your data storage. Since the data is held in RAM, it is much faster than typical databases where data is stored on disk. RAM is more limited than disk, so [cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms) algorithms such as [least recently used (LRU)](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) can help invalidate 'cold' entries and keep 'hot' data in RAM.
Redis has the following additional features:
* Persistence option
* Built-in data structures such as sorted sets and lists
There are multiple levels you can cache that fall into two general categories: **database queries** and **objects**:
* Row level
* Query-level
* Fully-formed serializable objects
* Fully-rendered HTML
Generally, you should try to avoid file-based caching, as it makes cloning and auto-scaling more difficult.
### Caching at the database query level
Whenever you query the database, hash the query as a key and store the result to the cache. This approach suffers from expiration issues:
* Hard to delete a cached result with complex queries
* If one piece of data changes such as a table cell, you need to delete all cached queries that might include the changed cell
### Caching at the object level
See your data as an object, similar to what you do with your application code. Have your application assemble the dataset from the database into a class instance or a data structure(s):
* Remove the object from cache if its underlying data has changed
* Allows for asynchronous processing: workers assemble objects by consuming the latest cached object
Suggestions of what to cache:
* User sessions
* Fully rendered web pages
* Activity streams
* User graph data
### When to update the cache
Since you can only store a limited amount of data in cache, you'll need to determine which cache update strategy works best for your use case.
#### Cache-aside
<p align="center">
<img src="images/ONjORqk.png">
<br/>
<i><a href=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>
The application is responsible for reading and writing from storage. The cache does not interact with storage directly. The application does the following:
* Look for entry in cache, resulting in a cache miss
* Load entry from the database
* Add entry to cache
* Return entry
```python
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user:
return user
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user
```
[Memcached](https://memcached.org/) is generally used in this manner.
Subsequent reads of data added to cache are fast. Cache-aside is also referred to as lazy loading. Only requested data is cached, which avoids filling up the cache with data that isn't requested.
##### Disadvantage(s): cache-aside
* Each cache miss results in three trips, which can cause a noticeable delay.
* Data can become stale if it is updated in the database. This issue is mitigated by setting a time-to-live (TTL) which forces an update of the cache entry, or by using write-through.
* When a node fails, it is replaced by a new, empty node, increasing latency.
#### Write-through
<p align="center">
<img src="images/0vBc0hN.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
The application uses the cache as the main data store, reading and writing data to it, while the cache is responsible for reading and writing to the database:
* Application adds/updates entry in cache
* Cache synchronously writes entry to data store
* Return
Application code:
```python
set_user(12345, {"foo":"bar"})
```
Cache code:
```python
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)
```
Write-through is a slow overall operation due to the write operation, but subsequent reads of just written data are fast. Users are generally more tolerant of latency when updating data than reading data. Data in the cache is not stale.
##### Disadvantage(s): write through
* When a new node is created due to failure or scaling, the new node will not cache entries until the entry is updated in the database. Cache-aside in conjunction with write through can mitigate this issue.
* Most data written might never be read, which can be minimized with a TTL.
* Failure in "Store in the DB" may lead to cache storing data that was never committed to the database. For a strong consistency, it's necessary to update the cache and the database in a distributed transaction that will roll back the cache in case of database failure. This adds complexity to the system.
#### Write-behind (write-back)
<p align="center">
<img src="images/rgSrvjG.png">
<br/>
<i><a href=http://www.slideshare.net/jboner/scalability-availability-stability-patterns/>Source: Scalability, availability, stability, patterns</a></i>
</p>
In write-behind, the application does the following:
* Add/update entry in cache
* Asynchronously write entry to the data store, improving write performance
##### Disadvantage(s): write-behind
* There could be data loss if the cache goes down prior to its contents hitting the data store.
* It is more complex to implement write-behind than it is to implement cache-aside or write-through.
#### Refresh-ahead
<p align="center">
<img src="images/kxtjqgE.png">
<br/>
<i><a href=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>
You can configure the cache to automatically refresh any recently accessed cache entry prior to its expiration.
Refresh-ahead can result in reduced latency vs read-through if the cache can accurately predict which items are likely to be needed in the future.
##### Disadvantage(s): refresh-ahead
* Not accurately predicting which items are likely to be needed in the future can result in reduced performance than without refresh-ahead.
### Disadvantage(s): cache
* Need to maintain consistency between caches and the source of truth such as the database through [cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms).
* Cache invalidation is a difficult problem, there is additional complexity associated with when to update the cache.
* Need to make application changes such as adding Redis or memcached.
### Source(s) and further reading
* [From cache to in-memory data grid](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)
* [Scalable system design patterns](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)
* [Introduction to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale/)
* [Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
* [Scalability](https://lecloud.tumblr.com/post/9246290032/scalability-for-dummies-part-3-cache)
* [AWS ElastiCache strategies](https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/Strategies.html)
* [Wikipedia](https://en.wikipedia.org/wiki/Cache_(computing))
## Asynchronism
<p align="center">
<img src="images/54GYsSx.png">
<br/>
<i><a href=http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer>Source: Intro to architecting systems for scale</a></i>
</p>
Asynchronous workflows help reduce request times for expensive operations that would otherwise be performed in-line. They can also help by doing time-consuming work in advance, such as periodic aggregation of data.
### Message queues
Message queues receive, hold, and deliver messages. If an operation is too slow to perform inline, you can use a message queue with the following workflow:
* An application publishes a job to the queue, then notifies the user of job status
* A worker picks up the job from the queue, processes it, then signals the job is complete
The user is not blocked and the job is processed in the background. During this time, the client might optionally do a small amount of processing to make it seem like the task has completed. For example, if posting a tweet, the tweet could be instantly posted to your timeline, but it could take some time before your tweet is actually delivered to all of your followers.
**[Redis](https://redis.io/)** is useful as a simple message broker but messages can be lost.
**[RabbitMQ](https://www.rabbitmq.com/)** is popular but requires you to adapt to the 'AMQP' protocol and manage your own nodes.
**[Amazon SQS](https://aws.amazon.com/sqs/)** is hosted but can have high latency and has the possibility of messages being delivered twice.
### Task queues
Tasks queues receive tasks and their related data, run them, then deliver their results. They can support scheduling, and can be used to run computationally-intensive jobs in the background.
**[Celery](https://docs.celeryproject.org/en/stable/)** has support for scheduling and primarily has python support.
### Back pressure
If queues start to grow significantly, the queue size can become larger than memory, resulting in cache misses, disk reads, and even slower performance. [Back pressure](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html) can help by limiting the queue size, thereby maintaining a high throughput rate and good response times for jobs already in the queue. Once the queue fills up, clients get a server busy or HTTP 503 status code to try again later. Clients can retry the request at a later time, perhaps with [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff).
### Transactional Messaging
Transactional messaging ensures reliable delivery and processing of messages while maintaining consistency across systems, especially in distributed architectures. It is critical for systems where operations must succeed or fail as a unit. [The Outbox Pattern](https://www.decodable.co/blog/revisiting-the-outbox-pattern) is a design to handle distributed transactions in an eventually consistent way. It ensures that messages are not lost even if a failure occurs while performing operations across multiple systems.
* The application writes a business change and the corresponding event (message) to an outbox table in the same database transaction.
* The transaction is committed, ensuring both the business operation and the event are saved together.
* A background worker periodically reads unprocessed messages from the outbox table and publishes them to the message queue.
* Upon successful delivery, the worker marks the messages as processed to avoid duplicates.
The database used for the outbox table must support ACID transactions to ensure atomicity, consistency, isolation, and durability. This ensures that both the business operation and the event write are treated as a single unit of work and are committed together reliably.
**Example:**
Consider an e-commerce system where a user places an order. As part of the transaction:
* The order's status is updated to "Placed" in the database.
* A corresponding "process payment" event is written to the outbox table within the same transaction.
Once the transaction is committed, a background worker reads the "process payment" event from the outbox table and publishes it to the payment service queue. This ensures that the payment service is notified about the new order only if the database update for the order status was successful. Similarly, the order status update happens only if the event is successfully written to the outbox table, maintaining consistency across the system.
### Disadvantage(s): asynchronism
* Use cases such as inexpensive calculations and realtime workflows might be better suited for synchronous operations, as introducing queues can add delays and complexity.
### Source(s) and further reading
* [It's all a numbers game](https://www.youtube.com/watch?v=1KRYH75wgy4)
* [Applying back pressure when overloaded](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)
* [Little's law](https://en.wikipedia.org/wiki/Little%27s_law)
* [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)
## Communication
<p align="center">
<img src="images/5KeocQs.jpg">
<br/>
<i><a href=http://www.escotal.com/osilayer.html>Source: OSI 7 layer model</a></i>
</p>
### Hypertext transfer protocol (HTTP)
HTTP is a method for encoding and transporting data between a client and a server. It is a request/response protocol: clients issue requests and servers issue responses with relevant content and completion status info about the request. HTTP is self-contained, allowing requests and responses to flow through many intermediate routers and servers that perform load balancing, caching, encryption, and compression.
A basic HTTP request consists of a verb (method) and a resource (endpoint). Below are the common HTTP verbs:
| Verb | Description | Idempotent* | Safe | Cacheable |
|---|---|---|---|---|
| GET | Reads a resource | Yes | Yes | Yes |
| POST | Creates a resource or triggers a process that handles data | No | No | Yes if response contains freshness info |
| PUT | Creates or replaces a resource | Yes | No | No |
| PATCH | Partially updates a resource | No | No | Yes if response contains freshness info |
| DELETE | Deletes a resource | Yes | No | No |
*Can be called many times without different outcomes.
HTTP is an application layer protocol relying on lower-level protocols such as **TCP** and **UDP**.
#### Source(s) and further reading: HTTP
* [What is HTTP?](https://www.nginx.com/resources/glossary/http/)
* [Difference between HTTP and TCP](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)
* [Difference between PUT and PATCH](https://laracasts.com/discuss/channels/general-discussion/whats-the-differences-between-put-and-patch?page=1)
### Transmission control protocol (TCP)
<p align="center">
<img src="images/JdAsdvG.jpg">
<br/>
<i><a href=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>
TCP is a connection-oriented protocol over an [IP network](https://en.wikipedia.org/wiki/Internet_Protocol). Connection is established and terminated using a [handshake](https://en.wikipedia.org/wiki/Handshake_(computing)). All packets sent are guaranteed to reach the destination in the original order and without corruption through:
* Sequence numbers and [checksum fields](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation) for each packet
* [Acknowledgement](https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)) packets and automatic retransmission
If the sender does not receive a correct response, it will resend the packets. If there are multiple timeouts, the connection is dropped. TCP also implements [flow control](https://en.wikipedia.org/wiki/Flow_control_(data)) and [congestion control](https://en.wikipedia.org/wiki/Network_congestion#Congestion_control). These guarantees cause delays and generally result in less efficient transmission than UDP.
To ensure high throughput, web servers can keep a large number of TCP connections open, resulting in high memory usage. It can be expensive to have a large number of open connections between web server threads and say, a [memcached](https://memcached.org/) server. [Connection pooling](https://en.wikipedia.org/wiki/Connection_pool) can help in addition to switching to UDP where applicable.
TCP is useful for applications that require high reliability but are less time critical. Some examples include web servers, database info, SMTP, FTP, and SSH.
Use TCP over UDP when:
* You want the guaranteed delivery of your data
* You want your data to arrive in order to the destination
* You need all of the data to arrive intact
* You want to automatically make a best estimate use of the network throughput
### User datagram protocol (UDP)
<p align="center">
<img src="images/yzDrJtA.jpg">
<br/>
<i><a href=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>
UDP is connectionless. Datagrams (analogous to packets) are guaranteed only at the datagram level. Datagrams might reach their destination out of order or not at all. UDP does not support congestion control. Without the guarantees that TCP support, UDP is generally more efficient.
UDP can broadcast, sending datagrams to all devices on the subnet. This is useful with [DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) because the client has not yet received an IP address, thus preventing a way for TCP to stream without the IP address.
UDP is less reliable but works well in real time use cases such as VoIP, video chat, streaming, and realtime multiplayer games.
Use UDP over TCP when:
* You need the lowest latency
* You don't need guaranteed delivery of data
* You can accept out of order delivery of data
* Late data is worse than loss of data
* You want to implement your own error correction
#### Source(s) and further reading: TCP and UDP
* [Networking for game programming](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)
* [Key differences between TCP and UDP protocols](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)
* [Difference between TCP and UDP](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
* [Transmission control protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)
* [User datagram protocol](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [Scaling memcache at Facebook](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)
### Remote procedure call (RPC)
<p align="center">
<img src="images/iF4Mkb5.png">
<br/>
<i><a href=http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview>Source: Crack the system design interview</a></i>
</p>
In an RPC, a client causes a procedure to execute on a different address space, usually a remote server. The procedure is coded as if it were a local procedure call, abstracting away the details of how to communicate with the server from the client program. Remote calls are usually slower and less reliable than local calls so it is helpful to distinguish RPC calls from local calls. Popular RPC frameworks include [Protobuf](https://developers.google.com/protocol-buffers/), [Thrift](https://thrift.apache.org/), and [Avro](https://avro.apache.org/docs/current/).
RPC is a request-response protocol:
* **Client program** - Calls the client stub procedure. The parameters are pushed onto the stack like a local procedure call.
* **Client stub procedure** - Marshals (packs) procedure id and arguments into a request message.
* **Client communication module** - OS sends the message from the client to the server.
* **Server communication module** - OS passes the incoming packets to the server stub procedure.
* **Server stub procedure** - Unmarshalls the request, calls the server procedure matching the procedure id and passes the given arguments.
* The server response repeats the steps above in reverse order.
Sample RPC calls:
```text
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
```
RPC is focused on exposing behaviors. RPCs are often used for performance reasons with internal communications, as you can hand-craft native calls to better fit your use cases.
Choose a native library (aka SDK) when:
* You know your target platform.
* You want to control how your "logic" is accessed.
* You want to control how error control happens off your library.
* Performance and end user experience is your primary concern.
HTTP APIs following **REST** tend to be used more often for public APIs.
#### Disadvantage(s): RPC
* RPC clients become tightly coupled to the service implementation.
* A new API must be defined for every new operation or use case.
* It can be difficult to debug RPC.
* You might not be able to leverage existing technologies out of the box. For example, it might require additional effort to ensure [RPC calls are properly cached](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/) on caching servers such as [Squid](http://www.squid-cache.org/).
### Representational state transfer (REST)
REST is an architectural style enforcing a client/server model where the client acts on a set of resources managed by the server. The server provides a representation of resources and actions that can either manipulate or get a new representation of resources. All communication must be stateless and cacheable.
There are four qualities of a RESTful interface:
* **Identify resources (URI in HTTP)** - use the same URI regardless of any operation.
* **Change with representations (Verbs in HTTP)** - use verbs, headers, and body.
* **Self-descriptive error message (status response in HTTP)** - Use status codes, don't reinvent the wheel.
* **[HATEOAS](http://restcookbook.com/Basics/hateoas/) (HTML interface for HTTP)** - your web service should be fully accessible in a browser.
Sample REST calls:
```text
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
```
REST is focused on exposing data. It minimizes the coupling between client/server and is often used for public HTTP APIs. REST uses a more generic and uniform method of exposing resources through URIs, [representation through headers](https://github.com/for-GET/know-your-http-well/blob/master/headers.md), and actions through verbs such as GET, POST, PUT, DELETE, and PATCH. Being stateless, REST is great for horizontal scaling and partitioning.
#### Disadvantage(s): REST
* With REST being focused on exposing data, it might not be a good fit if resources are not naturally organized or accessed in a simple hierarchy. For example, returning all updated records from the past hour matching a particular set of events is not easily expressed as a path. With REST, it is likely to be implemented with a combination of URI path, query parameters, and possibly the request body.
* REST typically relies on a few verbs (GET, POST, PUT, DELETE, and PATCH) which sometimes doesn't fit your use case. For example, moving expired documents to the archive folder might not cleanly fit within these verbs.
* Fetching complicated resources with nested hierarchies requires multiple round trips between the client and server to render single views, e.g. fetching content of a blog entry and the comments on that entry. For mobile applications operating in variable network conditions, these multiple roundtrips are highly undesirable.
* Over time, more fields might be added to an API response and older clients will receive all new data fields, even those that they do not need, as a result, it bloats the payload size and leads to larger latencies.
### RPC and REST calls comparison
| Operation | RPC | REST |
|---|---|---|
| Signup | **POST** /signup | **POST** /persons |
| Resign | **POST** /resign<br/>{<br/>"personid": "1234"<br/>} | **DELETE** /persons/1234 |
| Read a person | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| Read a persons items list | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| Add an item to a persons items | **POST** /addItemToUsersItemsList<br/>{<br/>"personid": "1234";<br/>"itemid": "456"<br/>} | **POST** /persons/1234/items<br/>{<br/>"itemid": "456"<br/>} |
| Update an item | **POST** /modifyItem<br/>{<br/>"itemid": "456";<br/>"key": "value"<br/>} | **PUT** /items/456<br/>{<br/>"key": "value"<br/>} |
| Delete an item | **POST** /removeItem<br/>{<br/>"itemid": "456"<br/>} | **DELETE** /items/456 |
<p align="center">
<i><a href=https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/>Source: Do you really know why you prefer REST over RPC</a></i>
</p>
#### Source(s) and further reading: REST and RPC
* [Do you really know why you prefer REST over RPC](https://apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc/)
* [When are RPC-ish approaches more appropriate than REST?](http://programmers.stackexchange.com/a/181186)
* [REST vs JSON-RPC](http://stackoverflow.com/questions/15056878/rest-vs-json-rpc)
* [Debunking the myths of RPC and REST](https://web.archive.org/web/20170608193645/http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/)
* [What are the drawbacks of using REST](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)
* [Crack the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
* [Thrift](https://code.facebook.com/posts/1468950976659943/)
* [Why REST for internal use and not RPC](http://arstechnica.com/civis/viewtopic.php?t=1190508)
## Security
This section could use some updates. Consider [contributing](#contributing)!
Security is a broad topic. Unless you have considerable experience, a security background, or are applying for a position that requires knowledge of security, you probably won't need to know more than the basics:
* Encrypt in transit and at rest.
* 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).
### Source(s) and further reading
* [API security checklist](https://github.com/shieldfy/API-Security-Checklist)
* [Security guide for developers](https://github.com/FallibleInc/security-guide-for-developers)
* [OWASP top ten](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)
## Appendix
You'll sometimes be asked to do 'back-of-the-envelope' estimates. For example, you might need to determine how long it will take to generate 100 image thumbnails from disk or how much memory a data structure will take. The **Powers of two table** and **Latency numbers every programmer should know** are handy references.
### Powers of two table
```text
Power Exact Value Approx Value Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
```
#### Source(s) and further reading
* [Powers of two](https://en.wikipedia.org/wiki/Power_of_two)
### Latency numbers every programmer should know
```text
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
HDD seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from HDD 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
```
Handy metrics based on numbers above:
* Read sequentially from HDD at 30 MB/s
* Read sequentially from 1 Gbps Ethernet at 100 MB/s
* Read sequentially from SSD at 1 GB/s
* Read sequentially from main memory at 4 GB/s
* 6-7 world-wide round trips per second
* 2,000 round trips per second within a data center
#### Latency numbers visualized
![](https://web.archive.org/web/20200702021143im_/https://camo.githubusercontent.com/77f72259e1eb58596b564d1ad823af1853bc60a3/687474703a2f2f692e696d6775722e636f6d2f6b307431652e706e67)
#### Source(s) and further reading
* [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)
### Additional system design interview questions
> Common system design interview questions, with links to resources on how to solve each.
| Question | Reference(s) |
|---|---|
| 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)<br/>[youtube.com](https://www.youtube.com/watch?v=BKZxZwUgL3Y) |
| 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](https://web.archive.org/web/20170406065247/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 | [figshare.com](https://figshare.com/articles/Globally_distributed_content_delivery/6605972) |
| 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 | [cs.ucsb.edu](https://www.cs.ucsb.edu/sites/default/files/documents/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](https://web.archive.org/web/20180929181117/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) |
| Design a Stock Exchange (like NASDAQ or Binance) | [Jane Street](https://youtu.be/b1e4t2k2KJY)<br/>[Golang Implementation](https://around25.com/blog/building-a-trading-engine-for-a-crypto-exchange/)<br/>[Go Implementation](http://bhomnick.net/building-a-simple-limit-order-in-go/) |
| Design a Task Scheduler | [Codemia](https://codemia.io/system-design/design-a-task-scheduler/solutions/sc3c5j/My-Solution-for-Design-a-Task-Scheduler-with-Score-910) |
| Add a system design question | [Contribute](#contributing) |
### Real world architectures
> Articles on how real world systems are designed.
<p align="center">
<img src="images/TcUo2fw.png">
<br/>
<i><a href=https://www.infoq.com/presentations/Twitter-Timeline-Scalability>Source: Twitter timelines at scale</a></i>
</p>
**Don't focus on nitty gritty details for the following articles, instead:**
* Identify shared principles, common technologies, and patterns within these articles
* Study what problems are solved by each component, where it works, where it doesn't
* Review the lessons learned
|Type | System | Reference(s) |
|---|---|---|
| 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) |
| Data store | **BigQuery** - Distributed analytics from Google | [research.google.com](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36632.pdf) |
| | | |
| 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](http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.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) |
| Misc | **Dapper** - Distributed systems tracing infrastructure | [research.google.com](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf)
| Misc | **Kafka** - Pub/sub message queue from LinkedIn | [slideshare.net](http://www.slideshare.net/mumrah/kafka-talk-tri-hug) |
| Misc | **Zookeeper** - Centralized infrastructure and services enabling synchronization | [slideshare.net](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) |
| Misc | **Raft** - Distributed Consensus | [paper](https://raft.github.io/raft.pdf)<br/>[secret lives of data](http://thesecretlivesofdata.com/raft/) |
| | Add an architecture | [Contribute](#contributing) |
### Company architectures
Start with an overview of the architectures of well-known big tech companies: [System Design And Recommendation Algorithm Of 20 Big Companies](https://www.theinsaneapp.com/2021/03/system-design-and-recommendation-algorithms.html).
| Company | Reference(s) |
|---|---|
| Amazon | [Amazon architecture](http://highscalability.com/amazon-architecture) |
| Cinchcast | [Producing 1,500 hours of audio every day](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html) |
| DataSift | [Realtime datamining At 120,000 tweets per second](http://highscalability.com/blog/2011/11/29/datasift-architecture-realtime-datamining-at-120000-tweets-p.html) |
| Dropbox | [How we've scaled Dropbox](https://www.youtube.com/watch?v=PE4gwstWhmc) |
| 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: Facebooks 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/>[Facebooks photo storage](https://www.usenix.org/legacy/event/osdi10/tech/full_papers/Beaver.pdf)<br/>[How Facebook Live Streams To 800,000 Simultaneous Viewers](http://highscalability.com/blog/2016/6/27/how-facebook-live-streams-to-800000-simultaneous-viewers.html) |
| Flickr | [Flickr architecture](http://highscalability.com/flickr-architecture) |
| 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) |
| Netflix | [A 360 Degree View Of The Entire Netflix Stack](http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html)<br/>[Netflix: What Happens When You Press Play?](http://highscalability.com/blog/2017/12/11/netflix-what-happens-when-you-press-play.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) |
| PlentyOfFish | [PlentyOfFish architecture](http://highscalability.com/plentyoffish-architecture) |
| Salesforce | [How they handle 1.3 billion transactions a day](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html) |
| Stack Overflow | [Stack Overflow architecture](http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html) |
| TripAdvisor | [40M visitors, 200M dynamic page views, 30TB data](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.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)<br/>[How Twitter Handles 3,000 Images Per Second](http://highscalability.com/blog/2016/4/20/how-twitter-handles-3000-images-per-second.html) |
| Uber | [How Uber scales their real-time market platform](http://highscalability.com/blog/2015/9/14/how-uber-scales-their-real-time-market-platform.html)<br/>[Lessons Learned From Scaling Uber To 2000 Engineers, 1000 Services, And 8000 Git Repositories](http://highscalability.com/blog/2016/10/12/lessons-learned-from-scaling-uber-to-2000-engineers-1000-ser.html) |
| WhatsApp | [The WhatsApp architecture Facebook bought for $19 billion](http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html) |
| YouTube | [YouTube scalability](https://www.youtube.com/watch?v=w5WVu624fY8)<br/>[YouTube architecture](http://highscalability.com/youtube-architecture) |
### Company engineering blogs
> Architectures for companies you are interviewing with.
>
> Questions you encounter might be from the same domain.
* [Airbnb Engineering](http://nerds.airbnb.com/)
* [Atlassian Developers](https://developer.atlassian.com/blog/)
* [AWS Blog](https://aws.amazon.com/blogs/aws/)
* [Bitly Engineering Blog](http://word.bitly.com/)
* [Box Blogs](https://blog.box.com/blog/category/engineering)
* [Cloudera Developer Blog](http://blog.cloudera.com/)
* [Dropbox Tech Blog](https://tech.dropbox.com/)
* [Engineering at Quora](https://www.quora.com/q/quoraengineering)
* [Ebay Tech Blog](http://www.ebaytechblog.com/)
* [Evernote Tech Blog](https://blog.evernote.com/tech/)
* [Etsy Code as Craft](http://codeascraft.com/)
* [Facebook Engineering](https://www.facebook.com/Engineering)
* [Flickr Code](http://code.flickr.net/)
* [Foursquare Engineering Blog](https://location.foursquare.com/developer/blog/)
* [GitHub Engineering Blog](https://github.blog/category/engineering)
* [Google Research Blog](http://googleresearch.blogspot.com/)
* [Groupon Engineering Blog](https://engineering.groupon.com/)
* [Heroku Engineering Blog](https://engineering.heroku.com/)
* [Hubspot Engineering Blog](http://product.hubspot.com/blog/topic/engineering)
* [High Scalability](http://highscalability.com/)
* [Instagram Engineering](http://instagram-engineering.tumblr.com/)
* [Intel Software Blog](https://software.intel.com/en-us/blogs/)
* [Jane Street Tech Blog](https://blogs.janestreet.com/category/ocaml/)
* [LinkedIn Engineering](http://engineering.linkedin.com/blog)
* [Microsoft Engineering](https://engineering.microsoft.com/)
* [Microsoft Python Engineering](https://blogs.msdn.microsoft.com/pythonengineering/)
* [Netflix Tech Blog](http://techblog.netflix.com/)
* [Paypal Developer Blog](https://medium.com/paypal-engineering)
* [Pinterest Engineering Blog](https://medium.com/@Pinterest_Engineering)
* [Reddit Blog](http://www.redditblog.com/)
* [Salesforce Engineering Blog](https://developer.salesforce.com/blogs/engineering/)
* [Slack Engineering Blog](https://slack.engineering/)
* [Spotify Labs](https://labs.spotify.com/)
* [Stripe Engineering Blog](https://stripe.com/blog/engineering)
* [Twilio Engineering Blog](http://www.twilio.com/engineering)
* [Twitter Engineering](https://blog.twitter.com/engineering/)
* [Uber Engineering Blog](http://eng.uber.com/)
* [Yahoo Engineering Blog](http://yahooeng.tumblr.com/)
* [Yelp Engineering Blog](http://engineeringblog.yelp.com/)
* [Zynga Engineering Blog](https://www.zynga.com/blogs/engineering)
#### Source(s) and further reading
* [binhnguyennus/awesome-scalability](https://github.com/binhnguyennus/awesome-scalability)
Looking to add a blog? To avoid duplicating work, consider adding your company blog to the following repo:
* [kilimchoi/engineering-blogs](https://github.com/kilimchoi/engineering-blogs)
## Interview preparation resources
### Mock interviews
* [Meetapro - mock interviews with experienced FAANG interviewers](https://meetapro.com/?utm_source=sdpgithub)
## Under development
Interested in adding a section or helping complete one in-progress? [Contribute](#contributing)!
* Distributed computing with MapReduce
* Distributed system synchronization and consensus algorithms
* Consistent hashing
* Scatter gather
* [Contribute](#contributing)
## Credits
Credits and sources are provided throughout this repo.
Special thanks to:
* [Hired in tech](http://www.hiredintech.com/system-design/the-system-design-process/)
* [Cracking the coding interview](https://www.amazon.com/dp/0984782850/)
* [High scalability](http://highscalability.com/)
* [checkcheckzz/system-design-interview](https://github.com/checkcheckzz/system-design-interview)
* [shashank88/system_design](https://github.com/shashank88/system_design)
* [mmcgrana/services-engineering](https://github.com/mmcgrana/services-engineering)
* [System design cheat sheet](https://gist.github.com/vasanthk/485d1c25737e8e72759f)
* [A distributed systems reading list](http://dancres.github.io/Pages/)
* [Cracking the system design interview](http://www.puncsky.com/blog/2016-02-13-crack-the-system-design-interview)
## Contact info
Feel free to contact me to discuss any issues, questions, or comments.
My contact info can be found on my [GitHub page](https://github.com/donnemartin).
## License
*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).*
```text
Copyright 2017 Donne Martin
Creative Commons Attribution 4.0 International License (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/
```