2016-03-22 16 views
2

akkaを使用してユーザーのゲーム状態を管理する方法を理解しようとしています。akkaを使用してユーザーのゲーム状態を管理する方法

ゲームの状態はmysqlに保持されますが、これを必要とする他のサービスがあるため変更できません。

ゲームで起こることはすべて「イベント」とみなされます。

あなたは誰かが達成できる「レベル」を持っています。レベルは、それに関連するすべての「イベント」を完了すると達成されます。

だからあなたが持っている:

Level 
- event1 e.g. reach a point in the game 
- event2 e.g. pickup a sword 
- event3 e.g. defeat a monster 

だからゲームで多くのレベル、およびレベルにリンクされているイベントの100年代があります。

したがって、すべての「イベント」はHTTP経由でバックエンドに送信され、イベントをデータベースに保存します。

その後、ユーザーのゲームプロファイルをメモリに読み込んでから、新しいイベントが発生してから達成したレベルを再計算する必要があります。 注:この計算は、私がここに書いているより少し複雑であるため、データベースレベルでは実行できません。

私が見ている問題は、akkaを使用すると、データが古くなる可能性があるため、複数のアクターが同じユーザーのイベントを処理できないことです。

ただ、データベース

を更新し、新しいイベントが到着したときに、彼らが持っている場合ので、私は、メモリ内のゲームプロファイルをロードレベルをループし、それらのいずれかが達成されたかどうかを確認する必要があり、明確にします
e.g. update levels set achieved=true where level_id = 123 and user_id=234 

たとえばactor1はプロファイル(このユーザーのすべてのレベルとイベント)を読み込んだ後、受信トレイに到着したばかりの新しいイベントを処理します。 同時に、actor2はプロファイルを読み込み(actor1と同じ)、新しいイベントを処理します。 mysqlへの変更が持続すると、データはsych外になります。

私がスレッドを使用していた場合は、ゲームプロファイルの計算中にロックし、dbに固定しなければなりません。

私はAkkaを使ってこれを行い、物事を並行して扱うことができますか、またはこのScenerioはそれを許さないのですか?

+0

この問題を解決できる 'akka-persistence'のように見えます –

答えて

5

あなたは俳優なしでそれをどのように管理するか考えてみましょう。だから、一言で言えば、あなたは次のような問題のシナリオを持っている:

  1. 2つ(またはそれ以上)の更新要求は、両方が は
  2. 両方の要求は、いくつかの安定したデータを読み取る同じデータを変更しようとしている、同時に到着 その後、それ自身のやり方でそれぞれを更新し、DBに持続する
  3. 最初にチェックインされたリクエストからの変更は失われ、より正確には後のリクエストによって上書きされます。

これは古典的な問題です。

  1. Optimistic locking
  2. ペシミスティック・ロック:それは通常の取引のためのSerializable分離レベルを適用することにより達成のITの少なくとも二つの古典的な解決策があります。

価値があるのはthis answerです。両方の世界を比較してみる価値があります。

あなたはAkkaを使用しているので、復旧しやすい並行性と時折の失敗を好むことが多いでしょう。それは、Akkaモットーlet it crashと同じレベルになります。

だから、あなたは、次のステップにする必要があります:(S)

  1. があなたのテーブルにversion列を追加します。数値または文字列(ハッシュ付き)にすることができます。数値は最も単純なものです。
  2. 新しいレコードを挿入すると、バージョンを初期化します。
  3. レコードを更新すると、versionの値は変更されていません。したがって、更新戦略は次のとおりです。
    1. 読み取りレコードとそのversionです。
    2. メモリ内のレコードを更新します。
    3. 条件where rec_id=$id and version=$versionで更新クエリを実行します。
    4. 更新されたレコード数が1の場合は、正常です。 0の場合はOptimisticLockExceptionをスローします。
  4. 最後に、それはその仕事をするAkkaのための時間です:適切な監督の戦略を考え出す(私はtry again in 1 secondのようなものを選ぶと思います)。アクタのpreRestartメソッドでは、アクタのメールボックスに更新メッセージを返します(AkkaドキュメントのRestart Hooksの章を参照)。

この方法では、2つの要求が同じレコードを一度に更新しようとしても、そのうちの1つが失敗し、すぐに再度処理されます。

関連する問題