私の
それについてのあなたのコメントとここでのあなたの質問から、あなたが解決する必要がある問題は、他ののために軍隊の数をどのように調整するかであるように思われます 移動を再生するユーザー。同じデータをもう一度見てみましょう:
{ "_id" : ObjectId("531cf5f3ba53b9dd07756bb7"), "user" : "A", "units" : 50 }
{ "_id" : ObjectId("531cf622ba53b9dd07756bb9"), "user" : "B", "units" : 62 }
「移動」を行う
したがって、ここでの状況は、ユーザー「B」が移動して62
をコミットしたところです。 その動きのユニット。前回の投稿では、一致するユーザー「A」の動きを取り戻す方法を説明したので、それらを「ペアリング」して勝利を決定することができます。
それをさらに進めて、リクエストで何が起こったのかを考えてください。ユーザー「B」が送信し、移動するドキュメントを挿入してから、一致するドキュメントを読み戻します。したがって、現在、リクエスト用に両方のドキュメントがメモリにあります。セッションデータを検討すると、次のようなものになる可能性があります(非常に簡単な方法で):
{
currentUnits: 100
}
それを開始カウントと呼びましょう。したがって、送信するとき ユーザーからの移動、あなたは彼らが持っている軍隊の数を減らすだけです。したがって、挿入を実行する場合 62
の 軍隊、カウンターはこれに行きます:
{
currentUnits: 38
}
移動中の挿入確認でそれを行うので、それは良い習慣です。しかし、次にそのコールバック内で、私が言ったように検索を実行します。それはのみ 1つのドキュメントを返します。これで、比較して計算できる情報が得られました。ユーザー「B」が勝つため、セッション値を調整できます:
{
currentUnits: 150
}
したがって、ユーザー「B」の移動のすべてをカバーする必要があります。あなたは、移動が行われたときにユニットを奪い、他のプレイヤーと一致し、次に「計算を行い」、結果を調整しました。終わり!ああ、あなたは保存しました 永続ストア内のすべてのセッションデータではありませんか?はい、うなずきます。また、そのセッションデータは、変更するためのアクセス権を取得するために、ユーザーハンドルに関連付けられています(またはユーザーは実際にはセッションIDです)。
残っているのは、他のプレイヤーに「通知」することだけです。
他の人にニュースを伝える
この部分は単純でなければなりません。だから私はあなたのためにそれをコーディングしていません。 socket.io を使用しています アプリケーションの場合、これはすべてメッセージの送信に帰着します。つまり、あなたが「放出する」データは、クライアント上の他のユーザーに「彼らの軍隊を失った」ことを伝えますが、あなたはそれを処理したいと思います。ただし、移動するときに、これらのユニットを「奪った」ことも忘れないでください。 提出されました。すべての場合において、それは誰もが彼らが持っている以上にコミットできないことを確実にしている。
ここで話すことができるのは、スケーリングだけです。 1つのインスタンスを超えたアプリケーション。したがって、すべてが1つのサーバーインスタンスで機能している「ノード」上のイベントと楽しく話すことができますが、「スケーリング」するには、異なるインスタンス間でメッセージを渡す必要があります。
MongoDBを使用してこれを処理する1つの方法は、上限付きコレクション を使用することです。 。
上限のあるコレクションが一般的にセットを維持する方法で行うことは別として ドキュメントのコレクションのサイズ、それらが提供するものがもう1つあります。それは、テーラブルカーソル 。ノードドライバを使用して作成するかなり非定型の方法は、次のようになります。
var options = { tailable: true, awaitdata: true, numberOfRetries: -1 };
var cursor = collection.find(query, options).sort({ $natural: 1 });
完全なオプションは、 Cursor()> ドライバのマニュアルページのセクション。これらの「ネイティブ」メソッドは、通常の方法でマングースで取得できます。
「調整可能な」カーソルが設定されているのは、コレクション内の「最後に挿入された」ドキュメントを「フォロー」することです。このように、次のように、均等なポーリングで座って「フォロー」できます。
(function more() {
cursor.nextObject(handle(function(doc) {
if (!doc) return setTimeout(poll, self.wait);
callback(doc);
latest = doc._id;
more();
}));
})();
したがって、このような構成内で、新しく挿入されたドキュメントを「検索」し、処理する情報を内部コールバックに渡します。ここで、クライアントにメッセージを「送信」したり、更新したり、その他の作業を行います。
実際の「リクエスト」に戻ると、別の「キャップされたコレクション」に「計算を行った」後に挿入を発行することになります。次のような簡単な説明で意味のあるものが必要になります:
{ "player": "B", "vsplayer": "A", "win": 50, "loss": 62 }
そしてまた、これらはただ 挿入します。したがって、TTLインデックス を設定します。 時間の経過とともに削除を処理し、上限を設定するために、古いエントリは、コレクションに存在するエントリから「プッシュアウト」されることによって自然に排出されます。
「クライアント」側では、接続されている各ユーザーアプリケーションが、返された「last_id」値を追跡します。したがって、新しく挿入されたエントリは常に 以前の「古い」ものよりも価値が高い。
したがって、MongoDBを使用して永続キューを作成し、複数のアプリケーションサーバーインスタンス間でメッセージパッシングを共有するために順次処理できる「1つの方法」があります。
最後の言葉
このように「テール可能な」カーソルを実装すると言っても、私のお金ではzeromq を使用します。 またはそのようなもの。ただし、別のテクノロジーを詳しく調べたくない場合は、MongoDBメソッドの方が適している場合があります。または、おそらくこの種の「スケーラビリティ」はアプリケーションでは必要なく(少なくともこの段階では)、リクエスト内で「socket.io」メソッドに渡すだけで十分です。あなた次第です。
ただし、大部分は、「ペアリング」と「削除」の概念にまだ「ハングアップ」しているようです。これは前回の回答で取り上げる意図であり、削除と言うことでした 処理時のドキュメントの数は不要です 。説明されているプロセスは保証 「同じペア」を取得することはありません リクエストに応じて戻ってください。
「再読」することをお勧めします その情報と本当にプロセスを理解しています。そして、質問があるかどうか尋ねてください。そこで説明されていることから、データアクセスパターンのアナロジーは、「ペアのマッチング」というよりも「スタックの再生」に似ています。
それで、あなたがそれに応じて与えられたもの、次の ここで説明するロジックはすべてです データアクセスパターンを設定するために必要です。もちろん、他のコンポーネントはメッセージングですが、これにより、必要なデータにアクセスできます。