Skip to content

Instantly share code, notes, and snippets.

@ashigeru
Created February 14, 2010 15:37
Show Gist options
  • Save ashigeru/304094 to your computer and use it in GitHub Desktop.
Save ashigeru/304094 to your computer and use it in GitHub Desktop.
slim3 gtx discussion on #ajn5
// #ajn5 でビール飲みながら討論したgtxネタ。
差分は
>>
old
--
new
<<
な感じで書きます。
**** トランザクションエンティティの寄生
1つ目のEGへの操作はすべてローカルトランザクションを維持したまま行う。
トランザクションエンティティを1つ目のEGに寄生させることで、
1つ目のEGだけは1PCで操作できる。
ただし、EGロックエンティティの検査だけは1回行う必要アリ。
**** 物理クロック問題への対応
gtxエンティティをbegin(なし), committed(あり)の2-statesではなく、
begin(なし), committed, abortedの3-statesにする。
lockを時間切れで解除する際には、該当gtxエンティティをbegin->abortedにする。
その後、全体をアンロックしていく。
このとき、committedの場合はもちろんロックされたままにしておく必要がある。
すでにabortedなら全体をアンロック。
トランザクションステートを1点に集約させることで、物理クロック問題を解決。
この操作はread-modify-writeなのですべてトランザクショナルに行う必要があるが、
異常系なのであまり気にしない。
なお、GlobalTransaction.commitGlobalTransactionInternally()も
トランザクショナルにbegin->committedに変更する必要がある。
これは「トランザクションエンティティの寄生」と混ぜるとチェックが不要なので楽。
同様に、GlobalTransaction.rollback()は何よりも先にbegin->abortedにする。
**** 地味な最適化 (1)
txはgetから始まることが多いはずなので、エンティティの取得と同時に
ロックエンティティも取得する。
同一EGに対する2回目以降の操作ではロックエンティティの確認は不要。
==== GlobalTransaction.java
public Entity get(Key key) throws NullPointerException,
EntityNotFoundRuntimeException, ConcurrentModificationException {
>>
Key rootKey = DatastoreUtil.getRoot(key);
lock(rootKey);
--
// ロックエンティティとkeyのエンティティを同時に取得
// batch getすれば -10ms程度?
return lockAndGet(rootKey, key);
<<
return Datastore.getWithoutTx(key);
}
====
**** 地味な最適化 (2)
ロックが有効に働いているので、ジャーナルは別EGでもいいかも。
バッチオペレーションがRPCの先でパラレルに動くらしいので、多少効く?
==== Journal.java
public static Key createKey(Key targetKey) throws NullPointerException {
if (targetKey == null) {
throw new NullPointerException("The target key must not be null.");
}
>>
return KeyFactory.createKey(targetKey, KIND, 1);
--
// + batch get/put/deleteの高速化(?), ローカルトランザクションの競合回避
// - key lengthの制限 (同じKindなのでallocateIdsのキャッシュも有効)
return KeyFactory.createKey(KIND, KeyFactory.keyToString(targetKey));
<<
}
====
**** やや富豪的な最適化
==== GlobalTransaction.java
protected void commitGlobalTransaction() {
Journal.put(journalMap.values());
commitGlobalTransactionInternally();
try {
Journal.applyWithinGlobalTransaction(journalMap.values());
unlock();
>>
Datastore.deleteWithoutTx(globalTransactionKey);
--
// ジャーナルの削除はTQに積むかcron任せ
<<
} catch (DeadlineExceededException e) {
logger
.info("...");
submitRollForwardJob(null, globalTransactionKey, 1);
}
}
====
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment