8

私は、scala と Akka で書かれた Minecraft サーバーであるはずの bc 論文プロジェクトに取り組んでいます。サーバーは、クラウドまたはクラスターに簡単に展開できる必要があります (適切な用語を使用するかどうかはわかりません...複数のノードで実行する必要があります)。しかし、私はakkaの初心者であり、そのようなことをどのように実装するのか疑問に思っていました. 私が今理解しようとしている問題は、異なるノードのアクター間で状態を共有する方法です。私の最初のアイデアは、Minecraft クライアントから tcp ストリームを読み取り、それをロード バランサーに送信して、リクエストを処理するノードを選択し、tcp 経由でクライアントに応答を送信する Camel アクターを用意することでした。ユーザーによって提供された資格情報が有効かどうかをチェックする AuthenticationService 実装アクターがあるとしましょう。すべてのノードにはそのようなアクター (またはおそらくそれ以上) があり、すべてのアクターは常にユーザーのまったく同じデータベース (または状態) を持つ必要があります。私の質問は、この状態を維持するための最良のアプローチは何ですか? 考えられるいくつかの解決策を思いつきましたが、このようなことは何もしていないので、欠点を指摘してください:

解決策 #1: データベースに状態を保持します。これは、状態がユーザー名とパスワードのリストなどによってのみ表されるこの認証の例ではおそらく非常にうまく機能しますが、状態に整数や文字列に簡単に分割できないオブジェクトが含まれている場合はおそらく機能しません。

解決策 #2: 特定のアクターに状態を変更するリクエストがあるたびに、アクターはリクエストを処理した後、同じタイプの他のすべてのアクターに変更に関する情報をブロードキャストします。元のアクターによって送信された情報。これは非常に非効率的で、かなりぎこちないようです。

解決策 #3: 特定のノードを一種の状態ノードとして機能させ、サーバー全体の状態を表すアクターを配置します。そのようなノードのアクターを除く他のアクターは状態を持たず、データが必要になるたびに「状態ノード」のアクターに問い合わせます。これも非効率的で、一種のフォールト・ノンプルーフのようです。

それで、あなたはそれを持っています。私が実際に気に入っている唯一の解決策は最初の解決策ですが、私が言ったように、おそらく非常に限られた問題のサブセットでのみ機能します (状態を redis 構造に分割できる場合)。より経験豊富な教祖からの応答は非常に高く評価されます。よろしく、トーマス・ハーマン

4

1 に答える 1

4

解決策 #1 はおそらく遅い可能性があります。また、これはボトルネックであり、単一障害点です (データベースのあるノードに障害が発生すると、アプリケーションが動作を停止することを意味します)。解決策 3 にも同様の問題があります。

解決策 2 は、思ったほど簡単ではありません。まず、単一障害点です。第 2 に、全順序ブロードキャスト(通常のブロードキャストよりもコストがかかります) を行わない限り、読み取りまたは書き込みの原子性やその他の順序保証 (規則性など) はありません。実際、ほとんどの分散レジスタ アルゴリズムは内部でブロードキャストを実行するため、非効率的ではありますが、必要になる場合があります。

あなたが説明したことから、分散レジスタには原子性が必要です。原子性とはどういう意味ですか? 原子性とは、一連の同時読み取りおよび書き込みにおけるすべての読み取りまたは書き込みが、単一の時点で発生したかのように見えることを意味します。 非公式に、単一のアクターがレジスターを保持しているソリューション #2 では、これにより、レジスターへの 2 つの後続の書き込み W1 とその後の W2 が発生した場合 (2 つのブロードキャストを意味します)、レジスターから値を読み取る他のアクターが値を読み取らないことが保証されます。最初に W1、次に W2 とは順序が異なります (実際にはそれよりも複雑です)。メッセージが異なる時点で宛先に到着する後続のブロードキャストの例をいくつか見てみると、そのような順序付けプロパティがまったく保証されていないことがわかります。

順序の保証や原子性が問題にならない場合は、ある種のゴシップベースのアルゴリズムが、変更をすべてのノードにゆっくりと伝達するトリックを実行する可能性があります。これはおそらくあなたの例ではあまり役に立ちません。

完全な耐障害性とアトミック性が必要な場合は、Rachid Guerraoui と Luís Rodrigues による信頼性の高い分散プログラミングに関するこの、または分散レジスタの抽象化に関連する部分を読むことをお勧めします。これらのアルゴリズムは、メッセージ パッシング通信層の上に構築され、読み取りおよび書き込み操作をサポートする分散レジスタを維持します。このようなアルゴリズムを使用して、分散状態情報を格納できます。ただし、数千のノードまたは大規模なクラスターには適用できません。これは、通常、ノード数に複雑な多項式があるため、スケーリングされないためです。

一方、分散レジスタの状態をすべてのノードに複製する必要はない場合があります。(1 つのノードだけではなく) ノードのサブセットに複製し、それらにアクセスして読み取りまたは書き込みを行います。一定レベルのフォールト トレランス (ノードのサブセット全体に障害が発生した場合のみ、レジスタ情報が失われます)。本書のアルゴリズムをこの目的に適合させることができます。

于 2011-03-31T17:20:50.180 に答える