4

私の主な目標は、終了するまで他のスレッドからアクセスされるべきではない同期メソッドを使用できるようにすることです。通常のVMがある場合、このメソッドを同期済みとしてマークします。しかし、GAEには複数のインスタンスがあります。これについて読んだすべての投稿には、memcacheまたはデータストアを使用する必要があると書かれています。しかし、どのくらい正確に?

4

2 に答える 2

6

通常、答えは関数を再設計して、グローバルに同期する必要がないようにすることです。なんとか同期できたとしても、それが1つのボトルネックです。

おそらく、バックエンドに実装するのが最善でしょう。単一のバックエンドを指定して、関数呼び出しをバックエンドへのリクエストにすることができます。memcache またはデータストアをセマフォとして使用することもできますが、これらはすべてパフォーマンスが低下します。

于 2013-02-16T08:23:13.033 に答える
1

実際、私はその種の同期をあまり使用しません。一度やった。それはかなりうまくいくようです。ここに例があります

String syncKey = "Sync:" + req.getRequestURI();
boolean lockAcquired = false;
try {
  lockAcquired = acquireLock(syncKey, 5000L);
  if (!lockAcquired) {
    return;
  }
  // do something here

} finally {
  if (lockAcquired) {
    memcacheService.delete(syncKey);
  }
}


public boolean acquireLock(String syncKey, long maxwait) {
  long start = System.currentTimeMillis();
  while (true) {
    if (memcacheService.increment(syncKey, 1L, 0L) == 1L) {
      return true;
    }
    if (System.currentTimeMillis() - start > maxwait) {
      return false;
    }
    try {
      Thread.sleep(100L);
    } catch (InterruptedException e) {
    }
  }
}

通常、私はより単純な同期を使用します。コードの一部を一度だけ実行する機会が得られます。

final long now = System.currentTimeMillis() / (60L * 1000L); // expire every minute
if (memcacheService.increment("VoteRemoveOldTask" + now, 1L, 1L) == 1L) {
  QueueFactory.getDefaultQueue().add(
      TaskOptions.Builder.withDefaults().url(VoteRemoveOldTask.URL));
}
于 2013-02-16T15:20:18.123 に答える