データストアで強力な一貫性を達成しようとしていますが、私の要件を処理する方法は他にありません。ユーザーがランダムに互いに接続するアプリケーションを持っています。ので、基本的に '接続' API呼び出しでは、QueueUserエンティティを照会し、それが見つからなければ、キュー内の呼び出し元のユーザーをプッシュします。GAEでobjectifyと強固な整合性を強制します
ofy().load().type(QueueUser.class)
.filterKey("!=", KeyFactory.createKey("QueueUser", caller.id))
.order("__key__")
.order("-time")
.limit(5)
.keys();
インデックスが最新でない可能性があるため、最新のエンティティキーを取得しないことを理解します。だから私はキーを介して介入し、それによって各エンティティを取得します。 null以外のエンティティを取得した場合は、削除しようとします。私がそれに成功すれば、それはユーザーのマッチであると仮定します。このget-by-keyとdelete()はTransaction内部にあります。
while(keyIterator.hasNext()) {
QueueUser queueUser = null;
try {
final Key<QueueUser> key = keyIterator.next();
queueUser = ofy().transactNew(1, new Work<QueueUser>() {
public QueueUser run() {
QueueUser queueUser = ofy().load().key(key).now();
if(queueUser == null) {
logger.log(Level.WARNING, "queue user was already deleted");
return null;
}
else
ofy().delete().key(key).now();
return queueUser;
}
});
} catch (ConcurrentModificationException e) {
logger.log(Level.WARNING, "exception while deleting queue user. err: " + e.getMessage());
}
if (queueUser != null) {
// we have a match here
// delete calling user from the queue if it's there
ofy().delete().entity(new QueueUser(caller.id, null, null, null, null, null, null, null, null)).now();
break;
}
}
これはほとんどの場合動作しますが、ユーザーがキューにプッシュされてすぐには取得されないことがあります。リクエストの待ち時間は最大15秒です。照会は多くのエンティティーを戻しますが、ほとんどは削除され、一部はピア要求(予期されるConcurrentModificationException)によって削除されます。
私はここに何かが欠けているかどうか知りたいのですが、これを処理するにはより良い方法があります。
ありがとうございます。私はデータストアが私の要求に適していないことを理解しています。そして、はい、永続的なストレージの必要はありません。私はmemcacheを試してみます。私はmemcacheがデータストアでのみ使用されていると考えました。もし@cachedエンティティがmemcacheに見つからなければ、データストアから取得します。 – sandeepd
Memcacheに 'getIdentifiable'と' putIfUntouched'がありました。レイテンシは大幅に減少しました。ありがとう@stickfigure!まれに、2つのリクエストが正確なミリ秒で 'putIfUntouched'を実行している場合、' true'を返します。 – sandeepd