Google App Engineã§Global Transaction
Google App Engineã«ã¯Transactionã¯1ã¤ã®Entity Groupå
ã§ããã§ããªãã¨ããå¶éãããã¾ãã詳ããã¯ãApp EngineのEntityGroupを理解しよう - yvsu pron. yasãåç
§ãã¦ãã ããã
ããããã¨ããå£åº§ããå¥ã®å£åº§ã«ãéãæ¯è¾¼ããããªééã®ãã¿ã¼ã³ã§ãTransactionãå©ç¨ãããã¨ãã§ãã¾ãã(ãã¹ã¦ã®å£åº§ã1Entity Groupã«æ¼ãè¾¼ãã¨æ´æ°ãã¶ã¤ãã£ã¦ç¾å®çã§ã¯ãªããã)ãééãã¿ã¼ã³ã§æ´åæ§ãä¿ã¤ããã«ã¯ãçè«çã«ã¯æ¬¡ã®ããã«ãªãã¾ãã
http://songofcloud.gluegent.com/2009/11/blog-post_18.html
å®è£
ããã¨ãããªæãã
http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine
ã³ã¼ãã®éçã«ã¯ãããªã«ãããããã¨ããã¾ãããã質çãªé£æåº¦ã¯ããªãé«ããééããªãå®è£
ããã®ã¯ããªã大å¤ã§ãã
ããã§ãSlim3ã§è¤æ°ã®EntityGroupã«ã¾ãããTransactionããµãã¼ãããGlobalTransactionã®æ©è½ãå®è£ ãã¾ãããä½¿ãæ¹ã¯ç°¡åã§ã次ã®ããã«GlobalTransactionã¯ã©ã¹ã使ãã ãã
GlobalTransaction gtx = Datastore.beginGlobalTransaction();
Acount acount = gtx.get(Acount.class, key);
Acount acount2 = gtx.get(Acount.class, key2);
if (acount.getAmount() >= 1000) {
acount.setAmount(acount.getAmount() - 1000);
acount2.setAmount(acount2.getAmount() + 1000);
} else {
throw new IllegalStateException(...);
}
gtx.put(acount, acount2);
gtx.commit();
EntityGroupã®Transactionãããµãã¼ããã¦ããªãApp Engineã§ãSlim3ã¯ã©ã®ããã«Global Transaction(ä»å¾ã¯gtxã¨çç¥)ãå®è£ ãã¦ããã®ã§ããããã
Slim3ã¯ãgtxä¸ã«get, put, deleteãããã¼ã¿ã«å¯¾ãã¦Entity Groupãã¨ã«ããã¯ãããã¾ããããã¯ã«å¤±æãããConcurrentModificationExceptionãæããæ¢ã«ç¢ºä¿ããããã¯ãããã°èªåçã«éæ¾ãã¾ããããã¯ãæåããå ´åã¯ãä»ããæä½ãããå¿é
ããªãã®ã§ãå®å¿ãã¦ãã¼ã¿ãããããã¨ãã§ãã¾ãã
put, deleteãããã¼ã¿ã¯ãDatastoreã«ç´æ¥åæ ãããããã§ã¯ãªããgtxå
ã«Journalã¨ãã¦è¨é²ããã¦ãã¾ããJournalã«ã¯å¾ããput, deleteããå
容ãåç¾ã§ãããããªãã¼ã¿ãä¿åããã¦ãã¾ãã
commit()ãå¼ã³åºãããã¨ãæåã«ã¡ã¢ãªå ã®JournalãDatastoreã«æ ¼ç´ãã¾ããæ°¸ç¶åããã®ã¯ããã®å¾ã®Journalã®é©ç¨ãã§ã¼ãºã§ããã»ã¹ãè½ã¡ã¦ãã¾ã£ãå ´åã§ãå¾ããããä¸åº¦åå®è¡åºæ¥ãããã«ããããã§ããJournalã®ä¿åã«å¤±æããå ´åã¯ãæ¢ã«ä¿åããJournalãããã°åé¤ããããã¯ãéæ¾ãã¾ãã
Journalã®ä¿åãæåããããGlobalTransactionã®EntityãDatastoreã«æ ¼ç´ãã¾ããæ ¼ç´ã«æåãããããã®gtxã¯è«ççã«ã¯commitæ¸ã¿ã§æåããã¨ã¿ãªããã¾ããããã§ã¯ãgtxãä¿åããå¾ã«ãããã»ã¹ãè½ã¡ã¦ãã¾ã£ããã©ããªãã®ã§ããããã
Slim3ã§ã¯commitæ¸ã¿ã§ã¾ã å¦çããã¦ããªãgtxããªããcronã§5忝ã«ãã§ãã¯ãã¦ãã¾ããåå¨ãã¦ããã°ãJournalã®å
容ãDatastoreã«èªåçã«åæ ããã¾ãã
ããã»ã¹ãè½ã¡ã¦ããcronã§ãªã«ããªã¼ãããã¾ã§è¥å¹²ã¿ã¤ã ã©ã°ãããå¯è½æ§ã¯ããã¾ããããã¼ã¿ã¯ããã¯ãããã¾ã¾ãªã®ã§ãä»ããæ¸ãæããããå¿é
ã¯ããã¾ãããã¿ã¤ã ã©ã°ãæ°ã«ãªãå ´åã«ã¯ãcronã®ééãçãããã°å¤§ä¸å¤«ã§ãããããã»ã¹(App Server)ãè½ã¡ããã¨ã¯ã¾ããªãã®ã§ããã¾ãç¥çµè³ªã«ãªããªãã¦ã大ä¸å¤«ã ã¨æãã¾ããç¥çµè³ªãªæ¹ã¯ãcronã®ééãçããã¦ãã ããï½ã
gtxã®ä¿åã«æåããããJournalã®å 容ãDatastoreã«åæ ããã¾ãããã®å¦çã®éä¸ã§ããã»ã¹ãè½ã¡ãå ´åã§ãä¸è¨ã¨åæ§cronã§ãªã«ããªã¼ããã¾ãã
Journalã®åæ ãçµãã£ãããããã¯ãè§£é¤ããgtxã®EntityãDatastoreããåé¤ãã¦ããã®gtxã¯çµäºãã¾ãã
App Engineã§ã¯30ç§ä»¥å ã§ãã¹ã¦ã®å¦çãçµããªãã¨ãããªãã¨ããã«ã¼ã«ãããã30ç§ãè¶ ããã¨DeadlineExceedExceptionãçºçãã¾ããgtxä¸ã«DeadlineExceedExceptionãçºçããã¨ã©ããªã£ã¦ãã¾ãã®ã§ããããã
Slim3ã§ã¯Filterãè¨å®ããã¦ãã¦ãDeadlineExceedExceptionãçºçããã¨ãã«ãgtxã®ä¿ååãªããrollbackããããã«ãªã£ã¦ãã¾ããgtxã®ä¿åå¾ãªããcronã«ãã£ã¦èªåçã«ãªã«ããªã¼ããã¾ãã
ä»åã®GlobalTransactionã®ãã¸ãã¯ã¯ã@asigeru(ãããããã)ã«ããªãã¢ããã¤ã¹ããããã¾ãããæ¬å½ã«ãããã¨ãã
ã½ã¼ã¹ã³ã¼ãã¯ãããªæã
GlobalTransaction.java
Lock.java
Journal.java
GlobalTransactionServlet.java
DatastoreFilter.java
App Engineã®æå¤§ã«æ¸å¿µç¹ã§ãã£ãTransactionåé¡ã¯ããã§è§£æ±ºããã¾ãããããããã§ãããªããªéçºã§ãã¾ãããã§ããéåæ¼ç®ã ã¨ãFilterã«å¶éãããã¨ããjoinãã§ããªãã¨ãã¾ã ãåé¡ãæ®ã£ã¦ãããããªããã ã£ã¦?
éåæ¼ç®ã«é¢ãã¦ã¯ãcount, min, maxã¯Slim3ã§ãµãã¼ãããã¦ãã¾ããApp Engineã§éåæ¼ç®ã¯ç´æ¥ãµãã¼ãããã¦ãã¾ããããã¡ãã£ã¨ãã工夫ã§ãªãã¨ããªãã¾ãã
ä¾ãã°ãcountã¯ã©ããã£ã¦ãããã¨ããã¨ãApp Engineã«ã¯Keyã ããåã£ã¦ããKeys Only Queryãããã®ã§ãKeys Only Queryãå®è¡ãã¦ãã®ä»¶æ°ãcountããã°ããã®ã§ãã1ä¸ä»¶ã§ã1ç§ãããã§countã§ãã¾ãã
minã¯ã©ããããã¨ããã¨ãminãåãããåã®æé ã§ã½ã¼ãããoffset=0, limit=1ã§åã£ã¦ããã°ãæå°å¤ãä¸ç¬ã§åã£ã¦ããã¾ããmaxã¯ãã®éã§ãã
Queryã«ããFilterã«ã¯ããããå¶éãããã¾ãããSlim3ã§ã¯in-memoryã®Filterãç¨æãã¦ããã®ã§ããã®å¶éãè¶ ãããã¨ãã§ãã¾ããQueryã§ã¯ã§ããªãLikeã®%XXX%ã%XXXã«ç¸å½ããcontains, endsWithãå®è¡ã§ãã¾ãã
EmployeeMeta e = EmployeeMeta.get();
Listlist = Datastore.query(e)
.filterInMemory(e.name.endsWith("ABC"), e.name.notEqual("SCOTT"), e.salary.ge(1000))
.sortInMemory(e.name.desc)
.asList();
joinãã§ããªãåé¡ã¯ãjoinããããªãå ´åã¯ãã¢ãã«ã®è¨è¨ãæªãã¨ããã®ã¯ãã¡ãã£ã¨è¨ãéãã§ãKeyãæããã¦lazy loadingããã°ããã®ã§ããæè¿ã®O/R Mapperã¯åºæ¬çã«joinãæç¤ºçã«æ¸ãã®ã§ã¯ãªãlazy loadingããã¾ããããããã¨åãã§ããRDBMSã使ã£ã¦ããå ´åã¯ãlazy loadingããã¨ããã©ã¼ãã³ã¹ã®åé¡ãåºãå ´åãããã¾ãããBigtableã¯Keyã§getããã®ã¯éãã®ã§ããã»ã©åé¡ã«ã¯ãªãã¾ããã
ã»ããBigtableã¯å¶éãå¤ããã¦ä½¿ãè¾ãã¨ããã®ã¯ãéå»ã®è©±ã ã¨ãããã¨ãçè§£ã§ãã¾ãããããæä»£ã¯é²åãã¦ããã®ã§ãã
Slim3ã¯GlobalTransactionã®ããã¥ã¡ã³ããæ¸ãããRC1ããªãªã¼ã¹ãã¾ãããã¶ãæ¥é±ã®ã©ãããRC1ãªãªã¼ã¹å¾ã¯ãæ°æ©è½ã¯è¿½å ããããã°ãã£ãã¯ã«å¾¹ãã䏿å¾ãããã«æ£å¼çããªãªã¼ã¹ããäºå®ã
GAE/Jã®æ´å²ã¯ãå»å¹´ã®4æããå§ã¾ã£ãããã§ãããçµæ§è¦å´ã®é£ç¶ã§ããã使
ãã£ã¦ããã¨ãæ¢åã®ãã¬ã¼ã ã¯ã¼ã¯ãApp Engineã«å¯¾å¿ããããã¨ããããã
ä»å¾ã¯ãSlim3ã®ãããªApp Engine nativeãªãã¬ã¼ã ã¯ã¼ã¯ãåºã¦ãã¦ã©ãã©ã使ãããããªããã¨ã§ããããããã¯ãJavaã ãã§ãªããPythonãåãæµãã§ããkay-frameworkã¨ãã§ã¦ãã¦ãããã
http://kay-docs-jp.shehas.net/
2æ20æ¥(å)Java Cloud Meeting Fukuoka 2010ãããã¾ããGlobalTransaction以å¤ã«ãããããé¢ç½ããããããã®ã§ããã²ãç³è¾¼ã¿ãã ããããããããé¡ããã¾ãã
詳細ã¯ãã¡ãã
http://event.seasarfoundation.org/jcmf2010/about/
ç³ãè¾¼ã¿ã¯ãã¡ããããä¼å ´ä»£ã¨ããã£ã¦ææã«ãªã£ã¦ç³ã訳ããã¾ããããããã°ã£ã¦é¢ç½ã話ãã¾ããå¦çã¯ç¡æã«ãªãäºå®ã§ããè²§ä¹ãªã¤ãã³ããªã®ã§äºç®ãåºãªãã£ãããå¦çåã¯ç§ãæã¤ã®ã§å¤§ä¸å¤«ã
https://event.seasarfoundation.org/jcmf2010/attend/
@kisããªãã¨ã度ã¡ã¼ã«ã¼ã®è©±ãããããã§ãã
http://d.hatena.ne.jp/nowokay/20100208#1265596892