← Courses Catalogue

English日本語简体中文繁體中文 | العَرَبِيَّة‎বাংলাPortuguês do BrasilDeutschελληνικάעבריתItaliano한국어فارسیPolskiрусский языкEspañolภาษาไทยTürkçetiếng ViệtFrançais | Add Translation

#システム設計入門


#動機・目的

大規模システムのシステム設計を学ぶ

システム設計面接課題に備える

#大規模システムの設計を学ぶ

スケーラブルなシステムのシステム設計を学ぶことは、より良いエンジニアになることに資するでしょう。

システム設計はとても広範なトピックを含みます。システム設計原理については インターネット上には膨大な量の文献が散らばっています。

このリポジトリは大規模システム構築に必要な知識を学ぶことができる 文献リストを体系的にまとめたもの です。

#オープンソースコミュニティから学ぶ

このプロジェクトは、これからもずっと更新されていくオープンソースプロジェクトの初期段階にすぎません。

Contributions は大歓迎です!

#システム設計面接課題に備える

コード技術面接に加えて、システム設計に関する知識は、多くのテック企業における 技術採用面接プロセス必要不可欠な要素 です。

システム設計面接での頻出質問に備え、自分の解答と模範解答:ディスカッション、コードそして図表などを比較して学びましょう。

面接準備に役立つその他のトピック:

#暗記カード


このAnki用フラッシュカードデッキ は、間隔反復を活用して、システム設計のキーコンセプトの学習を支援します。

外出先や移動中の勉強に役立つでしょう。

#コーディング技術課題用の問題: 練習用インタラクティブアプリケーション

コード技術面接用の問題を探している場合はこちら


姉妹リポジトリの Interactive Coding Challengesも見てみてください。追加の暗記デッキカードも入っています。

#コントリビュート

コミュニティから学ぶ

プルリクエスト等の貢献は積極的にお願いします:

現在、内容の改善が必要な作業中のコンテンツはこちらです。

コントリビュートの前にContributing Guidelinesを読みましょう。

#システム設計目次

賛否も含めた様々なシステム設計の各トピックの概要。 全てはトレードオフの関係にあります。

それぞれのセクションはより学びを深めるような他の文献へのリンクが貼られています。


#学習指針

学習スパンに応じてみるべきトピックス (short, medium, long)

Imgur

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では答えられない口頭質問)です。 自分で会話を組み立てることを求められます。

以下のステップに従って議論を組み立てることができるでしょう。この過程を確かなものにするために、次のセクションシステム設計課題例とその解答 を以下の指針に従って読み込むといいでしょう。

#ステップ 1: そのシステム使用例の概要、制約、推計値等を聞き出し、まとめる

システム仕様の要求事項を聞き出し、問題箇所を特定しましょう。使用例と制約を明確にするための質問を投げかけましょう。要求する推計値についても議論しておきましょう。

#ステップ 2: より高レベルのシステム設計を組み立てる

重要なコンポーネントを全て考慮した高レベルのシステム設計概要を組み立てる。

#ステップ 3: 核となるコンポーネントを設計する

それぞれの主要なコンポーネントについての詳細を学ぶ。例えば、url短縮サービスの設計を問われた際には次のようにするといいでしょう:

#ステップ 4: システム設計のスケール

与えられた制約条件からボトルネックとなりそうなところを割り出し、明確化する。 例えば、スケーラビリティの問題解決のために以下の要素を考慮する必要があるだろうか?

取りうる解決策とそのトレードオフについて議論をしよう。全てのことはトレードオフの関係にある。ボトルネックについてはスケーラブルなシステム設計の原理を読むといいでしょう。

#ちょっとした暗算問題

ちょっとした推計値を手計算ですることを求められることもあるかもしれません。補遺の以下の項目が役に立つでしょう:

#文献とその他の参考資料

以下のリンク先ページを見てどのような質問を投げかけられるか概要を頭に入れておきましょう:

#システム設計課題例とその解答

頻出のシステム設計面接課題と参考解答、コード及びダイアグラム

解答は solutions/ フォルダ以下にリンクが貼られている

問題
Pastebin.com (もしくは Bit.ly) を設計する 解答
Twitterタイムライン (もしくはFacebookフィード)を設計する
Twitter検索(もしくはFacebook検索)機能を設計する
解答
ウェブクローラーを設計する 解答
Mint.comを設計する 解答
SNSサービスのデータ構造を設計する 解答
検索エンジンのキー/バリュー構造を設計する 解答
Amazonのカテゴリ毎の売り上げランキングを設計する 解答
AWS上で100万人規模のユーザーを捌くサービスを設計する 解答
システム設計問題を追加する Contribute

#Pastebin.com (もしくは Bit.ly) を設計する

問題と解答を見る

Imgur

#Twitterタイムライン&検索 (もしくはFacebookフィード&検索)を設計する

問題と解答を見る

Imgur

#ウェブクローラーの設計

問題と解答を見る

Imgur

#Mint.comの設計

問題と解答を見る

Imgur

#SNSサービスのデータ構造を設計する

問題と解答を見る

Imgur

#検索エンジンのキー/バリュー構造を設計する

問題と解答を見る

Imgur

#Amazonのカテゴリ毎の売り上げランキングを設計する

問題と解答を見る

Imgur

#AWS上で100万人規模のユーザーを捌くサービスを設計する

問題と解答を見る

Imgur

#オブジェクト指向設計問題と解答

頻出のオブジェクト指向システム設計面接課題と参考解答、コード及びダイアグラム

解答は solutions/ フォルダ以下にリンクが貼られている

備考: このセクションは作業中です

問題
ハッシュマップの設計 解答
LRUキャッシュの設計 解答
コールセンターの設計 解答
カードのデッキの設計 解答
駐車場の設計 解答
チャットサーバーの設計 解答
円形配列の設計 Contribute
オブジェクト指向システム設計問題を追加する Contribute

