0

問題

Rails 3.2.8アプリをWEBrickからFCGIを使用してApacheに移動した後、問題が発生しました。

このアプリには、サーバー上のゲーム統計を更新するために多くのAJAXリクエストを送信するJavaScriptで記述されたゲームが含まれています。

これはWEBrickを使用して正常に機能しますが、同じレコードに複数の高速更新を行うと、Apacheに切り替えたため、相互に上書きしているように見えます。たとえば、リクエストごとに「ポイント」の値を5ポイントずつ更新するために、ほぼ同時に送信される15個のajax呼び出しがある場合、合計スコアは75になりませんが、必要に応じて変化します。 5から45の範囲の低い数値。

これは、apacheが一度に複数のリクエストを処理できるためだと思います。

私が思うことは起こっている

  • StatisticsControllerは、ポイントを追加する要求を受け取ります。
  • コントローラは、データベースから統計レコードのコピーを開きます。
  • モデルは、現在記録されているポイント数に5を追加します。
    • レコードが保存される前に、コントローラーはポイントを追加するための別の要求を受け取ります。
    • 古いポイントの合計を保持しているレコードを開きます。
    • 古い合計に5ポイントを追加します。
  • 最初のリクエストのレコードが保存されます。
    • 2番目のリクエストのレコードが保存されます。

ポイントの合計は、10ではなく5だけ増加しています。

私が試したこと

ActiveRecordコールバックを使用して書き込みを行っているときにレコードが開かないように、さまざまな方法でレコードを「ロック」してみましたが、これまでのところ成功していません。

私はいくつかのウェブ検索を試しましたが、私が探している答えを私に与えるための魔法のキーワードをまだ思い付いていません。

質問

これらのリクエストが相互に上書きされないようにする方法はありますか、それともサーバーでこれを処理できる他の方法はありますか?(別のリクエストを送信する前に待機するか、リクエストをマージするようにjavascript統計をコーディングできることはわかっていますが、サーバーはスローできる限り多くのリクエストを処理できるはずです。)

私がここでも私のアプローチから離れている可能性は十分にあり、どんな提案でも喜んでいるでしょう。

ありがとうございました。

4

1 に答える 1

0

悲観的なロックと連携してトランザクションブロックを使用して、これを機能させることができました。

コードは次のようになります。

  # GET /statistics/request.json
  def request
    # Begin a transaction
    Statistic.transaction do

      stat = Statistic.find(params[:id], lock: true) # Lock the record until we're done with the transaction.

      stat.total_points += 5

      stat.save!

      respond_to do |format|
        format.json { render json: stat }
      end
    end
  end

また、ロックをサポートするデータベースエンジン(私の場合はInnoDBを実行しているMySQL)を使用する必要があります。

私に光を見せてくれたこの記事に特に感謝します:悲観的なロックはmysqlでは機能しないようですか?

于 2012-11-13T17:11:29.847 に答える