system-design-primer - 大規模なシステムの設計方法を学びます。システム設計面接の準備をします。Ankiフラッシュカードが含まれています。

(Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.)

Created at: 2017-02-27 00:15:28
Language: Python
License: NOASSERTION

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

このガイドの翻訳を手伝ってください!

システム設計入門


モチベーション

大規模なシステムの設計方法を学びます。

システム設計面接の準備をします。

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

スケーラブルなシステムの設計方法を学ぶことは、より良いエンジニアになるのに役立ちます。

システム設計は幅広いトピックです。システム設計の原則に関する膨大な量のリソースがウェブ上に散在しています。

このリポジトリは、大規模にシステムを構築する方法を学ぶのに役立つリソースの体系的なコレクションです。

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

これは継続的に更新されるオープンソースプロジェクトです。

貢献は大歓迎です!

システム設計面接の準備

インタビューのコーディングに加えて、システム設計は多くのハイテク企業における技術インタビュープロセスの必須コンポーネントです。

一般的なシステム設計のインタビューの質問を練習し、その結果をサンプルソリューション(ディスカッション、コード、ダイアグラム)と比較します。

面接準備のための追加トピック:

アンキフラッシュカード


付属のAnkiフラッシュカードデッキは、間隔を空けた繰り返しを使用して、主要なシステム設計コンセプトを維持するのに役立ちます。

外出先での使用に最適です。

コーディングリソース:インタラクティブなコーディングの課題

コーディングインタビューの準備に役立つリソースをお探しですか?


追加のAnkiデッキを含む姉妹レポインタラクティブコーディングチャレンジをチェックしてください:

貢献

コミュニティから学ぶ。

お気軽にプルリクエストを送信してお手伝いします。

  • エラーの修正
  • セクションの改善
  • 新しいセクションの追加
  • 翻訳

多少の磨きが必要なコンテンツは開発中です。

寄稿ガイドラインを確認してください。

システム設計トピックの索引

長所と短所を含むさまざまなシステム設計トピックの概要。すべてはトレードオフです

各セクションには、より詳細なリソースへのリンクが含まれています。


学習ガイド

面接のタイムライン(ショート、ミディアム、ロング)に基づいて確認するトピックの提案。

イムグル

Q: 面接の場合、ここですべてを知る必要がありますか?

A: いいえ、面接の準備をするために、ここですべてを知る必要はありません

面接で尋ねられる内容は、次のような変数によって異なります。

  • 経験値
  • あなたの技術的背景は何ですか?
  • 面接対象の職種
  • どの企業と面接しているか

より経験豊富な候補者は、一般的にシステム設計についてもっと知っていることが期待されます。アーキテクトやチームリーダーは、個々の貢献者よりも多くのことを知っていることが期待されるかもしれません。トップテクノロジー企業は、1回以上のデザイン面接ラウンドを行う可能性が高いです。

広く始め、いくつかの分野でより深く行きます。さまざまな重要なシステム設計トピックについて少し知っておくと役立ちます。タイムライン、経験、面接するポジション、面接する企業に基づいて、次のガイドを調整します。

  • 短いタイムライン - システム設計のトピックで幅を目指します。面接の質問を解いて練習します。
  • 中程度のタイムライン - システム設計のトピックで幅と深さを目指します。多くの面接の質問を解いて練習します。
  • 長いタイムライン - システム設計のトピックで広さと深さを目指します。ほとんどの面接の質問を解いて練習してください。
短い 中程度 長い
システム設計のトピックを読んで、システムの仕組みを幅広く理解する 👍 👍 👍
あなたがインタビューしている企業の会社のエンジニアリングブログのいくつかの記事を読んでください 👍 👍 👍
いくつかの現実世界のアーキテクチャを読む 👍 👍 👍
システム設計の面接の質問へのアプローチ方法を確認する 👍 👍 👍
システム設計のインタビューの質問とソリューションの作業 多い 最も
オブジェクト指向設計のインタビューの質問とソリューションの作業 多い 最も
追加のシステム設計に関するインタビューの質問を確認する 多い 最も

システム設計面接の質問へのアプローチ方法

システム設計の面接の質問にどのように取り組むか。

システム設計のインタビューは、自由回答式の会話です。あなたはそれを導くことが期待されています。

次の手順を使用して、ディスカッションをガイドできます。このプロセスを固めるには、次の手順を使用して、「ソリューションに関するシステム設計のインタビューの質問」セクションを実行します。

ステップ 1: ユース ケース、制約、および前提条件を概説する

要件を収集し、問題の範囲を絞り込みます。ユースケースと制約を明確にするために質問をします。前提条件について話し合う。

  • 誰がそれを使用するつもりですか?
  • 彼らはそれをどのように使用するつもりですか?
  • ユーザーは何人いますか?
  • システムは何をしますか?
  • システムの入力と出力は何ですか?
  • どのくらいのデータを処理する予定ですか?
  • 1 秒あたりの要求数はいくつですか?
  • 予想される読み取り/書き込み比率はどのくらいですか。

ステップ 2: 高レベルの設計を作成する

すべての重要なコンポーネントを含む高レベルの設計を概説します。

  • 主要構成部品と接続をスケッチする
  • アイデアを正当化する

ステップ 3: コア コンポーネントを設計する

各コアコンポーネントの詳細について説明します。たとえば、URL 短縮サービスの設計を依頼された場合は、次の点について説明します。

  • 完全なURLのハッシュを生成して保存する
    • MD5 および Base62
    • ハッシュ衝突
    • SQL または NoSQL
    • データベーススキーマ
  • ハッシュされたURLを完全なURLに変換する
    • データベース検索
  • API とオブジェクト指向の設計

ステップ 4: 設計をスケーリングする

制約を考慮してボトルネックを特定し、対処します。たとえば、スケーラビリティの問題に対処するために次のものが必要ですか。

  • ロードバランサー
  • 水平スケーリング
  • キャッシング
  • データベースのシャーディング

潜在的な解決策とトレードオフについて話し合う。すべてがトレードオフです。スケーラブルなシステム設計の原則を使用してボトルネックに対処します。

