【发布时间】:2023-03-17 15:55:02
【问题描述】:
情况:
我有一张包含数千条记录的清算表。它们被分成例如包。 500 条记录。然后每个数据包通过消息驱动 Beans 发送到 AS。 AS根据每条记录的内容(如货币、validStart、validEnd)计算出一个key,并需要将该key(连同内容的组合)存储在数据库中。
请求:
为了避免重复,我需要一个集中的“工具”来计算密钥并存储它们,从而通过缓存这些密钥和记录来减少与数据库的通信。
现在我尝试为每个包处理线程使用在实用程序类实现中访问的本地 Infinispan 缓存。这导致了这样一个事实,即多个包计算了相同的密钥,因此在数据库中插入了重复项。或者有时我遇到了死锁。
我尝试通过静态变量实现“锁定”以在数据库插入期间阻止对缓存的访问,但没有成功。 下一个尝试是使用复制的、分别分布的 Infinispan 缓存。这并没有改变 AS 行为的结果。
我的最后一个想法是实现为 bean 管理的单例会话 bean,以在插入数据库期间获取事务锁。
AS 目前以单机模式运行,但近期会迁移到集群中,因此首选高可用性解决方案。
恢复中:
在创建(键、值)对以避免重复时锁定 Infinispan 缓存访问的正确方法是什么?
更新:
@cruftex:我的请求是:我有一组(键,值)对,应该被缓存。如果应该插入新记录,则对其应用算法并计算密钥。然后检查缓存是否存在键,并将值附加到新记录中。但如果 Value 不存在,则应创建并存储在数据库中。
缓存需要使用 Infinispan 来实现,因为 AS 应该运行在集群中。存在用于创建密钥的算法。也在数据库中插入值(通过 JDBC 或实体)。但我有一个问题,即使用消息驱动 Bean(因此在 AS 中使用多线程)相同的(键、值)对是在不同的线程中计算的,因此每个线程都试图在数据库中插入值(我想避免!)。
@戴夫:
public class Cache {
private static final Logger log = Logger.getLogger(Cache.class);
private final Cache<Key, FullValueViewer> fullCache;
private HomeCache homes; // wraps EntityManager
private final Session session;
public Cache(Session session, EmbeddedCacheManager cacheContainer, HomeCache homes) {
this.session = session;
this.homes = homes;
fullCache = cacheContainer.getCache(Const.CACHE_CONDCOMBI);
}
public Long getId(FullValueViewer viewerWithoutId) {
Long result = null;
final Key key = new Key(viewerWithoutId);
FullValueViewer view = fullCache.get(key);
if(view == null) {
view = checkDatabase(viewerWithoutId);
if(view != null) {
fullCache.put(key, view);
}
}
if(view == null) {
view = createValue(viewerWithoutId);
// 1. Try
fullCache.put(key, view);
// 2. Try
// if(!fullCache.containsKey(key)) {
// fullCache.put(key, view);
// } else {
// try {
// homes.condCombi().remove(view.idnr);
// } catch (Exception e) {
// log.error("remove", e);
// }
// }
// 3. Try
// synchronized(fullCache) {
// view = createValue(viewerWithoutId);
// fullCache.put(key, view);
// }
}
result = view.idnr;
return result;
}
private FullValueViewer checkDatabase(FullValueViewer newView) {
FullValueViewer result = null;
try {
CondCombiBean bean = homes.condCombi().findByTypeAndKeys(_parameters_);
result = bean.getAsView();
} catch (FinderException e) {
}
return result;
}
private FullValueViewer createValue(FullValueViewer newView) {
FullValueViewer result = null;
try {
CondCombiBean bean = homes.condCombi().create(session.subpk);
bean.setFromView(newView);
result = bean.getAsView();
} catch (Exception e) {
log.error("createValue", e);
}
return result;
}
private class Key {
private final FullValueViewer view;
public Key(FullValueViewer v) {
this.view = v;
}
@Override
public int hashCode() {
_omitted_
}
@Override
public boolean equals(Object obj) {
_omitted_
}
}
}
我尝试使用 Wildfly 的缓存配置:
<cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
<local-cache name="default">
<transaction mode="BATCH"/>
</local-cache>
</cache-container>
<cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
<transport lock-timeout="60000"/>
<distributed-cache name="default" mode="ASYNC"/>
</cache-container>
【问题讨论】:
-
请发布您实际编写/尝试过的内容; Stack Overflow 在这里帮助您解决编码问题,而不是为您编写所有内容:)
-
不清楚你要什么。您想知道如何生成密钥吗?在缓存中存储一些东西?或者使用缓存生成密钥(为什么?)?应该如何从数据中导出key?如果您想生成唯一的密钥,例如查看 UUID 算法,您不需要任何通信。
标签: java caching cluster-computing wildfly infinispan