#システム設計トピックス: まずはここから

システム設計の勉強は初めて?

まず初めに、よく使われる設計原理について、それらが何であるか、どのように用いられるか、長所短所について基本的な知識を得る必要があります

#ステップ 1: スケーラビリティに関する動画を観て復習する

Harvardでのスケーラビリティの講義

#ステップ 2: スケーラビリティに関する資料を読んで復習する

スケーラビリティ

#次のステップ

次に、ハイレベルでのトレードオフについてみていく:

全てはトレードオフの関係にあるというのを肝に命じておきましょう。

それから、より深い内容、DNSやCDNそしてロードバランサーなどについて学習を進めていきましょう。

#パフォーマンス vs スケーラビリティ

リソースが追加されるのにつれて パフォーマンス が向上する場合そのサービスは スケーラブル であると言えるでしょう。一般的に、パフォーマンスを向上させるというのはすなわち計算処理を増やすことを意味しますが、データセットが増えた時などより大きな処理を捌けるようになることでもあります。1

パフォーマンスvsスケーラビリティをとらえる他の考え方:

#その他の参考資料、ページ

#レイテンシー vs スループット

レイテンシー とはなにがしかの動作を行う、もしくは結果を算出するのに要する時間

スループット とはそのような動作や結果算出が単位時間に行われる回数

一般的に、 最大限のスループット許容範囲内のレイテンシー で実現することを目指すのが普通だ。

#その他の参考資料、ページ

#可用性 vs 一貫性

#CAP 理論


Source: CAP theorem revisited

分散型コンピュータシステムにおいては下の三つのうち二つまでしか同時に保証することはできない。:

ネットワークは信頼できないので、分断耐性は必ず保証しなければなりません。つまりソフトウェアシステムとしてのトレードオフは、一貫性を取るか、可用性を取るかを考えなければなりません。

#CP - 一貫性と分断耐性(consistency and partition tolerance)

分断されたノードからのレスポンスを待ち続けているとタイムアウトエラーに陥る可能性があります。CPはあなたのサービスがアトミックな読み書き(不可分操作)を必要とする際にはいい選択肢でしょう。

#AP - 可用性と分断耐性(availability and partition tolerance)

レスポンスはノード上にあるデータで最新のものを返します。つまり、最新版のデータが返されるとは限りません。分断が解消された後も、書き込みが反映されるのには時間がかかります。

結果整合性 を求めるサービスの際にはAPを採用するのがいいでしょう。もしくは、外部エラーに関わらずシステムが稼働する必要がある際にも同様です。

#その他の参考資料、ページ

#一貫性パターン

同じデータの複製が複数ある状態では、クライアントが一貫したデータ表示を受け取るために、どのようにそれらを同期すればいいのかという課題があります。 CAP 理論 における一貫性の定義を思い出してみましょう。全ての読み取りは最新の書き込みデータもしくはエラーを受け取るはずです。

#弱い一貫性

書き込み後の読み取りでは、その最新の書き込みを読めたり読めなかったりする。ベストエフォート型のアプローチに基づく。

このアプローチはmemcachedなどのシステムに見られます。弱い一貫性はリアルタイム性が必要なユースケース、例えばVoIP、ビデオチャット、リアルタイムマルチプレイヤーゲームなどと相性がいいでしょう。例えば、電話に出ているときに数秒間音声が受け取れなくなったとしたら、その後に接続が回復してもその接続が切断されていた間に話されていたことは聞き取れないというような感じです。

#結果整合性

書き込みの後、読み取りは最終的にはその結果を読み取ることができる(ミリ秒ほど遅れてというのが一般的です)。データは非同期的に複製されます。

このアプローチはDNSやメールシステムなどに採用されています。結果整合性は多くのリクエストを捌くサービスと相性がいいでしょう。

#強い一貫性

書き込みの後、読み取りはそれを必ず読むことができます。データは同期的に複製されます。

このアプローチはファイルシステムやRDBMSなどで採用されています。トランザクションを扱うサービスでは強い一貫性が必要でしょう。

#その他の参考資料、ページ

#可用性パターン

高い可用性を担保するには主に次の二つのパターンがあります: フェイルオーバーレプリケーション です。

#フェイルオーバー

#アクティブ・パッシブ

アクティブ・パッシブフェイルオーバーにおいては、周期信号はアクティブもしくはスタンバイ中のパッシブなサーバーに送られます。周期信号が中断された時には、パッシブだったサーバーがアクティブサーバーのIPアドレスを引き継いでサービスを再開します。

起動までのダウンタイムはパッシブサーバーが「ホット」なスタンバイ状態にあるか、「コールド」なスタンバイ状態にあるかで変わります。アクティブなサーバーのみがトラフィックを捌きます。

アクティブ・パッシブフェイルオーバーはマスター・スレーブフェイルオーバーと呼ばれることもあります。

#アクティブ・アクティブ

アクティブアクティブ構成では両方のサーバーがトラフィックを捌くことで負荷を分散します。

これらのサーバーがパブリックなものの場合、DNSは両方のサーバーのパブリックIPを知っている必要があります。もし、プライベートなものな場合、アプリケーションロジックが両方のサーバーの情報について知っている必要があります。

アクティブ・アクティブなフェイルオーバーはマスター・マスターフェイルオーバーと呼ばれることもあります。

#短所: フェイルオーバー

#レプリケーション

#マスター・スレーブ と マスター・マスター

このトピックは データベース セクションにおいてより詳細に解説されています:

#ドメインネームシステム


Source: DNS security presentation

ドメインネームシステム (DNS) は www.example.com などのドメインネームをIPアドレスへと翻訳します。