エンベロープの裏側計算

あなたは手作業でいくつかの見積もりをするように求められます。以下のリソースについては、付録を参照してください。

出典と参考文献

次のリンクをチェックして、何を期待すべきかをよりよく理解してください。

システム設計面接の質問とソリューション

一般的なシステム設計のインタビューの質問と、サンプルのディスカッション、コード、および図。

フォルダー内のコンテンツにリンクされたソリューション。

solutions/

質問
デザイン Pastebin.com(または Bit.ly) 解決
Twitter のタイムラインと検索 (または Facebook フィードと検索) をデザインする 解決
Web クローラーの設計 解決
デザイン Mint.com 解決
ソーシャル ネットワークのデータ構造を設計する 解決
検索エンジンのキーと値のストアを設計する 解決
Amazonの売上ランキングをカテゴリ別にデザインする機能 解決
AWS 上の何百万人ものユーザーに拡張できるシステムを設計する 解決
システム設計に関する質問を追加する 貢献する

デザイン Pastebin.com(または Bit.ly)

エクササイズとソリューションを見る

イムグル

Twitter のタイムラインと検索 (または Facebook フィードと検索) をデザインする

エクササイズとソリューションを見る

イムグル

Web クローラーの設計

エクササイズとソリューションを見る

イムグル

デザイン Mint.com

エクササイズとソリューションを見る

イムグル

ソーシャル ネットワークのデータ構造を設計する

エクササイズとソリューションを見る

イムグル

検索エンジンのキーと値のストアを設計する

エクササイズとソリューションを見る

イムグル

Amazonの売上ランキングをカテゴリ別にデザインする機能

エクササイズとソリューションを見る

イムグル

AWS 上の何百万人ものユーザーに拡張できるシステムを設計する

エクササイズとソリューションを見る

イムグル

オブジェクト指向設計のインタビューでソリューションに関する質問

一般的なオブジェクト指向設計のインタビューの質問と、サンプルのディスカッション、コード、および図。

フォルダー内のコンテンツにリンクされたソリューション。

solutions/

注: このセクションは開発中です。

質問
ハッシュマップの設計 解決
最も使用頻度の低いキャッシュを設計する 解決
コール センターを設計する 解決
カードのデッキをデザインする 解決
駐車場をデザインする 解決
チャットサーバーを設計する 解決
円形配列を設計する 貢献する
オブジェクト指向の設計に関する質問を追加する 貢献する

システム設計のトピック: ここから始める

システム設計は初めてですか?

まず、一般的な原則の基本的な理解、それらが何であるか、それらがどのように使用されているか、そしてそれらの長所と短所について学ぶ必要があります。

ステップ 1: スケーラビリティのビデオ講義を確認する

ハーバード大学でのスケーラビリティ講演会

  • カバーされるトピック:
    • 垂直スケーリング
    • 水平スケーリング
    • キャッシング
    • 負荷分散
    • データベースのレプリケーション
    • データベース・パーティション

手順 2: スケーラビリティに関する記事を確認する

拡張性

次のステップ

次に、大まかなトレードオフを見ていきます。

  • パフォーマンススケーラビリティ
  • レイテンシスループット
  • 可用性一貫性

すべてがトレードオフであることに注意してください。

次に、DNS、CDN、ロードバランサーなどのより具体的なトピックについて説明します。

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

サービスは、追加されたリソースに比例した方法でパフォーマンスが向上する場合、スケーラブルです。一般に、パフォーマンスの向上は、より多くの作業単位を処理することを意味しますが、データセットが大きくなる場合など、より大きな作業単位を処理することもできます。1

パフォーマンスとスケーラビリティを見るもう1つの方法:

  • パフォーマンスに問題がある場合、システムは 1 人のユーザーに対して低速です。
  • スケーラビリティーに問題がある場合、システムは 1 人のユーザーにとっては高速ですが、高負荷では低速です。

出典と参考文献

レイテンシとスループット

レイテンシは、何らかのアクションを実行したり、何らかの結果を生成したりする時間です。

スループットは、単位時間あたりのアクションまたは結果の数です。

一般に、許容可能な待機時間で最大のスループットを目指す必要があります。

出典と参考文献

可用性と一貫性

CAP定理


出典:CAP定理再考

分散コンピューター・システムでは、以下の保証のうち 2 つしかサポートできません。

  • 整合性 - すべての読み取りで最新の書き込みまたはエラーを受け取る
  • 可用性 - すべての要求は、最新バージョンの情報が含まれているという保証なしに、応答を受信します。
  • パーティション許容度 - ネットワーク障害による任意のパーティション分割にもかかわらず、システムは動作し続けます

ネットワークは信頼できないため、パーティションの許容範囲をサポートする必要があります。一貫性と可用性の間にソフトウェアのトレードオフを行う必要があります。

CP - 整合性とパーティション許容範囲

パーティション分割されたノードからの応答を待機すると、タイムアウト・エラーが発生する可能性があります。CPは、ビジネスニーズにアトミックな読み取りと書き込みが必要な場合に適しています。

AP - 可用性とパーティション許容範囲

応答は、どのノードでも使用可能な最も容易に使用可能なバージョンのデータを返しますが、これは最新ではない可能性があります。書き込みは、パーティションの解決時に伝搬に時間がかかる場合があります。

AP は、ビジネスで最終的な一貫性を確保する必要がある場合や、外部エラーがあってもシステムが動作し続ける必要がある場合に適しています。

出典と参考文献

整合性パターン

同じデータの複数のコピーでは、クライアントがデータの一貫したビューを持つように、それらを同期する方法に関するオプションに直面しています。CAP定理からの一貫性の定義を思い出してください - すべての読み取りは最新の書き込みまたはエラーを受け取ります。

弱い一貫性

書き込み後、読み取りはそれを見ることも、見えないこともあります。ベスト エフォート アプローチが取られます。

