web-dev-qa-db-ja.com

高度にスケーラブルになるようにWebサイトを設計する最良の方法は何ですか?

Facebookなどのソーシャルネットワークなど、高度にスケーラブルである必要があるWebサイトの場合、Webサイトを設計するための最良の方法は何ですか?

  1. 必要なデータを取得するためにサイトがクエリするWebサービスが必要ですか?

    または

  2. サイトはデータベースを直接クエリする必要がありますか? (テーブルを自動的に埋めるために組み込みの言語構造を使用して行うことができます)。

Webサービスは一元化されたデータアクセスを提供し、キャッシングなどの制御がはるかに容易になるため、より良い設計だと思いますが、他の人はどう思いますか?

37
Daniel

うわー、これは単純な質問であり、非常に多くの可能な答えがあります。質問のより明確な部分は、直接またはWebサービスを介してデータベースとインターフェースする方がよりスケーラブルであるかどうかを尋ねます。その答えは簡単です。データベースに直接クエリを実行します。 Webサービスを通過すると、ファイアウォールの背後で動作するコード(概して)で動作するコードに完全に不要な一連の待ち時間が追加されます。たとえば、Webサービスでは、要求を受信し、それを逆シリアル化し、DBにクエリを実行し、応答をシリアル化して返すためのコンポーネントが必要です。したがって、コードがすべてファイアウォールの背後で動作している場合は、問題を回避し、DBに直接クエリを実行します。

ただし、Webサイトをスケーラブルにすることは、最初に提起した質問をはるかに超えています。ここで正直言って許してください。しかし、特にFacebookについて言及していることを考えると、それが役立つと思いました。

Brad Fitzpatrick(LiveJournalの創設者、現在はGoogleに所属)が作成した作業とツールを読むことをお勧めします。 Six Apartで彼と一緒に仕事をしていたとき、彼から学んだことのいくつかと、LiveJournalのアーキテクチャーを使ってスケーラビリティを高めたものを紹介します。

  1. 広いデータベーステーブルではなく狭いデータベーステーブルを使用。これについて魅力的だったのは、このアーキテクチャの動機付けを学び、簡単に迅速にアップグレードされたシステムを作成することでした。幅の広いテーブル、または各フィールドまたはプロパティがテーブル内の列であるテーブルを使用する場合、新しい列を追加するなど、データベーススキーマをアップグレードするときに、システムはスキーマを更新している間、テーブルをロックする必要があります。変更が実装されています。大規模に運用する場合、これはデータベーススキーマへの単純な変更が大規模なデータベースの停止につながる可能性があることを意味します。明らかに最悪だ。一方、幅の狭いテーブルは、オブジェクトに関連付けられた個々のプロパティをデータベースの単一行として格納するだけです。したがって、データベースに新しい列を追加したい場合に必要なことは、レコードをテーブルに挿入することだけです。これは、非ロック操作です。さて、それは少し背景ですが、このモデルが実際にLiveJournalのような作業システムでどのように変換されるかを見てみましょう。

    個人のブログに最近の10件のジャーナルエントリをロードするとします。また、各ジャーナルエントリに10個のプロパティがあるとします。クラシックワイドテーブルレイアウトでは、各プロパティはテーブルの列に関連付けられます。次に、ユーザーは一度テーブルにクエリを実行して、必要なすべてのデータをフェッチします。クエリは10行を返し、各行には必要なすべてのデータが含まれます(例:SELECT * FROMエントリORDER BY日付LIMIT 10)。ただし、狭いテーブルレイアウトでは、状況が少し異なります。この例では、実際には2つのテーブルがあります。最初のテーブル(テーブルA)には、検索したい単純な基準が格納されています。エントリのID、作成者のID、エントリの日付など。2番目のテーブル(テーブルB)は、エントリに関連付けられたすべてのプロパティを格納します。この2番目のテーブルには、entry_id、key、valueという3つの列があります。テーブルAのすべての行について、テーブルBには10行あります(プロパティごとに1行)。したがって、最後の10エントリをフェッチして表示するには、11クエリが必要になります。最初のクエリはエントリIDのリストを提供し、次の10個のクエリは、最初のクエリで返された各エントリに関連付けられたプロパティをフェッチします。

    「聖なるモリー!」あなたは「地球上でそれをよりスケーラブルにするにはどうすればよいのか?」と言います。その完全に直観に反する権利ですか?最初のシナリオでは1つのデータベースクエリしかありませんでしたが、2番目の「よりスケーラブルな」ソリューションでは11のデータベースクエリがあります。それは意味がありません。その質問への答えは、次の箇条書きに完全に依存しています。

  2. 自由にmemcacheを使用してください。ご存じなかった場合、memcacheは分散型のステートレスで低レイテンシのネットワークベースのキャッシュシステムです。 Facebook、Google、Yahoo、そして世界中で人気のあるスケーラブルなWebサイトのほぼすべてで使用されています。これはBrad Fitzpatrickによって部分的に発明され、ナローテーブルデータベース設計に固有のデータベースオーバーヘッドを相殺するのに役立ちます。上記の#1で説明したのと同じ例を見てみましょうが、今回はmemcacheを紹介します。

    ユーザーが最初にページにアクセスし、何もキャッシュにないときに始めましょう。まず、ページに表示する10のエントリのIDを返すテーブルAをクエリします。これらの各エントリについて、データベースにクエリを実行して、そのエントリに関連付けられているプロパティを取得し、それらのプロパティを使用して、コードがインターフェイスできるオブジェクト(オブジェクトなど)を構成します。次に、そのオブジェクト(またはそのオブジェクトのシリアル化された形式)をmemcacheに隠しておきます。

    誰かが同じページを2回目にロードしたときも、同じ方法で開始します。表示するエントリIDのリストをテーブルAに問い合わせます。各エントリについて、最初にmemcacheに移動して、「キャッシュにエントリ#Xがありますか?」と言います。はいの場合、memcacheはエントリオブジェクトを返します。そうでない場合は、データベースを再度クエリしてそのプロパティをフェッチし、オブジェクトを構成してmemcacheに格納する必要があります。ほとんどの場合、2回目に同じページにアクセスしたときにデータベースクエリが1つしかない場合、他のすべてのデータはmemcacheから直接取得されます。

    実際、LiveJournalのほとんどで実際に起こったことは、システムのデータのほとんど、特に揮発性の低いデータがmemcacheにキャッシュされ、ナローテーブルスキーマをサポートするために必要なデータベースへの追加のクエリがすべて完全に相殺されたことです。

    この設計により、すべての友達に関連する投稿のリストをストリームまたは「壁」にまとめることに関連する問題をはるかに簡単に解決できるようになりました。

  3. 次に、データベースのパーティション分割を検討してください。上記のモデルにはさらに別の問題があり、狭いテーブルは非常に大きく/長くなる傾向があります。そして、それらのテーブルの行が多いほど、他の管理タスクが難しくなります。これを相殺するには、テーブルを何らかの方法でパーティション分割してテーブルのサイズを管理し、ユーザーのクラスターに1つのデータベースを提供し、別のユーザーのクラスターに別のデータベースを提供することが理にかなっています。これにより、データベースの負荷が分散され、クエリが効率的になります。

  4. 最後に、素晴らしいインデックスが必要です。クエリの速度は、データベースのテーブルがどれだけ適切にインデックス化されているかに大きく依存します。干し草の山から針をより効率的に見つけることは、巨大なカードカタログシステムによく似ているということを除いて、インデックスについての説明にあまり時間をかけません。 mysqlを使用している場合は、スロークエリログをオンにして、実行に時間がかかるクエリを監視することをお勧めします。クエリがレーダーでポップアップした場合(遅いためなど)、高速化するためにテーブルに追加する必要があるインデックスを特定します。

