)
- [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 サーバー)
Source: Wikipedia
リバースプロキシサーバーは内部サービスをまとめて外部に統一されたインターフェースを提供するウェブサーバーです。クライアントからのリクエストはそれに対応するサーバーに送られて、その後レスポンスをリバースプロキシがクライアントに返します。
他には以下のような利点があります:
- **より堅牢なセキュリティ** - バックエンドサーバーの情報を隠したり、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)
## アプリケーション層
Source: Intro to architecting systems for scale
ウェブレイヤーをアプリケーション層 (プラットフォーム層とも言われる) と分離することでそれぞれの層を独立にスケール、設定することができるようになります。新しい API をアプリケーション層に追加する際に、不必要にウェブサーバーを追加する必要がなくなります。
**単一責任の原則** では、小さい自律的なサービスが協調して動くように提唱しています。小さいサービスの小さいチームが急成長のためにより積極的な計画を立てられるようにするためです。
アプリケーション層は[非同期処理](#非同期処理)もサポートします。
### マイクロサービス
独立してデプロイできる、小規模なモジュール様式である[マイクロサービス](https://en.wikipedia.org/wiki/Microservices)もこの議論に関係してくる技術でしょう。それぞれのサービスは独自のプロセスを処理し、明確で軽量なメカニズムで通信して、その目的とする機能を実現します。1
例えば 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/)
## データベース
Source: Scaling up to your first 10 million users
### リレーショナルデータベースマネジメントシステム (RDBMS)
SQL などのリレーショナルデータベースはテーブルに整理されたデータの集合である。
**ACID** はリレーショナルデータベースにおける[トランザクション](https://en.wikipedia.org/wiki/Database_transaction)のプロパティの集合である
- **不可分性** - それぞれのトランザクションはあるかないかのいずれかである
- **一貫性** - どんなトランザクションもデータベースをある確かな状態から次の状態に遷移させる。
- **独立性** - 同時にトランザクションを処理することは、連続的にトランザクションを処理するのと同じ結果をもたらす。
- **永続性** - トランザクションが処理されたら、そのように保存される
リレーショナルデータベースをスケールさせるためにはたくさんの技術がある: **マスター・スレーブ レプリケーション**、 **マスター・マスター レプリケーション**、 **federation**、 **シャーディング**、 **非正規化**、 そして **SQL チューニング**
#### マスタースレーブ レプリケーション
マスターデータベースが読み取りと書き込みを処理し、書き込みを一つ以上のスレーブデータベースに複製します。スレーブデータベースは読み取りのみを処理します。スレーブデータベースは木構造のように追加のスレーブにデータを複製することもできます。マスターデータベースがオフラインになった場合には、いずれかのスレーブがマスターに昇格するか、新しいマスターデータベースが追加されるまでは読み取り専用モードで稼働します。
Source: Scalability, availability, stability, patterns
##### 欠点: マスタースレーブ レプリケーション
- スレーブをマスターに昇格させるには追加のロジックが必要になる。
- マスタースレーブ レプリケーション、マスターマスター レプリケーションの **両方** の欠点は[欠点: レプリケーション](#欠点-マスタースレーブ-レプリケーション)を参照
#### マスターマスター レプリケーション
いずれのマスターも読み取り書き込みの両方に対応する。書き込みに関してはそれぞれ協調する。いずれかのマスターが落ちても、システム全体としては読み書き両方に対応したまま運用できる。
Source: Scalability, availability, stability, patterns
##### 欠点: マスターマスター レプリケーション
- ロードバランサーを導入するか、アプリケーションロジックを変更することでどこに書き込むかを指定しなければならない。
- 大体のマスターマスターシステムは、一貫性が緩い(ACID 原理を守っていない)もしくは、同期する時間がかかるために書き込みのレイテンシーが増加してしまっている。
- 書き込みノードが追加され、レイテンシーが増加するにつれ書き込みの衝突の可能性が増える。
- マスタースレーブ レプリケーション、マスターマスター レプリケーションの **両方** の欠点は[欠点: レプリケーション](#欠点-マスタースレーブ-レプリケーション) を参照
##### 欠点: レプリケーション
- 新しいデータ書き込みを複製する前にマスターが落ちた場合にはそのデータが失われてしまう可能性がある。
- 書き込みは読み取りレプリカにおいてリプレイされる。書き込みが多い場合、複製ノードが書き込みの処理のみで行き詰まって、読み取りの処理を満足に行えない可能性がある。
- 読み取りスレーブノードの数が多ければ多いほど、複製しなければならない数も増え、複製時間が伸びてしまいます。
- システムによっては、マスターへの書き込みはマルチスレッドで並列処理できる一方、スレーブへの複製は単一スレッドで連続的に処理しなければならない場合があります。
- レプリケーションでは追加のハードウェアが必要になり、複雑性も増します。
##### その他の参考資料、ページ: レプリケーション
- [スケーラビリティ、 可用性、 スタビリティ パターン](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)
- [マルチマスター レプリケーション](https://en.wikipedia.org/wiki/Multi-master_replication)
#### Federation
Source: Scaling up to your first 10 million users
フェデレーション (もしくは機能分割化とも言う) はデータベースを機能ごとに分割する。例えば、モノリシックな単一データベースの代わりに、データベースを **フォーラム**、 **ユーザー**、 **プロダクト** のように三つにすることで、データベース一つあたりの書き込み・読み取りのトラフィックが減り、その結果レプリケーションのラグも短くなります。データベースが小さくなることで、メモリーに収まるデータが増えます。キャッシュの局所性が高まるため、キャッシュヒット率も上がります。単一の中央マスターで書き込みを直列化したりしないため、並列で書き込みを処理することができ、スループットの向上が期待できます。
##### 欠点: 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=w95murBkYmU)
#### シャーディング
Source: Scalability, availability, stability, patterns
シャーディングでは異なるデータベースにそれぞれがデータのサブセット断片のみを持つようにデータを分割します。ユーザーデータベースを例にとると、ユーザー数が増えるにつれてクラスターにはより多くの断片が加えられることになります。
[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)
- [シャードデータベースアーキテクチャ]()
- [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)
#### ワイドカラムストア
Source: SQL & NoSQL, a brief history
> 概要: ネストされたマップ `カラムファミリー<行キー、 カラム>`
ワイドカラムストアのデータの基本単位はカラム(ネーム・バリューのペア)です。それぞれのカラムはカラムファミリーとして(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)
#### グラフデータベース
Source: Graph database
> 概要: グラフ
グラフデータベースでは、それぞれのノードがレコードで、それぞれのアークは二つのノードを繋ぐ関係性として定義されます。グラフデータベースは多数の外部キーや多対多などの複雑な関係性を表すのに最適です。
グラフデータベースは 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)
- [スケーラビリティ](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 か?
Source: Transitioning from RDBMS to NoSQL
**SQL** を選ぶ理由:
- 構造化されたデータ
- 厳格なスキーマ
- リレーショナルデータ
- 複雑なジョインをする必要性
- トランザクション
- スケールする際のパターンが明確なとき
- 開発者の数、コミュニティ、コード等がより充実している
- インデックスによるデータ探索はとても速い
**NoSQL** を選ぶ理由:
- 準構造化されたデータ
- ダイナミックないし、フレキシブルなスキーマ
- ノンリレーショナルなデータ
- 複雑なジョインをする必要がない
- データの多くの TB (もしくは PB) を保存する
- 集中的、大規模なデータ負荷に耐えられる
- IOPS については極めて高いスループットを示す
NoSQL に適するサンプルデータ:
- 急激なクリックストリームやログデータの収集
- リーダーボードやスコアリングデータ
- ショッピングカートなどの一時的情報
- 頻繁にアクセスされる ('ホットな') テーブル
- メタデータやルックアップテーブル
##### その他の参考資料、ページ: SQL もしくは NoSQL
- [最初の 1000 万ユーザーにスケールアップするために](https://www.youtube.com/watch?v=w95murBkYmU)
- [SQL と NoSQL の違い](https://www.sitepoint.com/sql-vs-nosql-differences/)
## キャッシュ
Source: Scalable system design patterns
キャッシュはページの読み込み時間を削減し、サーバーやデータベースへの負荷を低減することができます。このモデルでは、実際の処理を保存するために、ディスパッチャーがまず以前にリクエストが送信されたかどうかを確認し、直前の結果を受け取ります。
データベースはそのパーティションに渡って統合された読み取り書き込みの分配を要求しますが、人気アイテムはその分配を歪めてシステム全体のボトルネックになってしまうことがあります。データベースの前にキャッシュを差し込むことでこのように、均一でない負荷やトラフィックの急激な増加を吸収することができます。
### クライアントキャッシング
キャッシュは 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
一般的に、ファイルベースキャッシングはクローンを作り出してオートスケーリングを難しくしてしまうので避けるべきです。
### データベースクエリレベルでのキャッシング
データベースをクエリする際には必ずクエリをキーとしてハッシュして結果をキャッシュに保存しましょう。この手法はキャッシュ期限切れ問題に悩むことになります:
- 複雑なクエリによりキャッシュされた結果を削除することが困難
- テーブルセルなどのデータ断片が変化した時に、その変化したセルを含むかもしれない全てのキャッシュされたクエリを削除する必要がある。
### オブジェクトレベルでのキャッシング
データをアプリケーションコードでそうするように、オブジェクトとして捉えてみましょう。アプリケーションに、データベースからのデータセットをクラスインスタンスやデータ構造として組み立てさせます。:
- そのデータが変更されたら、オブジェクトをキャッシュから削除すること
- 非同期処理を許容します: ワーカーがキャッシュされたオブジェクトの中で最新のものを集めてきます
何をキャッシュするか:
- ユーザーのセッション
- 完全にレンダーされたウェブページ
- アクテビティストリーム
- ユーザーグラフデータ
### いつキャッシュを更新するか
キャッシュに保存できる容量は限られているため、自分のケースではどのキャッシュ手法が一番いいかは検討する必要があります。
#### キャッシュアサイド
Source: From cache to in-memory data grid
アプリケーションはストレージへの読み書きの処理をします。キャッシュはストレージとは直接やりとりをしません。アプリケーションは以下のことをします:
- キャッシュの中のエントリを参照しますが、結果としてキャッシュミスになります
- データベースからエントリを取得します
- エントリをキャッシュに追加します
- エントリを返します
```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)を設定することでキャッシュエントリの更新を強制的に行う、もしくはライトスルーを採用することでこの問題は緩和できます。
- ノードが落ちると、新規の空のノードで代替されることでレイテンシーが増加することになります。
#### ライトスルー
Source: Scalability, availability, stability, patterns
アプリケーションはキャッシュをメインのデータストアとして使い、そこにデータの読み書きを行います。一方、キャッシュはデータベースへの読み書きを担当します。
- アプリケーションはキャッシュにあるエントリを追加・更新します
- キャッシュは同期的にデータストアに書き込みを行います
- エントリを返します
アプリケーションコード:
```
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 によって圧縮することができます。
#### ライトビハインド (ライトバック)
Source: Scalability, availability, stability, patterns
ライトビハインドではアプリケーションは以下のことをします:
- キャッシュのエントリーを追加・更新します
- データストアへの書き込みを非同期的に行うことで、書き込みパフォーマンスを向上させます。
##### 欠点: ライトビハインド
- キャッシュがデータストア内のコンテンツにヒットする前にキャッシュが落ちるとデータ欠損が起きる可能性があります。
- キャッシュアサイドやライトスルーよりも実装が複雑になります。
#### リフレッシュアヘッド
Source: From cache to in-memory data grid
期限切れよりも前に、直近でアクセスされた全てのキャッシュエントリを自動的に更新するように設定することができます。
もしどのアイテムが将来必要になるのかを正確に予測することができるのならば、リードスルーよりもレイテンシーを削減することができます。
##### 欠点: リフレッシュアヘッド
- どのアイテムが必要になるかの予測が正確でない場合にはリフレッシュアヘッドがない方がレイテンシーは良いという結果になってしまいます。
### 欠点: キャッシュ
- [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/)
- [スケーラビリティ](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)
- [AWS ElastiCache のストラテジー](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/Strategies.html)
- [Wikipedia]()
## 非同期処理
Source: Intro to architecting systems for scale
非同期のワークフローはもし、連続的に行われるとリクエスト時間を圧迫してしまうような重い処理を別で処理する手法です。また、定期的にデータを集合させるなどの時間がかかるような処理を前もって処理しておくことにも役立ちます。
### メッセージキュー
メッセージキューはメッセージを受け取り、保存し、配信します。もし、処理がインラインで行うには遅すぎる場合、以下のようなワークフローでメッセージキューを用いるといいでしょう:
- アプリケーションはジョブをキューに配信し、ユーザーにジョブステータスを伝えます。
- ワーカーがジョブキューから受け取って、処理を行い、終了したらそのシグナルを返します。
ユーザーの処理が止まることはなく、ジョブはバックグラウンドで処理されます。この間に、クライアントはオプションとして、タスクが完了したかのように見せるために小規模の処理を行います。例えば、ツイートを投稿するときに、ツイートはすぐにあなたのタイムラインに反映されたように見えますが、そのツイートが実際に全てのフォロワーに配信されるまでにはもう少し時間がかかっているでしょう。
**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)
## 通信
Source: OSI 7 layer model
### 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)
Source: How to make a multiplayer game
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]()パケットと自動再送信
もし送信者が正しいレスポンスを受け取らなかったとき、パケットを再送信します。複数のタイムアウトがあったとき、接続は解除されます。TCP は[フロー制御]() と [輻輳制御](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)
Source: How to make a multiplayer game
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)
Source: Crack the system design interview
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 コールが正しくキャッシュ](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
{
"personid": "1234"
} | **DELETE** /persons/1234 |
| Person 読み込み | **GET** /readPerson?personid=1234 | **GET** /persons/1234 |
| Person のアイテムリスト読み込み | **GET** /readUsersItemsList?personid=1234 | **GET** /persons/1234/items |
| Person のアイテムへのアイテム追加 | **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 |
Source: Do you really know why you prefer REST over RPC
#### その他の参考資料、ページ: 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](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)の原理を用いる
### その他の参考資料、ページ:
- [開発者のためのセキュリティガイド](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://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)
[stackexchange.com](http://programmers.stackexchange.com/questions/38324/interview-question-how-would-you-implement-google-search)
[ardendertat.com](http://www.ardendertat.com/2012/01/11/implementing-search-engines/)
[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/)
[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 のような 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)
[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)
[quora.com](http://www.quora.com/Activity-Streams/What-are-the-scaling-issues-to-keep-in-mind-while-developing-a-social-network-feed)
[slideshare.net](http://www.slideshare.net/danmckinley/etsy-activity-feeds-architecture) |
| Facebook タイムラインの設計 | [facebook.com](https://www.facebook.com/note.php?note_id=10150468255628920)
[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)
[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)
[facebook.com](https://www.facebook.com/notes/facebook-engineering/under-the-hood-indexing-and-ranking-in-graph-search/10151361720763920)
[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/)
[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)
[github.com](https://github.com/twitter/snowflake/) |
| 一定のインターバル時間での上位 k 件を返す | [ucsb.edu](https://icmi.cs.ucsb.edu/research/tech_reports/reports/2005-23.pdf)
[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)
[buildnewgames.com](http://buildnewgames.com/real-time-multiplayer/) |
| ガーベッジコレクションシステムの設計 | [stuffwithstuff.com](http://journal.stuffwithstuff.com/2013/12/08/babys-first-garbage-collector/)
[washington.edu](http://courses.cs.washington.edu/courses/csep521/07wi/prj/rick.pdf) |
| システム設計例題を追加する | [Contribute](#contributing) |
### 実世界のアーキテクチャ
> 世の中のシステムがどのように設計されているかについての記事
Source: Twitter timelines at scale
**以下の記事の重箱の隅をつつくような細かい詳細にこだわらないこと。むしろ**
- 共通の原理、技術、パターンを探ること
- それぞれのコンポーネントでどんな問題が解決され、コンポーネントはどこでうまく使えもしくは使えないかを知ること
- 学んだことを復習すること
| 種類 | システム | 参考ページ |
| ---------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| データ処理 | **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)
[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)
[TAO: Facebook’s distributed data store for the social graph](https://cs.uwaterloo.ca/~brecht/courses/854-Emerging-2014/readings/data-store/tao-facebook-distributed-datastore-atc-2013.pdf)
[Facebook’s 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)
[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)
[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)
[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)
[Timelines at scale](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)
[Big and small data at Twitter](https://www.youtube.com/watch?v=5cKTP36HVgI)
[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)
[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://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/)
- [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/