DNSは少数のオーソライズされたサーバーが上位に位置する階層的構造です。あなたのルーターもしくはISPは検索をする際にどのDNSサーバーに接続するかという情報を提供します。低い階層のDNSサーバーはその経路マップをキャッシュします。ただ、この情報は伝搬遅延によって陳腐化する可能性があります。DNSの結果はあなたのブラウザもしくはOSに一定期間(time to live (TTL)に設定された期間)キャッシュされます。

CloudFlareRoute 53 などのサービスはマネージドDNSサービスを提供しています。いくつかのDNSサービスでは様々な手法を使ってトラフィックを捌くことができます:

#欠点: DNS

#その他の参考資料、ページ

#コンテンツデリバリーネットワーク(Content delivery network)


Source: Why use a CDN

コンテンツデリバリーネットワーク(CDN)は世界中に配置されたプロキシサーバーのネットワークがユーザーに一番地理的に近いサーバーからコンテンツを配信するシステムのことです。AmazonのCloudFrontなどは例外的にダイナミックなコンテンツも配信しますが、一般的に、HTML/CSS/JS、写真、そして動画などの静的ファイルがCDNを通じて配信されます。そのサイトのDNSがクライアントにどのサーバーと交信するかという情報を伝えます。

CDNを用いてコンテンツを配信することで以下の二つの理由でパフォーマンスが劇的に向上します:

#プッシュCDN

プッシュCDNではサーバーデータに更新があった時には必ず、新しいコンテンツを受け取る方式です。コンテンツを用意し、CDNに直接アップロードし、URLをCDNを指すように指定するところまで、全て自分で責任を負う形です。コンテンツがいつ期限切れになるのか更新されるのかを設定することができます。コンテンツは新規作成時、更新時のみアップロードされることでトラフィックは最小化される一方、ストレージは最大限消費されてしまいます。

トラフィックの少ない、もしくは頻繁にはコンテンツが更新されないサイトの場合にはプッシュCDNと相性がいいでしょう。コンテンツは定期的に再びプルされるのではなく、CDNに一度のみ配置されます。

#プルCDN

プルCDNでは一人目のユーザーがリクエストした時に、新しいコンテンツをサービスのサーバーから取得します。コンテンツは自分のサーバーに保存して、CDNを指すURLを書き換えます。結果として、CDNにコンテンツがキャッシュされるまではリクエスト処理が遅くなります。

time-to-live (TTL) はコンテンツがどれだけの期間キャッシュされるかを規定します。プルCDNはCDN 上でのストレージスペースを最小化しますが、有効期限が切れたファイルが更新前にプルされてしまうことで冗長なトラフィックに繋がってしまう可能性があります。

大規模なトラフィックのあるサイトではプルCDNが相性がいいでしょう。というのも、トラフィックの大部分は最近リクエストされ、CDNに残っているコンテンツにアクセスするものであることが多いからです。

#欠点: CDN

#その他の参考資料、ページ

#ロードバランサー


Source: Scalable system design patterns

ロードバランサーは入力されるクライアントのリクエストをアプリケーションサーバーやデータベースへと分散させる。どのケースでもロードバランサーはサーバー等計算リソースからのレスポンスを適切なクライアントに返す。ロードバランサーは以下のことに効果的です:

ロードバランサーは (費用の高い) ハードウェアもしくはHAProxyなどのソフトウェアで実現できる。

他の利点としては:

障害に対応するために、アクティブ・パッシブ もしくは アクティブ・アクティブ モードのどちらにおいても、複数のロードバランサーを配置するのが一般的です。

ロードバランサーは以下のような種々のメトリックを用いてトラフィックルーティングを行うことができます:

#Layer 4 ロードバランシング

Layer 4 ロードバランサーは トランスポートレイヤー を参照してどのようにリクエストを配分するか判断します。一般的に、トランスポートレイヤーとしては、ソース、送信先IPアドレス、ヘッダーに記述されたポート番号が含まれますが、パケットの中身のコンテンツは含みません。 Layer 4 ロードバランサーはネットワークパケットを上流サーバーへ届け、上流サーバーから配信することでネットワークアドレス変換 Network Address Translation (NAT) を実現します。

#Layer 7 ロードバランシング

Layer 7 ロードバランサーは アプリケーションレイヤー を参照してどのようにリクエストを配分するか判断します。ヘッダー、メッセージ、クッキーなどのコンテンツのことです。Layer 7 ロードバランサーはネットワークトラフィックの終端を受け持ち メッセージを読み込み、ロードバランシングの判断をし、選択したサーバーとの接続を繋ぎます。例えば layer 7 ロードバランサーは動画のトラフィックを直接、そのデータをホストしているサーバーにつなぐと同時に、決済処理などのより繊細なトラフィックをセキュリティ強化されたサーバーに流すということもできる。

柔軟性とのトレードオフになりますが、 layer 4 ロードバランサーではLayer 7ロードバランサーよりも所要時間、計算リソースを少なく済ませることができます。ただし、昨今の汎用ハードウェアではパフォーマンスは最小限のみしか発揮できないでしょう。

#水平スケーリング

ロードバランサーでは水平スケーリングによってパフォーマンスと可用性を向上させることができます。手頃な汎用マシンを追加することによってスケールアウトさせる方が、一つのサーバーをより高価なマシンにスケールアップする(垂直スケーリング)より費用対効果も高くなり、結果的に可用性も高くなります。また、汎用ハードウェアを扱える人材を雇う方が、特化型の商用ハードウェアを扱える人材を雇うよりも簡単でしょう。

#欠点: 水平スケーリング

#欠点: ロードバランサー

#その他の参考資料、ページ

#リバースプロキシ(webサーバー)


Source: Wikipedia