このアプローチは、memcached などのシステムで見られます。一貫性の弱さは、VoIP、ビデオチャット、リアルタイムマルチプレイヤーゲームなどのリアルタイムユースケースでうまく機能します。たとえば、通話中に数秒間受信を失った場合、接続を回復すると、接続が失われたときに話された内容が聞こえません。

最終的な一貫性

書き込み後、読み取りは最終的に (通常はミリ秒以内に) それを認識します。データは非同期的にレプリケートされます。

このアプローチは、DNSや電子メールなどのシステムで見られます。最終的な整合性は、高可用性システムでうまく機能します。

強力な一貫性

書き込み後、読み取りはそれを見ます。データは同期的にレプリケートされます。

このアプローチは、ファイル・システムやRDBMSで見られます。強力な一貫性は、トランザクションを必要とするシステムでうまく機能します。

出典と参考文献

可用性パターン

高可用性をサポートするには、フェールオーバーレプリケーションという 2 つの補完的なパターンがあります。

フェイルオーバー

アクティブ/パッシブ

アクティブ/パッシブ・フェイルオーバーでは、ハートビートはスタンバイ時にアクティブ・サーバーとパッシブ・サーバーの間で送信されます。ハートビートが中断されると、パッシブサーバーはアクティブの IP アドレスを引き継ぎ、サービスを再開します。

ダウンタイムの長さは、パッシブサーバーが既に「ホット」スタンバイで実行されているかどうか、または「コールド」スタンバイから起動する必要があるかどうかによって決まります。アクティブなサーバーのみがトラフィックを処理します。

アクティブ/パッシブ フェールオーバーは、マスター/スレーブ フェールオーバーとも呼ばれます。

アクティブ-アクティブ

アクティブ/アクティブでは、両方のサーバーがトラフィックを管理し、両者の間で負荷を分散します。

サーバーがパブリックフェイスの場合、DNS は両方のサーバーのパブリック IP について知る必要があります。サーバーが内部を向いている場合、アプリケーション ロジックは両方のサーバーについて認識する必要があります。

アクティブ/アクティブ・フェイルオーバーは、マスター/マスター・フェイルオーバーとも呼ばれます。

短所: フェールオーバー

  • フェールオーバーにより、ハードウェアが増し、複雑さが増します。
  • 新しく書き込まれたデータをパッシブに複製する前にアクティブ・システムに障害が発生すると、データが失われる可能性があります。

複製

マスター-スレーブとマスター-マスター

このトピックについては、「データベース」セクションで詳しく説明します。

数での可用性

可用性は、多くの場合、サービスが利用可能な時間の割合として稼働時間 (またはダウンタイム) によって定量化されます。可用性は通常、9 の数で測定されます。99.99% の可用性を持つサービスは、4 つの 9 を持つと記述されます。

99.9%の可用性(3つの9秒)

期間 許容できるダウンタイム
年間ダウンタイム 8時間45分57秒
1 か月あたりのダウンタイム 43メートル49.7秒
1週間あたりのダウンタイム 10メートル4.8秒
1 日あたりのダウンタイム 1メートル26.4秒

99.99%の可用性(4つの9)

期間 許容できるダウンタイム
年間ダウンタイム 52分 35.7秒
1 か月あたりのダウンタイム 4m 23s
1週間あたりのダウンタイム 1メートル5秒
1 日あたりのダウンタイム 8.6秒

並列とシーケンスでの可用性

サービスが障害を起こしやすい複数のコンポーネントで構成されている場合、サービスの全体的な可用性は、コンポーネントが順番に並んでいるか並列になっているかによって異なります。

順番に

可用性が 100% の 2 つのコンポーネントが順番に<ると、全体的な可用性が低下します。

Availability (Total) = Availability (Foo) * Availability (Bar)

両方とそれぞれが 99.9% の可用性を持つ場合、順番に合計可用性は 99.8% になります。

Foo
Bar

並行して

全体的な可用性は、可用性が 100% < 2 つのコンポーネントが並列にある場合に増加します。

Availability (Total) = 1 - (1 - Availability (Foo)) * (1 - Availability (Bar))

両方とそれぞれが 99.9% の可用性を持つ場合、並列での合計可用性は 99.9999% になります。

Foo
Bar

ドメインネームシステム


ソース: DNS セキュリティのプレゼンテーション

ドメイン ネーム システム (DNS) は、www.example.com などのドメイン名を IP アドレスに変換します。

DNS は階層的であり、最上位レベルにいくつかの権限のあるサーバーがあります。ルーターまたは ISP は、ルックアップを実行するときにどの DNS サーバーに接続するかに関する情報を提供します。低レベルの DNS サーバーはマッピングをキャッシュします。これは、DNS 伝搬の遅延により古くなる可能性があります。DNSの結果は、存続時間(TTL)によって決定される一定期間、ブラウザまたはOSによってキャッシュされることもあります。

  • NS レコード (ネームサーバー) - ドメイン/サブドメインの DNS サーバーを指定します。
  • MX レコード (メール交換) - メッセージを受け入れるメールサーバーを指定します。
  • レコード (アドレス) - IP アドレスに名前を指定します。
  • CNAME (正規) - 名前を別の名前または (example.com に www.example.com) またはレコードにポイントします。
    CNAME
    A

CloudFlareRoute 53 などのサービスは、マネージド DNS サービスを提供します。一部の DNS サービスは、さまざまな方法でトラフィックをルーティングできます。

短所: DNS

  • DNS サーバーにアクセスすると、わずかな遅延が発生しますが、上記のキャッシュによって軽減されます。
  • DNSサーバーの管理は複雑になる可能性があり、通常は政府、ISP、および大企業によって管理されています
  • DNSサービスは最近DDoS攻撃を受けており、ユーザーがTwitterのIPアドレスを知らずにTwitterなどのWebサイトにアクセスするのを妨げています。

出典と参考文献

コンテンツ配信ネットワーク


ソース: CDN を使用する理由