「この素晴らしい背景のすべてに感謝しますが、それは私が書かなければならない多くのコードです。」

必ずしも。 memcacheとのインターフェースを本当に簡単にする多くのライブラリが作成されています。さらに他のライブラリは、上記のプロセス全体を成文化しました。 PerlのData :: ObjectDriverは、まさにそのようなライブラリです。他の言語については、あなた自身の研究を行う必要があります。

この回答がお役に立てば幸いです。私がしばしば見つけたのは、システムのスケーラビリティは、多くの場合、コードではなく、健全なデータストレージと管理戦略/技術設計にますます下がっていることです。

41
Byrne Reese

Facebookなどのソーシャルネットワークなど、高度にスケーラブルである必要があるWebサイトの場合、Webサイトを設計するための最良の方法は何ですか?

測定。

私は思います...

悪い方針。

実測が必要です。

13
S.Lott

スケーラビリティは特定の実装戦略の機能ではなく、アプリケーションアーキテクチャを設計する機能です。これにより、大規模なリファクタリングや書き換えを行わなくてもデータアクセスレイヤーを進化させることができます。

拡張性のあるシステムを構築する上で重要な手法は、高レベルのデータアクセス要件を理解し、それらの要件に関するインターフェースコントラクトを構築することです。たとえば、1人のユーザーを取得または任意のユーザーが最近投稿した50枚の写真を一覧表示する必要がある場合があります。

アプリケーションのビジネスロジックとデータアクセスロジックの間にネットワークチャネルが必ずしも必要ではありません。論理演算ごとに1つのメソッドを使用するメソッド呼び出しの間接化は、開始するには問題ありません。

最初に、これらのデータアクセスメソッドをできるだけ単純にします。アプリケーションが実際の使用パターンを提供し、ボトルネックのある場所に関するデータを収集するまで、パフォーマンスの問題がどこにあるかを予測することは非常に困難です。