リバースプロキシサーバーは内部サービスをまとめて外部に統一されたインターフェースを提供するウェブサーバーです。クライアントからのリクエストはそれに対応するサーバーに送られて、その後レスポンスをリバースプロキシがクライアントに返します。

他には以下のような利点があります:

#ロードバランサー vs リバースプロキシ

#欠点: リバースプロキシ

#その他の参考資料、ページ

#アプリケーション層


Source: Intro to architecting systems for scale

ウェブレイヤーをアプリケーション層 (プラットフォーム層とも言われる) と分離することでそれぞれの層を独立にスケール、設定することができるようになります。新しいAPIをアプリケーション層に追加する際に、不必要にウェブサーバーを追加する必要がなくなります。

単一責任の原則 では、小さい自律的なサービスが協調して動くように提唱しています。小さいサービスの小さいチームが急成長のためにより積極的な計画を立てられるようにするためです。

アプリケーション層は非同期処理もサポートします。

#マイクロサービス

独立してデプロイできる、小規模なモジュール様式であるマイクロサービスもこの議論に関係してくる技術でしょう。それぞれのサービスは独自のプロセスを処理し、明確で軽量なメカニズムで通信して、その目的とする機能を実現します。1

例えばPinterestでは以下のようなマイクロサービスに分かれています。ユーザープロフィール、フォロワー、フィード、検索、写真アップロードなどです。

#サービスディスカバリー

ConsulEtcdZookeeper などのシステムでは、登録されているサービスの名前、アドレス、ポートの情報を監視することで、サービス同士が互いを見つけやすくしています。サービスの完全性の確認には Health checks が便利で、これには HTTP エンドポイントがよく使われます。 Consul と Etcd のいずれも組み込みの key-value store を持っており、設定データや共有データなどのデータを保存しておくことに使われます。

#欠点: アプリケーション層

#その他の参考資料、ページ

#データベース


Source: Scaling up to your first 10 million users

#リレーショナルデータベースマネジメントシステム (RDBMS)

SQLなどのリレーショナルデータベースはテーブルに整理されたデータの集合である。

ACID はリレーショナルデータベースにおけるトランザクションのプロパティの集合である

リレーショナルデータベースをスケールさせるためにはたくさんの技術がある: マスター・スレーブ レプリケーションマスター・マスター レプリケーションfederationシャーディング非正規化、 そして SQL チューニング

#マスタースレーブ レプリケーション

マスターデータベースが読み取りと書き込みを処理し、書き込みを一つ以上のスレーブデータベースに複製します。スレーブデータベースは読み取りのみを処理します。スレーブデータベースは木構造のように追加のスレーブにデータを複製することもできます。マスターデータベースがオフラインになった場合には、いずれかのスレーブがマスターに昇格するか、新しいマスターデータベースが追加されるまでは読み取り専用モードで稼働します。


Source: Scalability, availability, stability, patterns

#欠点: マスタースレーブ レプリケーション

#マスターマスター レプリケーション

いずれのマスターも読み取り書き込みの両方に対応する。書き込みに関してはそれぞれ協調する。いずれかのマスターが落ちても、システム全体としては読み書き両方に対応したまま運用できる。


Source: Scalability, availability, stability, patterns

#欠点: マスターマスター レプリケーション
#欠点: レプリケーション
#その他の参考資料、ページ: レプリケーション

#Federation


Source: Scaling up to your first 10 million users

フェデレーション (もしくは機能分割化とも言う) はデータベースを機能ごとに分割する。例えば、モノリシックな単一データベースの代わりに、データベースを フォーラムユーザープロダクト のように三つにすることで、データベース一つあたりの書き込み・読み取りのトラフィックが減り、その結果レプリケーションのラグも短くなります。データベースが小さくなることで、メモリーに収まるデータが増えます。キャッシュの局所性が高まるため、キャッシュヒット率も上がります。単一の中央マスターで書き込みを直列化したりしないため、並列で書き込みを処理することができ、スループットの向上が期待できます。

#欠点: federation
#その他の参考資料、ページ: federation

#シャーディング


Source: Scalability, availability, stability, patterns

シャーディングでは異なるデータベースにそれぞれがデータのサブセット断片のみを持つようにデータを分割します。ユーザーデータベースを例にとると、ユーザー数が増えるにつれてクラスターにはより多くの断片が加えられることになります。

federationの利点に似ていて、シャーディングでは読み書きのトラフィックを減らし、レプリケーションを減らし、キャッシュヒットを増やすことができます。インデックスサイズも減らすことができます。一般的にはインデックスサイズを減らすと、パフォーマンスが向上しクエリ速度が速くなります。なにがしかのデータを複製する機能がなければデータロスにつながりますが、もし、一つのシャードが落ちても、他のシャードが動いていることになります。フェデレーションと同じく、単一の中央マスターが書き込みの処理をしなくても、並列で書き込みを処理することができ、スループットの向上が期待できます。

ユーザーテーブルをシャードする一般的な方法は、ユーザーのラストネームイニシャルでシャードするか、ユーザーの地理的配置でシャードするなどです。

#欠点: シャーディング
#その他の参考資料、ページ: シャーディング

#非正規化

非正規化では、書き込みのパフォーマンスをいくらか犠牲にして読み込みのパフォーマンスを向上させようとします。計算的に重いテーブルの結合などをせずに、複数のテーブルに冗長なデータのコピーが書き込まれるのを許容します。いくつかのRDBMS例えば、PostgreSQL やOracleはこの冗長な情報を取り扱い、一貫性を保つためのmaterialized views という機能をサポートしています。

フェデレーションシャーディングなどのテクニックによってそれぞれのデータセンターに分配されたデータを合一させることはとても複雑な作業です。非正規化によってそのような複雑な処理をしなくて済むようになります。