コンテンツ配信ネットワーク (CDN) は、プロキシ サーバーのグローバルに分散されたネットワークであり、ユーザーに近い場所からコンテンツを提供します。一般に、HTML/CSS/JS、写真、ビデオなどの静的ファイルはCDNから提供されますが、AmazonのCloudFrontなどの一部のCDNは動的コンテンツをサポートしています。サイトのDNS解決は、どのサーバーに接続するかをクライアントに指示します。

CDN からコンテンツを提供すると、次の 2 つの方法でパフォーマンスが大幅に向上します。

  • ユーザーは近くのデータ・センターからコンテンツを受け取る
  • サーバーは、CDN が満たす要求を処理する必要はありません。

CDN のプッシュ

プッシュ CDN は、サーバーで変更が発生するたびに新しいコンテンツを受信します。コンテンツの提供、CDN への直接アップロード、および CDN を指すように URL を書き換えることについては、お客様が全責任を負います。コンテンツの有効期限と更新時期を構成できます。コンテンツは、新規または変更された場合にのみアップロードされるため、トラフィックは最小限に抑えられますが、ストレージは最大化されます。

トラフィック量が少ないサイトや、頻繁に更新されないコンテンツを含むサイトは、プッシュ CDN で適切に機能します。コンテンツは、定期的に再プルされるのではなく、CDN に一度配置されます。

CDN のプル

プル CDN は、最初のユーザーがコンテンツを要求したときにサーバーから新しいコンテンツを取得します。コンテンツをサーバーに残し、CDN を指すように URL を書き換えます。これにより、コンテンツが CDN にキャッシュされるまで、要求が遅くなります。

有効期間 (TTL) は、コンテンツがキャッシュされる期間を決定します。プル CDN は CDN の記憶域スペースを最小限に抑えますが、ファイルが実際に変更される前に有効期限が切れてプルされると、冗長なトラフィックが発生する可能性があります。

トラフィックの多いサイトは、トラフィックがより均等に分散され、最近要求されたコンテンツのみが CDN に残っているため、プル CDN でうまく機能します。

短所: CDN

  • CDN のコストはトラフィックによっては大きくなる可能性がありますが、CDN を使用しないと発生する追加コストと比較検討する必要があります。
  • TTL の有効期限が切れる前にコンテンツが更新されると、コンテンツが古くなる可能性があります。
  • CDN では、静的コンテンツが CDN を指すように URL を変更する必要があります。

出典と参考文献

ロードバランサー


出典: スケーラブルなシステム設計パターン

ロード・バランサーは、着信クライアント要求をアプリケーション・サーバーやデータベースなどのコンピューティング・リソースに分散します。いずれの場合も、ロードバランサーはコンピューティングリソースからの応答を適切なクライアントに返します。ロードバランサーは、次の場合に効果的です。

  • 要求が異常なサーバーに送られるのを防ぐ
  • リソースの過負荷の防止
  • 単一点障害の排除を支援

ロードバランサーは、ハードウェア(高価)またはHAProxyなどのソフトウェアで実装できます。

その他の利点は次のとおりです。

  • SSL 終了 - 着信要求を復号化し、サーバー応答を暗号化して、バックエンド・サーバーがこれらの潜在的にコストのかかる操作を実行する必要がないようにします。
    • 各サーバーに X.509 証明書をインストールする必要がなくなります。
  • セッションの永続性 - Cookie を発行し、Web アプリがセッションを追跡しない場合、特定のクライアントの要求を同じインスタンスにルーティングします。

障害から保護するために、複数のロードバランサーをアクティブ/パッシブモードまたはアクティブ-アクティブモードで設定するのが一般的です。

ロードバランサーは、次のようなさまざまなメトリックに基づいてトラフィックをルーティングできます。

レイヤ 4 の負荷分散

レイヤー 4 ロード バランサーは、トランスポート層の情報を調べて、要求の分散方法を決定します。一般に、これにはヘッダー内の送信元、宛先 IP アドレス、およびポートが含まれますが、パケットの内容は含まれません。レイヤ 4 ロード バランサーは、ネットワーク アドレス変換 (NAT) を実行して、アップストリーム サーバーとの間でネットワーク パケットを転送します。

レイヤ 7 の負荷分散

レイヤ 7 ロードバランサーは、アプリケーションレイヤを参照して、要求の分散方法を決定します。これには、ヘッダー、メッセージ、および Cookie の内容が含まれる場合があります。レイヤ 7 ロード バランサーは、ネットワーク トラフィックを終了し、メッセージを読み取り、ロード バランシングの決定を行い、選択したサーバーへの接続を開きます。たとえば、レイヤ 7 ロード バランサーは、ビデオをホストするサーバーにビデオ トラフィックを送信できる一方で、より機密性の高いユーザーの課金トラフィックをセキュリティが強化されたサーバーに送信できます。

柔軟性を犠牲にして、レイヤ 4 のロード バランシングはレイヤ 7 よりも必要な時間とコンピューティング リソースが少なくて済みますが、最新のコモディティ ハードウェアではパフォーマンスへの影響を最小限に抑えることができます。

水平スケーリング

ロードバランサーは、水平スケーリングにも役立ち、パフォーマンスと可用性を向上させます。コモディティ マシンを使用してスケールアウトする方がコスト効率が高く、垂直スケーリングと呼ばれるより高価なハードウェアで 1 台のサーバーをスケール アップするよりも可用性が高くなります。また、コモディティハードウェアで作業する人材を雇う方が、特殊なエンタープライズシステムよりも簡単です。

短所: 水平スケーリング

  • 水平方向にスケーリングすると複雑さが増し、サーバーのクローン作成が必要
    • サーバーはステートレスである必要があります: セッションやプロフィール写真などのユーザー関連データを含めないでください。
    • セッションは、データベース (SQL、NoSQL) や永続キャッシュ (Redis、Memcached) などの一元化されたデータ ストアに格納できます。
  • キャッシュやデータベースなどのダウンストリーム サーバーは、アップストリーム サーバーがスケールアウトするにつれて、より多くの同時接続を処理する必要があります。

