Wildfly - Infinispan 事务配置
Wildfly - Infinispan Transactions configuration
我正在使用 Wildfly 8.2 及其随附的 Infinispan (6.0.2),我正在尝试将某些 Oracle 数据库 table 中的所有值缓存到 Infispan 缓存中。在大多数情况下,它似乎有效,但有时却无效。访问 cache.values()
时(这对于性能来说也可能不是一个好主意,但这只是一个例子)它有时看起来是空的,有时它包含正确的值。因此,我认为交易配置可能存在问题。当使 Infinispan 缓存成为非事务缓存时,问题就消失了。
访问缓存和数据库的服务是一个具有容器管理事务的 EJB bean。在服务初始化时,所有数据都从数据库加载(它不包含很多条目)。
根据 what's new in ejb 3.2,应该可以在 EJB Singleton
bean 中以事务方式访问数据库。
数据源和Infinispan缓存的配置是否正确?我可以将非 XA 数据源与 Infinispan 一起使用并期望它始终如一地工作吗?根据 Infinispan doc,NON_XA
意味着 Infinispan 正在注册为 Synchronization,这应该没问题,不是吗?
缓存在 standalone-full.xml 中配置如下(删除 <transaction mode="NON_XA" locking="PESSIMISTIC"/>
问题消失,代价是没有事务缓存):
<cache-container name="cacheContainer" start="EAGER">
<local-cache name="my_table_cache">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="NON_XA" locking="PESSIMISTIC"/>
</local-cache>
</cache-container>
Oracle DS定义如下
<datasource jndi-name="java:jboss/datasources/myDataSource" pool-name="dataSource" enabled="true">
<connection-url>jdbc:oracle:thin:@127.0.0.1:1523:orcl</connection-url>
<driver>ojdbc7.jar</driver>
<pool>
<max-pool-size>25</max-pool-size>
</pool>
<security>
<user-name>myuser</user-name>
<password>myuser</password>
</security>
<timeout>
<blocking-timeout-millis>5000</blocking-timeout-millis>
</timeout>
</datasource>
我的服务(dao 使用简单的 JDBC 操作,而不是 Hibernate 或类似的)
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class MyService {
@Resource(lookup = "java:jboss/infinispan/container/cacheContainer")
protected EmbeddedCacheManager cm;
protected Cache<String, MyEntity> cache;
@PostConstruct
private void init() {
try {
cache = getCache();
} catch (SQLException ex) {
log.fatal("could not initialize caches", ex);
throw new IllegalStateException(ex);
}
}
public Cache<String, MyEntity> getCache() {
Cache<String, MyEntity> cache = cm.getCache(getCacheName(), true);
fillCache(cache);
return cache;
}
protected void fillCache(Cache<String, MyEntity> cache) {
List<MyEntity> entities = myDao.getEntities();
for (MyEntity e : entities) {
cache.put(e.getKey, e);
}
}
public MyEntity getEntity(String key) {
return cache.get(key);
}
public void insert(MyEntity entity) {
myDao.insert(entity);
cache.put(entity.getKey(), entity);
}
public void debug() {
log.debug(cache.values());
}
}
当使用NON_XA事务时,未能在缓存中提交TX可能会让事务提交,并且您不会得到任何异常告诉您缓存不一致。
至于 cache.values()
,在 Infinispan 7.0 之前,它 returns 只有本地条目,但是在您的情况下这无关紧要 - 使用本地缓存,所有条目都是本地的。此操作的事务一致性应该保持。我没有发现您的配置有任何问题。
一般来说,我建议在 Hibernate ORM 中使用 Infinispan 模块,而不是尝试自己进行缓存,如您在此处所示。
根据接受的答案,配置是正确的。
如果有人遇到类似问题:
问题似乎是像 MyService.getEntity()
这样的读取方法之一在某些特定于应用程序的上下文中被极其频繁地调用(我不知道),因此使用乐观锁定和 READ_COMMITTED 而不是 REPEATABLE_READ 似乎使它按预期工作。
我正在使用 Wildfly 8.2 及其随附的 Infinispan (6.0.2),我正在尝试将某些 Oracle 数据库 table 中的所有值缓存到 Infispan 缓存中。在大多数情况下,它似乎有效,但有时却无效。访问 cache.values()
时(这对于性能来说也可能不是一个好主意,但这只是一个例子)它有时看起来是空的,有时它包含正确的值。因此,我认为交易配置可能存在问题。当使 Infinispan 缓存成为非事务缓存时,问题就消失了。
访问缓存和数据库的服务是一个具有容器管理事务的 EJB bean。在服务初始化时,所有数据都从数据库加载(它不包含很多条目)。
根据 what's new in ejb 3.2,应该可以在 EJB Singleton
bean 中以事务方式访问数据库。
数据源和Infinispan缓存的配置是否正确?我可以将非 XA 数据源与 Infinispan 一起使用并期望它始终如一地工作吗?根据 Infinispan doc,NON_XA
意味着 Infinispan 正在注册为 Synchronization,这应该没问题,不是吗?
缓存在 standalone-full.xml 中配置如下(删除 <transaction mode="NON_XA" locking="PESSIMISTIC"/>
问题消失,代价是没有事务缓存):
<cache-container name="cacheContainer" start="EAGER">
<local-cache name="my_table_cache">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="NON_XA" locking="PESSIMISTIC"/>
</local-cache>
</cache-container>
Oracle DS定义如下
<datasource jndi-name="java:jboss/datasources/myDataSource" pool-name="dataSource" enabled="true">
<connection-url>jdbc:oracle:thin:@127.0.0.1:1523:orcl</connection-url>
<driver>ojdbc7.jar</driver>
<pool>
<max-pool-size>25</max-pool-size>
</pool>
<security>
<user-name>myuser</user-name>
<password>myuser</password>
</security>
<timeout>
<blocking-timeout-millis>5000</blocking-timeout-millis>
</timeout>
</datasource>
我的服务(dao 使用简单的 JDBC 操作,而不是 Hibernate 或类似的)
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class MyService {
@Resource(lookup = "java:jboss/infinispan/container/cacheContainer")
protected EmbeddedCacheManager cm;
protected Cache<String, MyEntity> cache;
@PostConstruct
private void init() {
try {
cache = getCache();
} catch (SQLException ex) {
log.fatal("could not initialize caches", ex);
throw new IllegalStateException(ex);
}
}
public Cache<String, MyEntity> getCache() {
Cache<String, MyEntity> cache = cm.getCache(getCacheName(), true);
fillCache(cache);
return cache;
}
protected void fillCache(Cache<String, MyEntity> cache) {
List<MyEntity> entities = myDao.getEntities();
for (MyEntity e : entities) {
cache.put(e.getKey, e);
}
}
public MyEntity getEntity(String key) {
return cache.get(key);
}
public void insert(MyEntity entity) {
myDao.insert(entity);
cache.put(entity.getKey(), entity);
}
public void debug() {
log.debug(cache.values());
}
}
当使用NON_XA事务时,未能在缓存中提交TX可能会让事务提交,并且您不会得到任何异常告诉您缓存不一致。
至于 cache.values()
,在 Infinispan 7.0 之前,它 returns 只有本地条目,但是在您的情况下这无关紧要 - 使用本地缓存,所有条目都是本地的。此操作的事务一致性应该保持。我没有发现您的配置有任何问题。
一般来说,我建议在 Hibernate ORM 中使用 Infinispan 模块,而不是尝试自己进行缓存,如您在此处所示。
根据接受的答案,配置是正确的。
如果有人遇到类似问题:
问题似乎是像 MyService.getEntity()
这样的读取方法之一在某些特定于应用程序的上下文中被极其频繁地调用(我不知道),因此使用乐观锁定和 READ_COMMITTED 而不是 REPEATABLE_READ 似乎使它按预期工作。