多くのシステムで、100対1あるいは1000対1くらいになるくらい読み取りの方が、書き込みのトラフィックよりも多いことでしょう。読み込みを行うために、複雑なデータベースのジョイン処理が含まれるものは計算的に高価につきますし、ディスクの処理時間で膨大な時間を費消してしまうことになります。

#欠点: 非正規化
#その他の参考資料、ページ: 非正規化

#SQLチューニング

SQLチューニングは広範な知識を必要とする分野で多くの が書かれています。

ボトルネックを明らかにし、シミュレートする上で、 ベンチマーク を定め、 プロファイル することはとても重要です。

ベンチマークとプロファイルをとることで以下のような効率化の選択肢をとることになるでしょう。

#スキーマを絞る
#インデックスを効果的に用いる
#高負荷なジョインを避ける
#テーブルのパーティション
#クエリキャッシュを調整する
#その他の参考資料、ページ: SQLチューニング

#NoSQL

NoSQL は key-value storedocument-storewide column store、 もしくは graph databaseによって表現されるデータアイテムの集合です。データは一般的に正規化されておらず、アプリケーション側でジョインが行われます。大部分のNoSQLは真のACIDトランザクションを持たず、 結果整合性 的な振る舞いの方を好みます。

BASE はしばしばNoSQLデータベースのプロパティを説明するために用いられます。CAP Theorem と対照的に、BASEは一貫性よりも可用性を優先します。

SQLか?NoSQLか? を選択するのに加えて、どのタイプのNoSQLがどの使用例に最も適するかを理解するのはとても有益です。このセクションでは キーバリューストアドキュメントストアワイドカラムストア、 と グラフデータベース について触れていきます。

#キーバリューストア

概要: ハッシュテーブル

キーバリューストアでは一般的にO(1)の読み書きができ、それらはメモリないしSSDで裏付けられています。データストアはキーを 辞書的順序 で保持することでキーの効率的な取得を可能にしています。キーバリューストアではメタデータを値とともに保持することが可能です。

キーバリューストアはハイパフォーマンスな挙動が可能で、単純なデータモデルやインメモリーキャッシュレイヤーなどのデータが急速に変わる場合などに使われます。単純な処理のみに機能が制限されているので、追加の処理機能が必要な場合にはその複雑性はアプリケーション層に載せることになります。

キーバリューストアはもっと複雑なドキュメントストアや、グラフデータベースなどの基本です。

#その他の参考資料、ページ: キーバリューストア

#ドキュメントストア

概要: ドキュメントがバリューとして保存されたキーバリューストア

ドキュメントストアはオブジェクトに関する全ての情報を持つドキュメント(XML、 JSON、 binaryなど)を中心に据えたシステムです。ドキュメントストアでは、ドキュメント自身の内部構造に基づいた、APIもしくはクエリ言語を提供します。 メモ:多くのキーバリューストアでは、値のメタデータを扱う機能を含んでいますが、そのことによって二つドキュメントストアとの境界線が曖昧になってしまっています。

以上のことを実現するために、ドキュメントはコレクション、タグ、メタデータやディレクトリなどとして整理されています。ドキュメント同士はまとめてグループにできるものの、それぞれで全く異なるフィールドを持つ可能性があります。

MongoDBCouchDB などのドキュメントストアも、複雑なクエリを処理するためのSQLのような言語を提供しています。DynamoDB はキーバリューとドキュメントの両方をサポートしています。

ドキュメントストアは高い柔軟性を担保するので、頻繁に変化するデータを扱う時に用いられます。

#その他の参考資料、ページ: ドキュメントストア

#ワイドカラムストア


Source: SQL & NoSQL, a brief history

概要: ネストされたマップ カラムファミリー<行キー、 カラム<ColKey、 Value、 Timestamp>>

ワイドカラムストアのデータの基本単位はカラム(ネーム・バリューのペア)です。それぞれのカラムはカラムファミリーとして(SQLテーブルのように)グループ化することができます。スーパーカラムファミリーはカラムファミリーの集合です。それぞれのカラムには行キーでアクセスすることができます。同じ行キーを持つカラムは同じ行として認識されます。それぞれの値は、バージョン管理とコンフリクトが起きた時のために、タイムスタンプを含みます。

GoogleはBigtableを初のワイドカラムストアとして発表しました。それがオープンソースでHadoopなどでよく使われるHBase やFacebookによるCassandra などのプロジェクトに影響を与えました。BigTable、HBaseやCassandraなどのストアはキーを辞書形式で保持することで選択したキーレンジでのデータ取得を効率的にします。

ワイドカラムストアは高い可用性とスケーラビリティを担保します。これらはとても大規模なデータセットを扱うことによく使われます。

#その他の参考資料、ページ: ワイドカラムストア

#グラフデータベース


Source: Graph database

概要: グラフ

グラフデータベースでは、それぞれのノードがレコードで、それぞれのアークは二つのノードを繋ぐ関係性として定義されます。グラフデータベースは多数の外部キーや多対多などの複雑な関係性を表すのに最適です。

グラフデータベースはSNSなどのサービスの複雑な関係性モデルなどについて高いパフォーマンスを発揮します。比較的新しく、まだ一般的には用いられていないので、開発ツールやリソースを探すのが他の方法に比べて難しいかもしれません。多くのグラフはREST APIsを通じてのみアクセスできます。

#その他の参考資料、ページ: グラフ

#その他の参考資料、ページ: NoSQL

#SQLか?NoSQLか?


Source: Transitioning from RDBMS to NoSQL

SQL を選ぶ理由:

NoSQL を選ぶ理由:

NoSQLに適するサンプルデータ:

#その他の参考資料、ページ:  SQLもしくはNoSQL

#キャッシュ


Source: Scalable system design patterns