短所: ロードバランサー

  • ロードバランサーは、十分なリソースがない場合、または適切に構成されていない場合、パフォーマンスのボトルネックになる可能性があります。
  • 単一障害点を排除するためにロードバランサーを導入すると、複雑さが増します。
  • 単一のロードバランサーは単一障害点であり、複数のロードバランサーを構成するとさらに複雑さが増します。

出典と参考文献

リバースプロキシ (Web サーバー)


出典:ウィキペディア

リバース プロキシは、内部サービスを集中化し、統一されたインターフェイスをパブリックに提供する Web サーバーです。クライアントからの要求は、リバース プロキシがサーバーの応答をクライアントに返す前に、要求を満たすことができるサーバーに転送されます。

その他の利点は次のとおりです。

  • セキュリティの強化 - バックエンドサーバーに関する情報の非表示、IPのブラックリスト登録、クライアントあたりの接続数の制限
  • 拡張性と柔軟性の向上 - クライアントはリバースプロキシのIPのみを参照できるため、サーバーのスケーリングや構成の変更が可能になります。
  • SSL 終了 - 着信要求を復号化し、サーバー応答を暗号化して、バックエンド・サーバーがこれらの潜在的にコストのかかる操作を実行する必要がないようにします。
    • 各サーバーに X.509 証明書をインストールする必要がなくなります。
  • 圧縮 - サーバーの応答を圧縮する
  • キャッシュ - キャッシュされた要求の応答を返します。
  • 静的コンテンツ - 静的コンテンツを直接提供する
    • HTML/CSS/JS
    • 写真
    • ビデオ

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

  • ロード・バランサーのデプロイは、複数のサーバーがある場合に便利です。多くの場合、ロードバランサーは、同じ機能を提供する一連のサーバーにトラフィックをルーティングします。
  • リバースプロキシは、Web サーバーまたはアプリケーションサーバーが 1 つしかない場合でも有用であり、前のセクションで説明した利点を開きます。
  • NGINX や HAProxy などのソリューションは、レイヤ 7 リバース プロキシとロード バランシングの両方をサポートできます。

短所: リバースプロキシ

  • リバースプロキシを導入すると、複雑さが増します。
  • 単一のリバースプロキシは単一障害点であり、複数のリバースプロキシ(つまりフェールオーバー)を設定すると複雑さがさらに増します。

出典と参考文献

アプリケーション層


出典:スケールを考慮したシステム設計入門

Web レイヤーをアプリケーション層 (プラットフォーム層とも呼ばれます) から分離すると、両方のレイヤーを個別にスケーリングおよび構成できます。新しい API を追加すると、必ずしも Web サーバーを追加せずにアプリケーション・サーバーが追加されます。単一責任の原則は、連携して機能する小規模で自律的なサービスを提唱しています。小規模なサービスを持つ小規模なチームは、急速な成長に向けてより積極的に計画を立てることができます。

アプリケーション層のワーカーは、非同期を有効にするのにも役立ちます。

マイクロサービス

この説明に関連するマイクロサービスは、独立してデプロイ可能な小規模のモジュラー サービスのスイートとして記述できます。各サービスは固有のプロセスを実行し、明確に定義された軽量なメカニズムを介して通信し、ビジネス目標を達成します。1

たとえば、Pinterest には、ユーザー プロファイル、フォロワー、フィード、検索、写真のアップロードなどのマイクロサービスがあります。

サービスディスカバリー

ConsulEtcdZookeeper などのシステムは、登録された名前、住所、ポートを追跡することで、サービスが互いを見つけるのに役立ちます。正常性チェックは、サービスの整合性を検証するのに役立ち、多くの場合、HTTP エンドポイントを使用して実行されます。Consul と Etcd の両方には、設定値やその他の共有データの格納に役立つキーと値のストアが組み込まれています。

短所: アプリケーション層

  • 疎結合のサービスでアプリケーション層を追加するには、アーキテクチャ、運用、およびプロセスの観点から (モノリシック システムと) 異なるアプローチが必要です。
  • マイクロサービスは、展開と操作の面で複雑さを増す可能性があります。

出典と参考文献

データベース


ソース: 最初の 1,000 万人のユーザーへのスケールアップ

リレーショナルデータベース管理システム (RDBMS)

SQL のようなリレーショナル・データベースは、表に編成されたデータ項目の集合です。

ACID は、リレーショナル データベース トランザクションのプロパティのセットです。

  • アトミック性 - 各トランザクションはすべてまたは何もない
  • 一貫性 - すべてのトランザクションは、データベースをある有効な状態から別の状態に戻します
  • 分離 - トランザクションを同時に実行すると、トランザクションが連続して実行された場合と同じ結果になります。
  • 持続性 - トランザクションがコミットされると、トランザクションはそのまま残ります

リレーショナル データベースをスケーリングするには、マスター/スレーブ レプリケーション、マスター/マスター レプリケーションフェデレーションシャーディング非正規化SQL チューニングなど、多くの手法があります。

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

マスターは読み取りと書き込みを行い、読み取りのみを処理する 1 つ以上のスレーブに書き込みを複製します。スレーブは、ツリーのような方法で追加のスレーブに複製することもできます。マスターがオフラインになった場合、スレーブがマスターに昇格されるか、新しいマスターがプロビジョニングされるまで、システムは読み取り専用モードで動作し続けることができます。


ソース: スケーラビリティ、可用性、安定性、パターン

短所: マスター/スレーブレプリケーション
  • スレーブをマスターに昇格するには、追加のロジックが必要です。
  • 欠点: レプリケーション (マスター/スレーブとマスター-マスターの両方に関連するポイント)を参照してください。

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

両方のマスターは、読み取りと書き込みを提供し、書き込み時に互いに調整します。いずれかのマスターがダウンしても、システムは読み取りと書き込みの両方で動作を継続できます。


ソース: スケーラビリティ、可用性、安定性、パターン

