Ehcache(2.9.x) - API Developer Guide, Transaction Support
About Transaction Support
Transactions are supported in versions of Ehcache 2.0 and higher. The 2.3.x or lower releases only support XA. However since ehcache 2.4 support for both Global Transactions with xa_strict and xa modes, and Local Transactions with local mode has been added.
All or Nothing
If a cache is enabled for transactions, all operations on it must happen within a transaction context otherwise a TransactionException will be thrown.
Change Visibility
The isolation level offered by Ehcache is READ_COMMITTED. Ehcache can work as an XAResource, in which case, full two-phase commit is supported. Specifically:
- All mutating changes to the cache are transactional including put(), remove(), putWithWriter(), removeWithWriter(), and removeAll().
- Mutating changes are not visible to other transactions in the local JVM or across the cluster until COMMIT has been called.
- Until then, reads such as by cache.get(...) by other transactions return the old copy. Reads do not block.
Transactional Modes
Transactional modes enable you to perform atomic operations on your caches and other data stores.
- local - When you want your changes across multiple caches to be performed atomically. Use this mode when you need to update your caches atomically. That is, you can have all your changes be committed or rolled back using a straightforward API. This mode is most useful when a cache contains data calculated from other cached data.
- xa - Use this mode when you cache data from other data stores, such as a DBMS or JMS, and want to do it in an atomic way under the control of the JTA API (“Java Transaction API”) but without the overhead of full two-phase commit. In this mode, your cached data can get out of sync with the other resources participating in the transactions in case of a crash. Therefore, only use this mode if you can afford to live with stale data for a brief period of time.
- xa_strict - Similar to “xa” but use it only if you need strict XA disaster recovery guarantees. In this mode, the cached data can never get out of sync with the other resources participating in the transactions, even in case of a crash. However, to get that extra safety the performance decreases significantly.
Requirements for Transactional Caches
The objects you store in your transactional cache must:
- Implement java.io.Serializable — This is required to store cached objects when the cache is distributed in a Terracotta cluster, and it is also required by the copy-on-read / copy-on-write mechanism used to implement isolation.
- Override equals and hashcode — These must be overridden because the transactional stores rely on element value comparison. See: ElementValueComparator and theelementValueComparator configuration setting.
Configuring Transactional Cache
Transactions are enabled on a cache-by-cache basis with the transactionalMode cache attribute. The allowed values are:
- xa_strict
- xa
- local
- off
The default value is “off.” In the following example, “xa_strict” is enabled.
<cache name="xaCache"
maxEntriesLocalHeap="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
diskExpiryThreadIntervalSeconds="1"
transactionalMode="xa_strict">
</cache>
Transactional Caches with Spring
Note the following when using Spring:
- If you access the cache from an @Transactional Spring-annotated method, begin/commit/rollback statements are not required in application code because they are emitted by Spring.
- Both Spring and Ehcache need to access the transaction manager internally, and therefore you must inject your chosen transaction manager into Spring's PlatformTransactionManager as well as use an appropriate lookup strategy for Ehcache.
- The Ehcache default lookup strategy might not be able to detect your chosen transaction manager. For example, it cannot detect the WebSphere transaction manager. For additional information, see the Transaction Managers.
- Configuring a <tx:method> with read-only=true could be problematic with certain transaction managers such as WebSphere.
Working with Global Transactions
Global Transactions are supported by Ehcache . Ehcache can act as an {XAResouce} to participate in JTA transactions under the control of a Transaction Manager. This is typically provided by your application server. However you can also use a third party transaction manager such as Bitronix.
To use Global Transactions, select either “xa_strict” or “xa” mode.
Implementation
Global transactions support is implemented at the Store level, through XATransactionStore and JtaLocalTransactionStore. The former decorates the underlying MemoryStore implementation, augmenting it with transaction isolation and two-phase commit support through an <XAResouce> implementation. The latter decorates a LocalTransactionStore-decorated cache to make it controllable by the standard JTA API instead of the proprietary TransactionController API.
During its initialization, the cache does a lookup of the Transaction Manager using the provided TransactionManagerLookup implementation. Then, using the TransactionManagerLookup.register(XAResouce), the newly created XAResource is registered. The store is automatically configured to copy every element read from the cache or written to it. Cache is copy-on-read and copy-on-write.
Failure Recovery
In support of the JTA specification, only prepared transaction data is recoverable. Prepared data is persisted onto the cluster and locks on the memory are held. This means that non-clustered caches cannot persist transaction data. Therefore, recovery errors after a crash might be reported by the transaction manager.
Recovery
At any time after something went wrong, an XAResource might be asked to recover. Data that has been prepared might either be committed or rolled back during recovery. XA data that has not yet been prepared is discarded. The recovery guarantee differs depending on the XA mode.
xa Mode
With “xa” mode, the cache doesn't get registered as an {XAResource} with the Transaction Manager but merely can follow the flow of a JTA transaction by registering a JTA {Synchronization}. The cache can end up inconsistent with the other resources if there is a JVM crash in the mutating node. In this mode, some inconsistency might occur between a cache and other XA resources (such as databases) after a crash. However, the cache data remains consistent because the transaction is still fully atomic on the cache itself.
xa_strict Mode
Sample Applications
The following sample applications showing how to use XA with a variety of technologies.
XA Sample Application
This sample application uses the JBoss application server. It shows an example using User managed transactions. Although most people use JTA from within a Spring or EJB container rather than managing it themselves, this sample application is useful as a demonstration. The following snippet from our SimpleTX servlet shows a complete transaction.
Ehcache cache = cacheManager.getEhcache("xaCache");
UserTransaction ut = getUserTransaction();
printLine(servletResponse, "Hello...");
try {
ut.begin();
int index = serviceWithinTx(servletResponse, cache);
printLine(servletResponse, "Bye #" + index);
ut.commit();
} catch(Exception e) {
printLine(servletResponse,
"Caught a " + e.getClass() + "! Rolling Tx back");
if(!printStackTrace) {
PrintWriter s = servletResponse.getWriter();
e.printStackTrace(s);
s.flush();
}
rollbackTransaction(ut);
}
You can download the source code for the sample from Terracotta Forge. The readme file explains how to set up the sample application.
XA Banking Application
This application represents a real-world scenario. A Web application reads <account transfer> messages from a queue and tries to execute the transfers.
With transaction mode enabled, failures are rolled back so that the cached account balance is always the same as the true balance summed from the database. This sample is a Spring-based web application running in a Jetty container. It has (embedded) the following components:
- A message broker (ActiveMQ)
- 2 databases (embedded Derby XA instances)
- 2 caches (transactional Ehcache)
All XA Resources are managed by Atomikos Transaction Manager. Transaction demarcation is done using Spring AOP's @Transactional annotation. You can run it with: mvn clean jetty:run. Then point your browser at: http://localhost:9080. To see what happens without XA transactions: mvn clean jetty:run -Dxa=no
You can download the source code for the sample from Terracotta Forge. The readme file explains how to set up the sample application.
Transaction Managers
Automatically Detected Transaction Managers
Ehcache automatically detects and uses the following transaction managers in the order shown below:
- GenericJNDI (e.g. GlassFish, JBoss, JTOM and any others that register themselves in JNDI at the standard location of java:/TransactionManager
- WebLogic (since 2.4.0)
- Bitronix
- Atomikos
No configuration is required. They work out-of-the-box. The first found is used.
Configuring a Transaction Manager
If your transaction manager is not in the list above or you want to change the priority, provide your own lookup class based on an implementation of net.sf.ehcache.transaction.manager.TransactionManagerLookup and specify it in place of the DefaultTransactionManagerLookup in ehcache.xml as shown below.
<transactionManagerLookup class= "com.mycompany.transaction.manager.MyTransactionManagerLookupClass"
properties="" propertySeparator=":"/>
Another option is to provide a different location for the JNDI lookup by passing the jndiName property to the DefaultTransactionManagerLookup. The example below provides the proper location for the transaction manager in GlassFish v3:
<transactionManagerLookup class="net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup"
properties="jndiName=java:appserver/TransactionManager" propertySeparator=";"/>
Working with Local Transactions
Local Transactions allow single-phase commit across multiple cache operations, across one or more caches, and in the same CacheManager.This lets you apply multiple changes to a CacheManager all in your own transaction. If you also want to apply changes to other resources, such as a database, open a transaction to them and manually handle commit and rollback to ensure consistency.
Local transactions are not controlled by a transaction manager. Instead there is an explicit API where a reference is obtained to a TransactionController for the CacheManager using cacheManager.getTransactionController() and the steps in the transaction are called explicitly. The steps in a local transaction are:
- transactionController.begin() - This marks the beginning of the local transaction on the current thread. The changes are not visible to other threads or to other transactions.
- transactionController.commit() - Commits work done in the current transaction on the calling thread.
- transactionController.rollback() - Rolls back work done in the current transaction on the calling thread. The changes done since begin are not applied to the cache. These steps should be placed in a try-catch block which catches TransactionException. If any exceptions are thrown, rollback() should be called. Local Transactions has its own exceptions that can be thrown, which are all subclasses of CacheException. They are:
- TransactionException - a general exception
- TransactionInterruptedException - if Thread.interrupt() was called while the cache was processing a transaction.
- TransactionTimeoutException - if a cache operation or commit is called after the transaction timeout has elapsed.
Introductory Video
Ludovic Orban, the primary author of Local Transactions, presents an introductory video on Local Transactions.
Configuration
Local transactions are configured as follows:
<cache name="sampleCache"
...
transactionalMode="local">
</cache>
Isolation Level
As with the other transaction modes, the isolation level is READ_COMMITTED.
Transaction Timeouts
transactionController.setDefaultTransactionTimeout(int defaultTransactionTimeoutSeconds)
The countdown starts when begin() is called. You might have another local transaction on a JDBC connection and you might be making multiple changes. If you think it might take longer than 15 seconds for an individual transaction, you can override the default when you begin the transaction with:
transactionController.begin(int transactionTimeoutSeconds)
Sample Code
The following example shows a transaction that performs multiple operations across two caches.
CacheManager cacheManager = CacheManager.getInstance();
try {
cacheManager.getTransactionController().begin();
cache1.put(new Element(1, "one"));
cache2.put(new Element(2, "two"));
cache1.remove(4);
cacheManager.getTransactionController().commit();
} catch (CacheException e) {
cacheManager.getTransactionController().rollback()
}
Performance Considerations
Managing Contention
If two transactions attempt to perform a cache operation on the same element, the following rules apply:
- The first transaction gets access
- The following transactions block on the cache operation until either the first transaction completes or the transaction timeout occurs.
Note: When an element is involved in a transaction, it is replaced with a new element with a marker that is locked, along with the transaction ID.
What Granularity of Locking is Used?
Ehcache uses soft locks stored in the Element itself and is on a key basis.
Performance Comparisons
Any transactional cache adds an overhead, which is significant for writes and nearly negligible for reads. Compared to transactionalMode="off", the time it takes to perform writes will be noticeably slower with either “xa” or “local” specified, and “xa_strict” will be the slowest.
Within the modes the relative time take to perform writes, where off = 1, is as follows:
- off - no overhead
- xa_strict - 20 times slower
- xa - 3 times slower
- local - 3 times slower The relative read performance is:
- off - no overhead
- xa_strict - 20 times slower
- xa - 30% slower
- local - 30% slower
Use “xa_strict” only when full guarantees are required, otherwise use one of the other modes.
Potential Timeouts in a Transactional Cache
Why Do Some Threads Regularly Time Out and Throw an Exception?
In transactional caches, write locks are in force whenever an element is updated, deleted, or added. With concurrent access, these locks cause some threads to block and appear to deadlock. Eventually the deadlocked threads time out (and throw an exception) to avoid being stuck in a deadlock condition.
Transactions in Write-Behind and Write-Through Caches
If your transaction-enabled cache is being used with a writer, write operations are queued until transaction commit time. A solely write-through approach would have its potential XAResource participate in the same transaction.
Write-behind is supported, however it should probably not be used with an XA transactional cache because the operations would never be part of the same transaction. Your writer would also be responsible for obtaining a new transaction.
Support for Other Transaction Systems
Is IBM WebSphere Transaction Manager supported?
Mostly. The “xa_strict” mode is not supported due to each version of WebSphere being a custom implementation. That is, it has no stable interface to implement against. However, “xa”, which uses TransactionManager callbacks, and “local” modes are supported.
When using Spring, make sure your configuration is set up correctly with respect to the PlatformTransactionManager and the WebSphere TM.
To confirm that Ehcache will succeed, try to manually register a com.ibm.websphere.jtaextensions.SynchronizationCallback in the com.ibm.websphere.jtaextensions.ExtendedJTATransaction. Get java:comp/websphere/ExtendedJTATransaction from JNDI, cast that to com.ibm.websphere.jtaextensions.ExtendedJTATransaction and call the registerSynchronizationCallbackForCurrentTran method. If you succeed, Ehcache should too.
Are Hibernate Transactions Supported?
Ehcache is a “transactional” cache for Hibernate purposes. The net.sf.ehcache.hibernate.EhCacheRegionFactory supports Hibernate entities configured with <cache usage="transactional"/>.
How Do I Make WebLogic 10 Work with a Transactional Cache?
WebLogic uses an optimization that is not supported by the Ehcache implementation. By default WebLogic 10 spawns threads to start the transaction on each XAResource in parallel. Because we need transaction work to be performed on the same Thread, you must turn off this optimization by setting the parallel-xa-enabled option to false in your domain configuration:
<jta>
...
<checkpoint-interval-seconds>300</checkpoint-interval-seconds>
<parallel-xa-enabled>false</parallel-xa-enabled>
<unregister-resource-grace-period>30</unregister-resource-grace-period>
...
</jta>
How Do I Make Atomikos Work with a Cache in “xa” Mode?
Atomikos has a bug, which makes the “xa” mode's normal transaction termination mechanism unreliable. There is an alternative termination mechanism built in that transaction mode that is automatically enabled when net.sf.ehcache.transaction.xa.alternativeTerminationMode is set to true or when Atomikos is detected as the controlling transaction manager.
This alternative termination mode has strict requirement on the way threads are used by the transaction manager and Atomikos’s default settings will not work unless you configure the following property as shown below:
com.atomikos.icatch.threaded_2pc=false
Ehcache(2.9.x) - API Developer Guide, Transaction Support的更多相关文章
- Ehcache(2.9.x) - API Developer Guide, Write-Through and Write-Behind Caches
About Write-Through and Write-Behind Caches Write-through caching is a caching pattern where writes ...
- Ehcache(2.9.x) - API Developer Guide, Key Classes and Methods
About the Key Classes Ehcache consists of a CacheManager, which manages logical data sets represente ...
- Ehcache(2.9.x) - API Developer Guide, Cache Usage Patterns
There are several common access patterns when using a cache. Ehcache supports the following patterns ...
- Ehcache(2.9.x) - API Developer Guide, Cache Eviction Algorithms
About Cache Eviction Algorithms A cache eviction algorithm is a way of deciding which element to evi ...
- Ehcache(2.9.x) - API Developer Guide, Basic Caching
Creating a CacheManager All usages of the Ehcache API start with the creation of a CacheManager. The ...
- Ehcache(2.9.x) - API Developer Guide, Searching a Cache
About Searching The Search API allows you to execute arbitrarily complex queries against caches. The ...
- Ehcache(2.9.x) - API Developer Guide, Using Explicit Locking
About Explicit Locking Ehcache contains an implementation which provides for explicit locking, using ...
- Ehcache(2.9.x) - API Developer Guide, Blocking and Self Populating Caches
About Blocking and Self-Populating Caches The net.sf.ehcache.constructs package contains some applie ...
- Ehcache(2.9.x) - API Developer Guide, Cache Loaders
About Cache Loaders A CacheLoader is an interface that specifies load() and loadAll() methods with a ...
随机推荐
- python challenge第1关--NoteBook上的“乱码”
在 python challenge第0关中已经得到第1关的地址了: http://www.pythonchallenge.com/pc/def/map.html 一.观察地址栏和标签: What a ...
- MVC神韵---你想在哪解脱!(十二)
追加一条电影信息 运行应用程序,在浏览器中输入“http://localhost:xx/Movies/Create”,在表单中输入一条电影信息,然后点击追加按钮,如图所示. 点击追加按钮进行提交,表单 ...
- UITableView section header 不固定
iOS系统自带的UITableView,当数据分为多个section的时候,在UITableView滑动的过程中,默认section header是固定在顶部的,滑动到下一个section的时候,下一 ...
- 关于本人遇到的nodejs的一些错误信息
window xp.win7 32位下安装node.js mongodb驱动 1.cmd->npm install mongodb 2.新建一个环境变量NODE_PATH 3.把Nodejs目录 ...
- 我所理解的设计模式(C++实现)——备忘录模式(Memento Pattern)
概述: 我们玩单机游戏的时候总会遇到老婆大人的各位事情,一会去买瓶醋了,一会去打个酱油了,会耽误我们玩游戏的进程,但是此时我们能有“保存游戏”这个宝贝,我们的主基地不会在我们打酱油的时候被对手拆掉. ...
- 【转】2013年中国IT业10大公司
转自:http://www.chinaz.com/news/2013/1217/331446.shtml?zyy 1.最得志的公司:小米 在2013年,再没有一家公司像小米这样志得意满,即便看看所有的 ...
- Android学习笔记(2)
今天我继续看Mars老师的Android开发视频教程,看到一个“深入LinearLayout”的时候,发现一个比较好玩的技巧. 控件的layout_weight属性,他是父控件剩余空间的比例. 如果把 ...
- Codeforces Round #329 (Div. 2) B. Anton and Lines 逆序对
B. Anton and Lines Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/pr ...
- Codeforces Round #250 (Div. 1) A. The Child and Toy 水题
A. The Child and Toy Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/438/ ...
- mysql备份工具 :mysqldump mydumper Xtrabackup 原理
备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之百的数据(取决于备份周期),但至少能将损失降到最低.衡量备份恢复有两个重要的指标:恢复点目标(RPO)和恢复时间目标(R ...