明確に定義されたデータアクセスインターフェイスを持つことで、アプリケーション全体に大きな変更を加えることなく、データアクセスの実装を進化させることができます。ビジネスロジックに対して透過的にWebサービスアーキテクチャに切り替えることもできます。

上記の回答の多くは、パフォーマンスのボトルネックを発見した後の進め方に関する優れたアドバイスを提供しますが、これらをあまりに早く適用すると、コードの複雑さが必要であるかどうかを知る前に、コードの複雑さに悩まされる可能性があります。

9
Martin Atkins

シンプルなWebサイトを開発し、ある程度のトラフィックレベルに到達させます。それに沿って、スケーラブルなWebサイトを作成する方法を学びます。

問題に直面するまで、解決策を考えることはできません

サイトをローリングしてスケーリングの要件に直面したら、私を信頼してください。そうすれば、その方法を確実に理解できます。 :-)

4
Pankaj Upadhyay

Webアプリケーションは、デフォルトでWeb(プレゼンテーション)、アプリケーション、およびデータベースレイヤーの3つの層で設計する必要があるという認識は受け入れられています。この分割は、各レイヤーでの異なる要件によるものです。通常、データベースに対する高品質のディスクアクセス/ストレージ、アプリレイヤーでの高CPU /メモリ、およびWebレイヤーでの高外部帯域幅/メモリ/地理的分散です。多くの場合、データベースマシンは、初期のアプリケーションの負荷を処理するために構築できる大規模なサーバーになる傾向があるため、アプリケーション/データベースレイヤーは、アプリケーションのライフサイクルのかなり後の段階まで1つに統合されます。

ただし、アプリケーションの特定の数のレイヤーと適切なアーキテクチャは、このモデルや他のモデルと一致する必要はありません。

システム内のすべてのアクティビティを測定および監視する必要があることを計画します。 2層または3層の設計から始めて、それを構築するときに、最も多くのリソースを必要とするように見える部分に焦点を当てます。このレベルで、実行中のアプリケーションが設計をガイドできるようにします。収集する情報が多く、情報が正確で詳細であるほど、アプリケーションの成長に合わせてアプリケーションを設計する上でより適切な決定を下すことができます。

後で、必要な変更を可能な限り迅速かつ簡単にピボット/変更できるようにするフレームワークとアーキテクチャを選択します。データアクセス/ストレージ/処理とアプリケーション処理が同じ実行可能ファイルで実行されている場合でも、適切に因数分解されていれば、たとえば、後で2つのレイヤーに分割することはそれほど難しくありません。

2
blueberryfields

データベースに接続するための追加の手順は、単なるオーバーヘッドです。たとえば、UI -> Business Facade -> Business -> Data Access -> DatabaseおよびUI -> Database、2番目のアプローチの方が高速です。ただし、削除する手順が多いほど、システムの保守性が低下し、重複が多くなります。プロフィール、ホームページ、悪魔の管理ページなどで友達のリストを取得するために必要なコードを書くことを想像してみてください。

したがって、ここではハイパフォーマンス(もちろん、より高いスケーラビリティに直接影響します)とより良いメンテナンス性の間でバランスを取る必要があります。

ただし、拡張性の高いWebサイトの作成を検討する場合は、データベース接続トピックに限定されないでください。次の項目も考慮してください。

  1. 適切なプラットフォームを選択する(PHPはスクリプトの性質により高速ですが、ASP.NETは要求されたファイルをその場でコンパイルして処理し、何かを提供する必要があります。また、 node.jsコールバックベースのアーキテクチャ )のため、よりスケーラブルであると主張されています
  2. Webサービスモデル(SOA)の代わりにRESTfulアーキテクチャを使用する
  3. XMLの代わりにデータ転送にJSONを使用する(転送されるバイト数が少なくなります)
  4. Yahooの パフォーマンスガイドライン
  5. 負荷分散、または層アーキテクチャなどのネットワークおよびハードウェアトピック
2
Saeed Neamati

スケールアップとスケールアウトには、主に2つの方法があります。

スケールアップとは、マシンをより強力なマシンに置き換えることです。スケールアウトとは、既存のマシンが実行している作業を実行するために別のマシンを追加することを意味します。

トラフィックの多いWebサイトには、スケールアウトする機能が必要です。実行する必要があるソフトウェアアーキテクチャは、より多くのマシンを簡単に追加できるようにするなどの方法で、サイトがビジー状態になります。

通常、これは、アプリケーションを層に分割して、各層でより多くのサーバーを接続して再生できるようにすることを意味します。

私はオプション1を行いますが、直接行う代わりにサービスを提供します。これまでのところ、モノリシックアプリケーションのみをスケーリングできます。

1
Jon Raynor

クラウドのサポートを完全に統合したテクノロジープラットフォームを使用してサイトを開発します。

0
bhagyas