6

Grails で問題が発生しました。これは、同時実行の処理方法に関する潜在的な問題である可能性があります。そして、これをどのように処理するのが最善かわかりません(または、適応できる解決策/実践がすでに整っている場合)。

バックグラウンド


私の Grails アプリケーションは REST API として機能しており、暗号化のソルティング メカニズムとしてカウンター変数に依存するデータの暗号化メソッドを備えています。

このカウンタ変数は維持する必要があり、発行後にカウンタを変更できないSIM カードにデータが送信されるため、これよりも小さくすることはできません。したがって、このカウンタを正しく維持することが重要です。さらに、カウンターが正しくない場合、メッセージは SIM によって拒否されます。

たとえば、ユーザーが呼び出すと、http://example.tld/service/controller/action?id=1サーバーは次のことを行います。

  • getcontroller識別子を持つオブジェクト1
  • counterオブジェクトのメンバー/行を変更します
  • saveオブジェクト

これは、20,000 を超えるリクエストで問題ありませんでした。ただし、StaleObjectExceptionオブジェクトがまったく同時にアクセスされたために発生すると判断したことが2回ありました。これは、私が提供したラッパー API が 10 個のスレッドを使用しており、偶然にも両方のスレッドがaction同時に を呼び出したためであると判断しました。

私は次のいずれかを実行できることを読み、注意しました。

  • 楽観的ロックをオフにします (これは悪い考えのようです) 。
  • 動的更新を有効にします (同じ行を同時に更新しているため、これが役立つとは思いません) 。
  • lockオブジェクト - しかし、オブジェクトが2回目にアクセスされたときにロックされているため、これでも例外が発生すると思いますか?
  • executeUpdate動的更新をオンにするのと似ていると思われるものを使用しますか? おそらく私のユースケースでは役に立たないでしょう。

質問


おそらく使用できるトランザクションメカニズムがあるかどうか疑問に思っていますか? つまり、オブジェクトが現在ロックされているかどうかを確認し、ロックされている場合は、データベースでトランザクションが完了するまでスリープするメソッドです。t

最終的に、私の最終目標はリクエストを拒否しないことです。したがって、上記のトランザクション メカニズムが存在し (これはある種の悲観的ロックであると想定しています)、オブジェクトがロックされているときにトランザクション メカニズムがリクエストを拒否する場合は、他の解決策が必要です。クライアントへの事前の配信が複雑になるため、サービスへのリクエストを拒否することは絶対に避けたいからです。

私が考えている現在の解決策は、次のとおりです。

try { 
    Foo.save()
catch (RespectiveException ex) {
    Thread.sleep(1000)
    if(depth < 3) {
        recursiveCallToThisMethod(depth++)
    } else {
        render(letTheUserKnowWhyItFailed)
    }
}

でもええ...かなり醜い。

4

1 に答える 1

0

悲観的ロックを試してください。2 番目のリクエストには例外はなく、最初のリクエストが完了するまでブロックされます。

def controller = Controller.lock(params.id)
controller.counter += 1
controller.save()
于 2016-01-20T10:03:12.160 に答える