短所: マスター/マスター レプリケーション
  • ロードバランサーが必要になるか、アプリケーションロジックを変更して、書き込む場所を決定する必要があります。
  • ほとんどのマスター/マスター システムは、一貫性が緩やかであるか (ACID に違反している)、または同期のために書き込み待機時間が長くなっています。
  • 競合の解決は、書き込みノードが追加され、待機時間が長くなるにつれて、より有効になります。
  • 欠点: レプリケーション (マスター/スレーブとマスター-マスターの両方に関連するポイント)を参照してください。
短所: レプリケーション
  • 新しく書き込まれたデータを他のノードに複製する前にマスターに障害が発生すると、データが失われる可能性があります。
  • 書き込みは、読み取りレプリカに再生されます。書き込みが多い場合、読み取りレプリカは書き込みの再生で行き詰まり、それほど多くの読み取りを行うことができません。
  • 読み取りスレーブが多いほど、レプリケートする必要が多くなり、レプリケーションの遅延が大きくなります。
  • 一部のシステムでは、マスターへの書き込みによって複数のスレッドが生成されて並列に書き込まれることがありますが、読み取りレプリカは 1 つのスレッドでの順次書き込みのみをサポートします。
  • レプリケーションにより、ハードウェアが増し、複雑さが増します。
ソースと関連資料: レプリケーション

フェデレーション


ソース: 最初の 10,<> 万人のユーザーへのスケールアップ

フェデレーション (または機能的パーティション分割) は、データベースを機能別に分割します。たとえば、単一のモノリシック データベースではなく、フォーラムユーザーおよび製品の 3 つのデータベースを持つことができるため、各データベースへの読み取りと書き込みのトラフィックが少なくなり、レプリケーションの遅延が少なくなります。データベースが小さいほど、メモリに収まるデータが増え、キャッシュの局所性が向上するため、キャッシュヒット数が増加します。書き込みをシリアル化する単一の中央マスターがいなくても、並列に書き込みが可能になり、スループットが向上します。

短所: フェデレーション
  • フェデレーションは、スキーマが巨大な関数やテーブルを必要とする場合、効果的ではありません。
  • アプリケーション ロジックを更新して、読み取りと書き込みを行うデータベースを決定する必要があります。
  • 2 つのデータベースからのデータの結合は、サーバー リンクではより複雑です。
  • フェデレーションは、ハードウェアと複雑さを増します。
出典と参考文献:フェデレーション

シャーディング


ソース: スケーラビリティ、可用性、安定性、パターン

シャーディングは、各データベースがデータのサブセットのみを管理できるように、異なるデータベース間でデータを分散します。users データベースを例にとると、ユーザー数が増えると、クラスターに追加されるシャードが増えます。

フェデレーションの利点と同様に、シャーディングにより、読み取りおよび書き込みトラフィックが少なくなり、レプリケーションが少なくなり、キャッシュ ヒット数も増加します。インデックス サイズも小さくなり、一般に、より高速なクエリでパフォーマンスが向上します。1 つのシャードがダウンしても、他のシャードはまだ動作可能ですが、データの損失を防ぐために何らかの形式のレプリケーションを追加することをお勧めします。フェデレーションと同様に、書き込みをシリアル化する単一の中央マスターは存在せず、スループットの向上と並行して書き込みを行うことができます。

ユーザーのテーブルをシャーディングする一般的な方法は、ユーザーの姓のイニシャルまたはユーザーの地理的な場所を使用することです。

短所: シャーディング
  • シャードと連携するようにアプリケーション ロジックを更新する必要があるため、SQL クエリが複雑になる可能性があります。
  • シャード内でデータ分散が偏ることがあります。たとえば、シャード上の一連のパワー ユーザーは、他のシャードと比較してそのシャードへの負荷が増加する可能性があります。
    • リバランスは複雑さを増します。一貫性のあるハッシュに基づくシャーディング関数を使用すると、転送されるデータの量を減らすことができます。
  • 複数のシャードからのデータの結合は、より複雑です。
  • シャーディングは、より多くのハードウェアと複雑さを追加します。
ソースとさらなる読書:シャーディング

非正規化

非正規化は、書き込みパフォーマンスを犠牲にして読み取りパフォーマンスを改善しようとします。データの冗長コピーは、コストのかかる結合を避けるために複数のテーブルに書き込まれます。PostgreSQLやOracleなどの一部のRDBMSは、冗長な情報を格納し、冗長なコピーの一貫性を維持する作業を処理するマテリアライズドビューをサポートしています。

フェデレーションシャーディングなどの手法でデータが分散されると、データ センター間での結合の管理はさらに複雑になります。非正規化は、このような複雑な結合の必要性を回避する可能性があります。

ほとんどのシステムでは、読み取りは書き込み数が 100:1 または 1000:1 をはるかに上回ることがあります。読み取りの結果、複雑なデータベース結合が発生すると、非常にコストがかかり、ディスク操作にかなりの時間が費やされる可能性があります。

欠点: 非正規化
  • データは複製されます。
  • 制約は、情報の冗長コピーの同期を維持するのに役立ち、データベース設計の複雑さが増します。
  • 書き込み負荷が高い非正規化されたデータベースは、正規化されたデータベースよりもパフォーマンスが低下する可能性があります。
出典と参考文献:非正規化

SQL チューニング

SQL チューニングは幅広いトピックであり、多くの書籍が参考資料として書かれています。

ベンチマークプロファイルを作成して、ボトルネックをシミュレートして発見することが重要です。

  • ベンチマーク - abなどのツールを使用して高負荷状況をシミュレートします
  • プロファイル - スロー クエリ ログなどのツールを有効にして、パフォーマンスの問題を追跡します。

ベンチマークとプロファイリングにより、次の最適化が示される場合があります。

