はじめに
今日は、高負荷のフォールトトレラントシステムの設計について説明します。 ドライ理論ではなく、実用的な開発と揚げた事実に重点が置かれます。 読んだ後、十分なサーバーがあれば、10億人のユーザーがいるサービスを開発することを恐れません。 このトピックは非常に広範囲に渡りますが、簡潔かつ簡潔にしようと思います。何を取得したいですか?
問題とシステム要件の論文ステートメントから始めましょう。それらはほとんどありません。- システムは、使用可能なサーバー間でタスクを自動的に共有する必要があります。
- 2台のサーバーの同時物理障害(シャットダウン)は、システムの整合性に影響しません。
- 機器の物理的な故障は、システム全体の故障を伴いません。
- 新しいサーバーを有効にするために、手動で構成する必要はありません。
- クライアントは、任意のフロントエンドサーバーと同等に対話できます。
2つの方法。
2つの方法があります。 1つ目はMicrosoftの方法です。各サービスは独立して開発され、各開発チームが独自の決定を下します。2番目のパス-Googleのパス-アプリケーションが存在する単一のプラットフォームと単一のシステム(検索エンジン、メーラー、グループなど)があります。
システムの任意の部分を最適化すると、すべてのサービスの作業が一度に改善されるため、2番目の方法が顕著に勝利します。 1つ目は、白鳥、ガン、カワカマスに関するクリロフのf話を非常に連想させます。
プラットフォームの主要コンポーネント。
各サーバーで任意のコンポーネントのセットを起動でき、各コンポーネントのサーバーの数は自動的に決定されます。- データウェアハウス。 システムの状態はその中にのみ保存されます。
- キャッシュサブシステム。 ホットデータをメモリに一時的に保存するために使用されます。
- ロックサービス。 順次プロシージャーの同時呼び出しを防ぐために使用されます。
- サービスアプリケーション。 すべての最終サービスがそこにあります。
- カスタマーインタラクションサービス。 WebサーバーとDNSサーバーが含まれます。
データウェアハウス。
システムの状態はシステムにのみ保存され、アプリケーションの他のリポジトリは利用できません。 MongoDBを選択します。 アプローチ方法を理解するために、以前の記事であるMongoDBに精通することをお勧めします。 良いコーヒーを作るため 、クラスタリングに特に注意を払ってください。 MapReduceも重要です。キャッシュサブシステム。
オブジェクトの単純なサンプルと複雑なサンプルの両方で、データベースの負荷を軽減する必要があります。 memcachedを選択します。 MongoDBとmemcachedを友達にする方法については、MongoDBに関する記事で説明されていますが、注意を払うことをお勧めします。ロックサービス。
順次プロシージャーの同時呼び出しを防ぐために使用されます。 一連のアクションを必要とする手順を実行する前に、アプリケーションはロックサービスに要求を送信します。 それに応じて、履行または拒否の同意を受け取ります。 phpDaemon :: LockServerを選択します。 1つのノードが落ちた場合、そのノードが率いるすべてのクライアントが別のノードに切り替えられます。サービスアプリケーション。
最終サービスはその中にあります。 OpenVZは、アプリケーションサービスとして機能できます。 アプリケーションは、phpDaemon非同期モジュールにすることもできます。 アプリケーションを開発するときは、重い操作をキューに入れる必要があります。カスタマーインタラクションサービス。
これには、Webサーバー(nginx)、DNSサーバー(bind9)、およびリクエストがアプリケーションに直接送信されるファイアウォールが含まれます。 フォールトトレランスとロードバランシングは、ラウンドロビンDNSまたはASステータスのBGPのいずれかを介して提供されます。ファイルストレージ。
ファイルはGridFSの方法論に従ってデータベースに保存され、FUSEモジュールの形式で実装されています。使用例。 Web Searchサービスの説明。
このサービスは、いくつかのコンポーネントに分かれています。1.ドキュメントに関する情報の保存。
これを行うには、プロパティurl、host、type、size、mtime、atime、title、text、description、indexedなどを含むドキュメントでドキュメントコレクションを使用します。urlでフィールドを分割します。
2.ページのコンテンツをデータベースに保存するクローラー。
クローラーはdocuments.find({host:...、indexed:0})を要求し、このホストでロックを取得します。 ネットワーク経由で各ドキュメントを要求し、データベースに追加して、インデックス付きを公開します.1。
3.全文検索。
効果的なテキスト検索を行うには、特定の単語でドキュメントをすばやく検索できる特別なメカニズムが必要です。
3.1。 単語を「通常の」形式にする。 単語はさまざまな単語形式で書くことができますが、それらはすべて1つの通常の形式に減らす必要があります。そのためには、辞書(Sphinxのスペルダンプを参照)、および辞書にない単語の発見的ステマーを使用する必要があります。
3.2。 インデックスストレージ。
2つのアプローチがあります。
最初のアプローチは、検索クエリの数が比較的少ない検索エンジンでよく使用されます。 これは、単一の検索インデックスを複数に分割すること、およびクエリ内のすべてのノードの並列処理を意味します。 つまり、検索クエリが送信されると、すべてのノードがポーリングされ、それらの応答が結合されます。 このアプローチでは、パフォーマンスを向上させるために、ノードミラーを追加し、これらのミラーノード間で負荷を分散します。 しかし、これは非常に非効率的です。なぜなら、 インデックスが大きいほど、より多くのサーバーが必要になり、単語の人気はまったく考慮されません。 多くの言葉は決して要求されません。
2番目のアプローチには単語の配布が含まれるので、「ホットガール」にクエリを実行すると、最初にこれらの単語のそれぞれに責任があるサーバーを見つけ、次にそれらを要求して結果を接着します。 これらの言葉を担当していないサーバーは、通常はロードしません。 これにより、パフォーマンスが大幅に向上します。
したがって、2番目のオプションを選択します。 インデックス作成中、ドキュメントは単語に分割され、通常の形式に縮小され、words.upsert({word:...、{"$ push":{"docs":...}}}が各単語に対して呼び出されます。
3.3。 検索。
「hot girls」を簡単に検索すると、words.find({word:「hot」})およびwords.find({word:「girl」)が要求されます。「girls」ではなく「girl」に注意してください。 次に、それらの間の交差が明らかにされ、ランキングが実行されます。
効果的なランキングを得るには、ドキュメント内のすべての単語のペア間の距離を保存する必要があります。 {docid:...、word1: "hot"、word2: "girl"、distance:1}という形式のオブジェクトを含むwordpairsコレクション。 したがって、ホットドキュメントとガールドキュメントが最も近くにあるドキュメントをすばやく見つけることができます。
使用するソフトウェアへのリンク。
- Nginx -Webサーバー
- MongoDB-データベース
- phpDaemon-ロックサーバーと他のモジュールを含むサーバー
おわりに
実際、そのようなシステムを作ることはまったく難しくありません。 さらに、このようなシステムを簡単に作成するための適切なフレームワークに取り組んでいます。このような膨大な情報をこの記事に収めるのは非常に困難ですが、その本質を伝えることができたと思います。 あなたが特に興味深いと思うのはどの側面かと思いますが、次回はそれらについて書きます。
主なことは、より簡単なツールで作業することで問題に直面している場合、代わりに既製のソリューションを使用せずに問題に直面した場合を理解して認識することです想像すらしません 一般的に、Keep It Simple、Stupidの原則を公言していない製品には疑いがあります。 基本レベルで何が起こるかを制御できない場合、すべての種類の自動オプティマイザー(SQLクエリ、コードなど)がしばしば誤解されるため、すべてを正しく行うことができないことを理解しています。
たとえば、記事の1つへのコメントで、MongoDBでSQLクエリ「SELECT * FROM table ORDER BY RAND()* hosts LIMIT 5」に類似したものを実行できるかどうかを尋ねられました。 これはもちろんクールで便利ですが、同じ成功を収めて、プレート全体を選択し、スクリプトで必要なものを選択することができます。この場合、MySQLは各行のRAND()*ホストを実行し、すべてをソートしますこれらの行はメモリ内にあり、最初の5つの結果を切り捨てます。 もちろん、プレートが大きいほど、ブレーキが多くなります。 したがって、アクションの結果として実際に何が起こるかを常に考える必要があります。そうしないと、負荷の高いシステムを作成する方法を学習できなくなります。
ご清聴ありがとうございました!