Created
February 14, 2010 15:37
-
-
Save ashigeru/304094 to your computer and use it in GitHub Desktop.
slim3 gtx discussion on #ajn5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// #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