キャッシュはページの読み込み時間を削減し、サーバーやデータベースへの負荷を低減することができます。このモデルでは、実際の処理を保存するために、ディスパッチャーがまず以前にリクエストが送信されたかどうかを確認し、直前の結果を受け取ります。

データベースはそのパーティションに渡って統合された読み取り書き込みの分配を要求しますが、人気アイテムはその分配を歪めてシステム全体のボトルネックになってしまうことがあります。データベースの前にキャッシュを差し込むことでこのように、均一でない負荷やトラフィックの急激な増加を吸収することができます。

#クライアントキャッシング

キャッシュはOSやブラウザーなどのクライアントサイド、サーバーサイド もしくは独立のキャッシュレイヤーに設置することができます。

#CDNキャッシング

CDN もキャッシュの一つとして考えることができます。

#Webサーバーキャッシング

リバースプロキシVarnish などのキャッシュは静的そして動的なコンテンツを直接配信することができます。 webサーバーもリクエストをキャッシュしてアプリケーションサーバーに接続することなしにレスポンスを返すことができます。

#データベースキャッシング

データベースは普通、一般的な使用状況に適するようなキャッシングの設定を初期状態で持っています。この設定を特定の仕様に合わせて調整することでパフォーマンスを向上させることができます。

#アプリケーションキャッシング

メムキャッシュなどのIn-memoryキャッシュやRedisはアプリケーションとデータストレージの間のキーバリューストアです。データはRAMで保持されるため、データがディスクで保存される一般的なデータベースよりもだいぶ速いです。RAM容量はディスクよりも限られているので、least recently used (LRU)などのcache invalidation アルゴリズムが 'コールド' なエントリを弾き、'ホット' なデータをRAMに保存します。

Redisはさらに以下のような機能を備えています:

キャッシュには様々なレベルのものがありますが、いずれも大きく二つのカテゴリーのいずれかに分類することができます: データベースクエリオブジェクト です:

一般的に、ファイルベースキャッシングはクローンを作り出してオートスケーリングを難しくしてしまうので避けるべきです。

#データベースクエリレベルでのキャッシング

データベースをクエリする際には必ずクエリをキーとしてハッシュして結果をキャッシュに保存しましょう。この手法はキャッシュ期限切れ問題に悩むことになります:

#オブジェクトレベルでのキャッシング

データをアプリケーションコードでそうするように、オブジェクトとして捉えてみましょう。アプリケーションに、データベースからのデータセットをクラスインスタンスやデータ構造として組み立てさせます。:

何をキャッシュするか:

#いつキャッシュを更新するか

キャッシュに保存できる容量は限られているため、自分のケースではどのキャッシュ手法が一番いいかは検討する必要があります。

#キャッシュアサイド


Source: From cache to in-memory data grid

アプリケーションはストレージへの読み書きの処理をします。キャッシュはストレージとは直接やりとりをしません。アプリケーションは以下のことをします:

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 は通常このように使われる。

その後のキャッシュデータ読み込みは速いです。キャッシュアサイドはレージーローディングであるとも言われます。リクエストされたデータのみがキャッシュされ、リクエストされていないデータでキャッシュが溢れるのを防止します。

#欠点: キャッシュアサイド

#ライトスルー


Source: Scalability, availability, stability, patterns

アプリケーションはキャッシュをメインのデータストアとして使い、そこにデータの読み書きを行います。一方、キャッシュはデータベースへの読み書きを担当します。

アプリケーションコード:

set_user(12345, {"foo":"bar"})

キャッシュコード:

def set_user(user_id, values):
    user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
    cache.set(user_id, user)

ライトスルーは書き込み処理のせいで全体としては遅いオペレーションですが、書き込まれたばかりのデータに関する読み込みは速いです。ユーザー側は一般的にデータ更新時の方が読み込み時よりもレイテンシーに許容的です。キャッシュ内のデータは最新版で保たれます。

#欠点: ライトスルー

#ライトビハインド (ライトバック)


Source: Scalability, availability, stability, patterns

ライトビハインドではアプリケーションは以下のことをします:

#欠点: ライトビハインド

#リフレッシュアヘッド


Source: From cache to in-memory data grid

期限切れよりも前に、直近でアクセスされた全てのキャッシュエントリを自動的に更新するように設定することができます。

もしどのアイテムが将来必要になるのかを正確に予測することができるのならば、リードスルーよりもレイテンシーを削減することができます。

#欠点: リフレッシュアヘッド

#欠点: キャッシュ

#その他の参考資料、ページ

#非同期処理


Source: Intro to architecting systems for scale

非同期のワークフローはもし、連続的に行われるとリクエスト時間を圧迫してしまうような重い処理を別で処理する手法です。また、定期的にデータを集合させるなどの時間がかかるような処理を前もって処理しておくことにも役立ちます。

#メッセージキュー

メッセージキューはメッセージを受け取り、保存し、配信します。もし、処理がインラインで行うには遅すぎる場合、以下のようなワークフローでメッセージキューを用いるといいでしょう:

ユーザーの処理が止まることはなく、ジョブはバックグラウンドで処理されます。この間に、クライアントはオプションとして、タスクが完了したかのように見せるために小規模の処理を行います。例えば、ツイートを投稿するときに、ツイートはすぐにあなたのタイムラインに反映されたように見えますが、そのツイートが実際に全てのフォロワーに配信されるまでにはもう少し時間がかかっているでしょう。

Redis はシンプルなメッセージ仲介としてはいいですが、メッセージが失われてしまう可能性があります。

RabbitMQ はよく使われていますが、'AMQP'プロトコルに対応して、自前のノードを立てる必要があります。

Amazon SQS という選択肢もありますが、レイテンシーが高く、メッセージが重複して配信されてしまう可能性があります。

#タスクキュー

タスクキューはタスクとその関連するデータを受け取り、処理した上でその結果を返します。スケジュール管理をできるほか、バックグラウンドでとても重いジョブをこなすこともできます。

Celery はスケジューリングとpythonのサポートがあります。

#バックプレッシャー

もし、キューが拡大しすぎると、メモリーよりもキューの方が大きくなりキャッシュミスが起こり、ディスク読み出しにつながり、パフォーマンスが低下することにつながります。バックプレッシャーはキューサイズを制限することで回避することができ、高いスループットを確保しキューにすでにあるジョブについてのレスポンス時間を短縮できます。キューがいっぱいになると、クライアントはサーバービジーもしくはHTTP 503をレスポンスとして受け取りまた後で時間をおいてアクセスするようにメッセージを受け取ります。クライアントはexponential backoffなどによって後ほど再度時間を置いてリクエストすることができます。

#欠点: 非同期処理

#その他の参考資料、ページ

#通信


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はTCPUDP などの低級プロトコルに依存しているアプリケーションレイヤーのプロトコルである。

#その他の参考資料、ページ: HTTP

#伝送制御プロトコル (TCP)


Source: How to make a multiplayer game

TCPはIP networkの上で成り立つ接続プロトコルです。接続はhandshakeによって開始、解除されます。全ての送信されたパケットは欠損なしで送信先に送信された順番で到達するように以下の方法で保証されています:

もし送信者が正しいレスポンスを受け取らなかったとき、パケットを再送信します。複数のタイムアウトがあったとき、接続は解除されます。TCP はフロー制御輻輳制御も実装しています。これらの機能によって速度は低下し、一般的にUDPよりも非効率な転送手段になっています。

ハイスループットを実現するために、ウェブサーバーはかなり大きな数のTCP接続を開いておくことがあり、そのことでメモリー使用が圧迫されます。ウェブサーバスレッドと例えばmemcached サーバーの間で多数のコネクションを保っておくことは高くつくかもしれません。可能なところではUDPに切り替えるだけでなくコネクションプーリングなども役立つかもしれません。

TCPは高い依存性を要し、時間制約が厳しくないものに適しているでしょう。ウェブサーバー、データベース情報、SMTP、FTPやSSHなどの例に適用されます。

以下の時にUDPよりもTCPを使うといいでしょう:

#ユーザデータグラムプロトコル (UDP)


Source: How to make a multiplayer game

UDPはコネクションレスです。データグラム(パケットのようなもの)はデータグラムレベルでの保証しかされません。データグラムは順不同で受け取り先に到着したりそもそも着かなかったりします。UDPは輻輳制御をサポートしません。TCPにおいてはサポートされているこれらの保証がないため、UDPは一般的に、TCPよりも効率的です。

UDPはサブネット上のすべての機器にデータグラムを送信することができます。これはDHCP において役に立ちます。というのも、クライアントはまだIPアドレスを取得していないので、IPアドレスを必要とするTCPによるストリームができないからです。

UDPは信頼性の面では劣りますが、VoIP、ビデオチャット、ストリーミングや同時通信マルチプレイヤーゲームなどのリアルタイム性が重視される時にはとても効果的です。

TCPよりもUDPを使うのは:

#その他の参考資料、ページ: TCP と UDP

#遠隔手続呼出 (RPC)


Source: Crack the system design interview

RPCではクライアントがリモートサーバーなどの異なるアドレス空間でプロシージャーが処理されるようにします。プロシージャーはローカルでのコールのように、クライアントからサーバーにどのように通信するかという詳細を省いた状態でコードが書かれます。リモートのコールは普通、ローカルのコールよりも遅く、信頼性に欠けるため、RPCコールをローカルコールと区別させておくことが好ましいでしょう。人気のRPCフレームワークは以下です。ProtobufThriftAvro

RPC は リクエストレスポンスプロトコル:

Sample RPC calls:

GET /someoperation?data=anId

POST /anotheroperation
{
  "data":"anId";
  "anotherdata": "another value"
}

RPCは振る舞いを公開することに焦点を当てています。RPCは内部通信パフォーマンスを理由として使われることが多いです。というのも、使用する状況に合わせてネイティブコールを自作することができるからです。

ネイティブライブラリー (aka SDK) を呼ぶのは以下の時:

REST プロトコルに従うHTTP APIはパブリックAPIにおいてよく用いられます。

#欠点: RPC

#Representational state transfer (REST)

RESTは、クライアントがサーバーによってマネージされるリソースに対して処理を行うクライアント・サーバーモデルを支持するアーキテキチャスタイルです。サーバーは操作できるもしくは新しいリソースレプレゼンテーションを受け取ることができるようなリソースやアクションのレプレゼンテーションを提供します。すべての通信はステートレスでキャッシュ可能でなければなりません。

RESTful なインターフェースには次の四つの特徴があります:

サンプル REST コール:

GET /someresources/anId

PUT /someresources/anId
{"anotherdata": "another value"}

RESTはデータを公開することに焦点を当てています。クライアントとサーバーのカップリングを最小限にするもので、パブリックAPIなどによく用いられます。RESTはURI、 representation through headers、そして、GET、POST、PUT、 DELETE、PATCHなどのHTTP動詞等のよりジェネリックで統一されたメソッドを用います。ステートレスであるのでRESTは水平スケーリングやパーティショニングに最適です。

#欠点: REST

#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

#セキュリティ

このセクションは更新が必要です。contributingしてください!

セキュリティは幅広いトピックです。十分な経験、セキュリティ分野のバックグラウンドがなくても、セキュリティの知識を要する職に応募するのでない限り、基本以上のことを知る必要はないでしょう。

#その他の参考資料、ページ:

#補遺

暗算で、推計値を求める必要があることも時にはあります。例えば、ディスクから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

#その他の参考資料、ページ:

#全てのプログラマーが知るべきレイテンシー値

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