スキーマを厳格化する
  • MySQL は、高速アクセスのために連続したブロックでディスクにダンプします。
  • 固定長フィールドの代わりに使用してください。
    CHAR
    VARCHAR
    • CHAR
      効果的に高速でランダムなアクセスを可能にしますが、 を使用すると、次の文字列に移動する前に文字列の終わりを見つける必要があります。
      VARCHAR
  • ブログ投稿などの大きなテキスト ブロックに使用します。 ブール検索も可能です。フィールドを使用すると、テキストブロックの検索に使用されるポインタがディスクに格納されます。
    TEXT
    TEXT
    TEXT
  • 2 ^ 32または40億までの大きな数値に使用します。
    INT
  • 浮動小数点表現エラーを回避するために通貨に使用します。
    DECIMAL
  • 大きな を格納することは避け、代わりにオブジェクトを取得する場所の場所を格納します。
    BLOBS
  • VARCHAR(255)
    は、8 ビット数でカウントできる最大文字数であり、多くの場合、一部の RDBMS では 1 バイトの使用が最大化されます。
  • 検索パフォーマンスを向上させるために、必要に応じて制約を設定します。
    NOT NULL
適切なインデックスを使用する
  • 照会している列 (、、) は、インデックスを使用すると高速になる可能性があります。
    SELECT
    GROUP BY
    ORDER BY
    JOIN
  • インデックスは通常、データをソートしたままにし、対数時間で検索、順次アクセス、挿入、および削除を可能にする自己バランスBツリーとして表されます。
  • インデックスを配置すると、データをメモリに保持できるため、より多くの領域が必要になります。
  • インデックスも更新する必要があるため、書き込みが遅くなることもあります。
  • 大量のデータをロードする場合は、インデックスを無効にし、データをロードしてからインデックスを再構築する方が速い場合があります。
高価な結合を避ける
パーティションテーブル
  • ホット スポットを別のテーブルに配置してテーブルを分割し、メモリに保持します。
クエリキャッシュの調整
ソースと参考資料: SQL チューニング

いいえSQL

NoSQL は、キー値ストア、ドキュメント ストア、ワイド列ストア、またはグラフ データベースで表されるデータ項目のコレクションです。データは非正規化され、結合は通常アプリケーション コードで行われます。ほとんどのNoSQLストアには真のACIDトランザクションがなく、最終的な一貫性が優先されます。

BASE は、NoSQL データベースのプロパティを記述するためによく使用されます。CAP 定理と比較して、BASE は一貫性よりも可用性を選択します。

  • 基本的に利用可能 - システムは可用性を保証します。
  • ソフト状態 - システムの状態は、入力がなくても時間の経過とともに変化する可能性があります。
  • 最終的な一貫性 - システムは、その期間中に入力を受信しないため、一定期間にわたって一貫性が保たれます。

SQL または NoSQL のどちらかを選択することに加えて、どのタイプの NoSQL データベースがユース ケースに最も適しているかを理解すると役立ちます。次のセクションでは、キー値ストア、ドキュメント ストア、ワイド列ストア、およびグラフ データベースを確認します。

キーと値のストア

抽象化:ハッシュテーブル

キーと値のストアは、一般的にO(1)の読み取りと書き込みを可能にし、多くの場合、メモリまたはSSDによってバックアップされます。データ ストアは、キーを辞書順に保持できるため、キー範囲を効率的に取得できます。キーと値のストアでは、値を持つメタデータを格納できます。

キー値ストアは高いパフォーマンスを提供し、単純なデータ モデルや、メモリ内キャッシュ層など、急速に変化するデータによく使用されます。限られた操作セットしか提供しないため、追加の操作が必要な場合は、複雑さがアプリケーション層に移行します。

キーと値のストアは、ドキュメント ストアや、場合によってはグラフ データベースなど、より複雑なシステムの基礎となります。

ソースとさらなる読書:キー - 値ストア

ドキュメント ストア

抽象化:値として格納されたドキュメントを持つキーと値のストア

ドキュメントストアは、ドキュメント(XML、JSON、バイナリなど)を中心に、ドキュメントは特定のオブジェクトのすべての情報を格納します。ドキュメント ストアは、ドキュメント自体の内部構造に基づいてクエリを実行する API またはクエリ言語を提供します。多くのキー値ストアには、値のメタデータを操作するための機能が含まれており、これら 2 つのストレージの種類の境界線が曖昧になっていることに注意してください。

基礎となる実装に基づいて、ドキュメントはコレクション、タグ、メタデータ、またはディレクトリによって編成されます。ドキュメントは整理またはグループ化できますが、ドキュメントには互いに完全に異なるフィールドがある場合があります。

MongoDBCouchDB などの一部のドキュメント ストアも、複雑なクエリを実行するための SQL に似た言語を提供します。DynamoDB は、キー値とドキュメントの両方をサポートしています。

ドキュメント ストアは高い柔軟性を提供し、時折変更されるデータの操作によく使用されます。

ソースと参考資料: ドキュメント ストア

ワイド列ストア


Source: SQL & NoSQL, a brief history

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 as the first wide column store, which influenced the open-source HBase often-used in the Hadoop ecosystem, and Cassandra 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

Graph database


Source: Graph database

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.

Source(s) and further reading: graph

Source(s) and further reading: NoSQL

SQL or NoSQL


Source: Transitioning from RDBMS to NoSQL

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

Cache


Source: Scalable system design patterns

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, or in a distinct cache layer.

CDN caching

CDNs are considered a type of cache.

Web server caching

Reverse proxies and caches such as Varnish 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 algorithms such as 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


Source: From cache to in-memory data grid

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


Source: Scalability, availability, stability, patterns

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:

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

Cache code:

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.

Write-behind (write-back)


Source: Scalability, availability, stability, patterns

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


Source: From cache to in-memory data grid

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.
  • 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

Asynchronism


Source: Intro to architecting systems for scale

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 is useful as a simple message broker but messages can be lost.

RabbitMQ is popular but requires you to adapt to the 'AMQP' protocol and manage your own nodes.

Amazon 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, runs them, then delivers their results. They can support scheduling and can be used to run computationally-intensive jobs in the background.

Celery 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 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.

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

Communication


Source: OSI 7 layer model

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 common HTTP verbs:

Verb Description Idempotent* Safe Cacheable
GET Reads a resource Yes Yes Yes
POST Creates a resource or trigger a process that handles data No No Yes if response contains freshness info
PUT Creates or replace 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

Transmission control protocol (TCP)


Source: How to make a multiplayer game

TCP is a connection-oriented protocol over an IP network. Connection is established and terminated using a handshake. All packets sent are guaranteed to reach the destination in the original order and without corruption through:

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 and 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 server. Connection pooling 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 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)


Source: How to make a multiplayer game

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 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
  • Late data is worse than loss of data
  • You want to implement your own error correction

Source(s) and further reading: TCP and UDP

Remote procedure call (RPC)


Source: Crack the system design interview

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, Thrift, and Avro.

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 results, 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:

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 on caching servers such as Squid.

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 (HTML interface for HTTP) - your web service should be fully accessible in a browser.

Sample REST calls:

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, 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
{
"personid": "1234"
}
DELETE /persons/1234
Read a person GET /readPerson?personid=1234 GET /persons/1234
Read a person’s items list GET /readUsersItemsList?personid=1234 GET /persons/1234/items
Add an item to a person’s items POST /addItemToUsersItemsList
{
"personid": "1234";
"itemid": "456"
}
POST /persons/1234/items
{
"itemid": "456"
}
Update an item POST /modifyItem
{
"itemid": "456";
"key": "value"
}
PUT /items/456
{
"key": "value"
}
Delete an item POST /removeItem
{
"itemid": "456"
}
DELETE /items/456

Source: Do you really know why you prefer REST over RPC

Source(s) and further reading: REST and RPC

Security

This section could use some updates. Consider 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 and SQL injection.
  • Use parameterized queries to prevent SQL injection.
  • Use the principle of least privilege.

Source(s) and further reading

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

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

Latency numbers every programmer should know

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

Source(s) and further reading

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
Design a search engine like Google queue.acm.org
stackexchange.com
ardendertat.com
stanford.edu
Design a scalable web crawler like Google quora.com
Design Google docs code.google.com
neil.fraser.name
Design a key-value store like Redis slideshare.net
Design a cache system like Memcached slideshare.net
Design a recommendation system like Amazon's hulu.com
ijcai13.org
Design a tinyurl system like Bitly n00tc0d3r.blogspot.com
Design a chat app like WhatsApp highscalability.com
Design a picture sharing system like Instagram highscalability.com
highscalability.com
Design the Facebook news feed function quora.com
quora.com
slideshare.net
Design the Facebook timeline function facebook.com
highscalability.com
Design the Facebook chat function erlang-factory.com
facebook.com
Design a graph search function like Facebook's facebook.com
facebook.com
facebook.com
Design a content delivery network like CloudFlare figshare.com
Design a trending topic system like Twitter's michael-noll.com
snikolov .wordpress.com
Design a random ID generation system blog.twitter.com
github.com
Return the top k requests during a time interval cs.ucsb.edu
wpi.edu
Design a system that serves data from multiple data centers highscalability.com
Design an online multiplayer card game indieflashblog.com
buildnewgames.com
Design a garbage collection system stuffwithstuff.com
washington.edu
Design an API rate limiter https://stripe.com/blog/
Design a Stock Exchange (like NASDAQ or Binance) Jane Street
Golang Implementation
Go Implementation
Add a system design question Contribute

Real world architectures

Articles on how real world systems are designed.


Source: Twitter timelines at scale

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
Data processing Spark - Distributed data processing from Databricks slideshare.net
Data processing Storm - Distributed data processing from Twitter slideshare.net
Data store Bigtable - Distributed column-oriented database from Google harvard.edu
Data store HBase - Open source implementation of Bigtable slideshare.net
Data store Cassandra - Distributed column-oriented database from Facebook slideshare.net
Data store DynamoDB - Document-oriented database from Amazon harvard.edu
Data store MongoDB - Document-oriented database slideshare.net
Data store Spanner - Globally-distributed database from Google research.google.com
Data store Memcached - Distributed memory caching system slideshare.net
Data store Redis - Distributed memory caching system with persistence and value types slideshare.net
File system Google File System (GFS) - Distributed file system research.google.com
File system Hadoop File System (HDFS) - Open source implementation of GFS apache.org
Misc Chubby - Lock service for loosely-coupled distributed systems from Google research.google.com
Misc Dapper - Distributed systems tracing infrastructure research.google.com
Misc Kafka - Pub/sub message queue from LinkedIn slideshare.net
Misc Zookeeper - Centralized infrastructure and services enabling synchronization slideshare.net
Add an architecture Contribute

Company architectures

Company Reference(s)
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
How Facebook Live Streams To 800,000 Simultaneous Viewers
Flickr Flickr architecture
Mailbox From 0 to one million users in 6 weeks
Netflix A 360 Degree View Of The Entire Netflix Stack
Netflix: What Happens When You Press Play?
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
How Twitter Handles 3,000 Images Per Second
Uber How Uber scales their real-time market platform
Lessons Learned From Scaling Uber To 2000 Engineers, 1000 Services, And 8000 Git Repositories
WhatsApp The WhatsApp architecture Facebook bought for $19 billion
YouTube YouTube scalability
YouTube architecture

Company engineering blogs

Architectures for companies you are interviewing with.

Questions you encounter might be from the same domain.

Source(s) and further reading

Looking to add a blog? To avoid duplicating work, consider adding your company blog to the following repo:

Under development

Interested in adding a section or helping complete one in-progress? Contribute!

  • Distributed computing with MapReduce
  • Consistent hashing
  • Scatter gather
  • Contribute

クレジット

クレジットとソースは、このレポ全体で提供されています。

特別な感謝:

連絡先

問題、質問、またはコメントを議論するために私に連絡すること自由に感じなさい。

私の連絡先情報は、GitHub ページにあります。

ライセンス

私はこのリポジトリのコードとリソースをオープンソースライセンスの下であなたに提供しています。これは私の個人的なリポジトリなので、あなたが私のコードとリソースに対して受け取るライセンスは私からのものであり、私の雇用主(Facebook)からのものではありません。

Copyright 2017 Donne Martin

Creative Commons Attribution 4.0 International License (CC BY 4.0)

http://creativecommons.org/licenses/by/4.0/