上記表に基づいた役に立つ数値:

#レイテンシーの視覚的表

#その他の参考資料、ページ:

#他のシステム設計面接例題

頻出のシステム設計面接課題とその解答へのリンク

質問 解答
Dropboxのようなファイル同期サービスを設計する youtube.com
Googleのような検索エンジンの設計 queue.acm.org
stackexchange.com
ardendertat.com
stanford.edu
Googleのようなスケーラブルなwebクローラーの設計 quora.com
Google docsの設計 code.google.com
neil.fraser.name
Redisのようなキーバリューストアの設計 slideshare.net
Memcachedのようなキャッシュシステムの設計 slideshare.net
Amazonのようなレコメンデーションシステムの設計 hulu.com
ijcai13.org
BitlyのようなURL短縮サービスの設計 n00tc0d3r.blogspot.com
WhatsAppのようなチャットアプリの設計 highscalability.com
Instagramのような写真共有サービスの設計 highscalability.com
highscalability.com
Facebookニュースフィードの設計 quora.com
quora.com
slideshare.net
Facebookタイムラインの設計 facebook.com
highscalability.com
Facebookチャットの設計 erlang-factory.com
facebook.com
Facebookのようなgraph検索の設計 facebook.com
facebook.com
facebook.com
CloudFlareのようなCDNの設計 cmu.edu
Twitterのトレンド機能の設計 michael-noll.com
snikolov .wordpress.com
ランダムID発行システムの設計 blog.twitter.com
github.com
一定のインターバル時間での上位k件を返す ucsb.edu
wpi.edu
複数のデータセンターからデータを配信するサービスの設計 highscalability.com
オンラインの複数プレイヤーカードゲームの設計 indieflashblog.com
buildnewgames.com
ガーベッジコレクションシステムの設計 stuffwithstuff.com
washington.edu
システム設計例題を追加する Contribute

#実世界のアーキテクチャ

世の中のシステムがどのように設計されているかについての記事


Source: Twitter timelines at scale

以下の記事の重箱の隅をつつくような細かい詳細にこだわらないこと。むしろ

種類 システム 参考ページ
データ処理 MapReduce - Googleの分散データ処理システム research.google.com
データ処理 Spark - Databricksの分散データ処理システム slideshare.net
データ処理 Storm - Twitterの分散データ処理システム slideshare.net
データストア Bigtable - Googleのカラム指向分散データベース harvard.edu
データストア HBase - Bigtableのオープンソース実装 slideshare.net
データストア Cassandra - Facebookのカラム指向分散データベース slideshare.net
データストア DynamoDB - Amazonのドキュメント指向分散データベース harvard.edu
データストア MongoDB - ドキュメント指向分散データベース slideshare.net
データストア Spanner - Googleのグローバル分散データベース research.google.com
データストア Memcached - 分散メモリーキャッシングシステム slideshare.net
データストア Redis - 永続性とバリュータイプを兼ね備えた分散メモリーキャッシングシステム slideshare.net
ファイルシステム Google File System (GFS) - 分散ファイルシステム research.google.com
ファイルシステム Hadoop File System (HDFS) - GFSのオープンソース実装 apache.org
Misc Chubby - 疎結合の分散システムをロックするGoogleのサービス research.google.com
Misc Dapper - 分散システムを追跡するインフラ research.google.com
Misc Kafka - LinkedInによるPub/subメッセージキュー slideshare.net
Misc Zookeeper - 同期を可能にする中央集権インフラとサービス slideshare.net
アーキテクチャを追加する Contribute

#各企業のアーキテクチャ

企業 参考ページ
Amazon Amazon architecture
Cinchcast Producing 1,500 hours of audio every day
DataSift Realtime datamining At 120,000 tweets per second
DropBox How we've scaled Dropbox
ESPN Operating At 100,000 duh nuh nuhs per second
Google Google architecture
Instagram 14 million users, terabytes of photos
What powers Instagram
Justin.tv Justin.Tv's live video broadcasting architecture
Facebook Scaling memcached at Facebook
TAO: Facebook’s distributed data store for the social graph
Facebook’s photo storage
Flickr Flickr architecture
Mailbox From 0 to one million users in 6 weeks
Pinterest From 0 To 10s of billions of page views a month
18 million visitors, 10x growth, 12 employees
Playfish 50 million monthly users and growing
PlentyOfFish PlentyOfFish architecture
Salesforce How they handle 1.3 billion transactions a day
Stack Overflow Stack Overflow architecture
TripAdvisor 40M visitors, 200M dynamic page views, 30TB data
Tumblr 15 billion page views a month
Twitter Making Twitter 10000 percent faster
Storing 250 million tweets a day using MySQL
150M active users, 300K QPS, a 22 MB/S firehose
Timelines at scale
Big and small data at Twitter
Operations at Twitter: scaling beyond 100 million users
Uber How Uber scales their real-time market platform
WhatsApp The WhatsApp architecture Facebook bought for $19 billion
YouTube YouTube scalability
YouTube architecture

#企業のエンジニアブログ

面接を受ける企業のアーキテクチャ

投げられる質問は同じ分野から来ることもあるでしょう

#その他の参考資料、ページ:

ここにあるリストは比較的小規模なものにとどめ、kilimchoi/engineering-blogsにより詳細に記すことで重複しないようにしておくことにする。エンジニアブログへのリンクを追加する場合はここではなく、engineering-blogsレボジトリに追加することを検討してください。

#進行中の作業

セクションの追加や、進行中の作業を手伝っていただける場合はこちら!

#クレジット

クレジット及び、参照ページは適時このリポジトリ内に記載してあります

Special thanks to:

#Contact info

Feel free to contact me to discuss any issues, questions, or comments.

My contact info can be found on my GitHub page.

#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/