0

我们正在使用 Infinispan 控制在 Payara 服务器(Enterprise v 5.22.0)上运行的 JEE 应用程序中的分布式缓存(复制缓存),使用 Java 8(OpenJDK 64 位服务器 VM 供应商:Azul Systems, Inc. 版本:25.262 -b19)

为了在启动多个实例时控制应用程序的启动,我们创建了一个名为 Mutex 的 PESSIMISTIC 锁定缓存,用于“锁定”集群以允许 1 个实例加载缓存而其他实例等待。获取锁的第一个实例读取数据库并加载许多其他缓存,这些缓存都配置为 OPTIMISISTIC 锁定。这些缓存“放置”都发生在外部 Mutex 事务中。OPTMISTIC 缓存使用 state-transfer enabled=true 定义,因此当实例从数据库加载缓存完成并通过提交外部事务释放互斥锁时,缓存也会在所有实例上更新。

在加载 OPTIMISTIC 缓存时,我们有时会使用 CACHE1 中的条目来驱动 CACHE2 的加载(我们确实有更有意义的名称,但这里的细节并不重要)。因此,加载 CACHE1 后,我们使用 CACHE1.values() 将条目编排到 CACHE2.put() 中。

现在问题...

在 V9.4.20.Final(及以下),上述过程有效。在 V10.x(也是 V.11.0.5.Final)这不起作用。我们已经调试了我们的代码,发现在 V10.x 中,写入 CACHE1 的条目(所有缓存都是隔离 =“READ_COMMITTED”)在尝试加载 CACHE2 时使用 CACHE1.values() 是不可见的。只是为了确认相同的代码在 V9 中有效,其中 CACHE1.values() 确实按预期返回值,因为它在同一事务中并且应该能够看到条目。

如果在 V10 中我们没有外部 Mutex 事务或在尝试读取 CACHE1 之前提交外部 Mutex 事务,那么一切正常。

问题:

事务性是否已更改以删除嵌套事务中写入的条目对写入它们的进程的可见性?

我尝试过 Weblogic 12.2.13,怀疑容器事务管理器的行为可能有所不同,但没有。它在 V10 上失败,在 Weblogic 上与 V9 一起工作。

我可以在 zip(eclipse / gradle 项目)中提供完整的代码复制器,但这里是代码片段:

CacheServiceImpl 有一个方法 exclusivePutAndGetAll 和名称为 LOCK_KEY 的锁,可以用布尔值调用它来控制是在“互斥”父事务提交之前还是之后读取条目:

@Override
    public <K, V> Collection<V> exclusivePutAndGetAll(String cacheName, Map<K, V> values, boolean insideMutex) throws Exception {

        Collection<V> returnValues = null;

        LOGGER.debug("mutex manager is " + mutexManager.getManagerHash());
        LOGGER.debug("cache manager is " + cacheManager.getManagerHash());

        LOGGER.info("Acquiring mutex lock before starting context");
        mutexManager.startTransactionAndAcquireMutex("LOCK_KEY");

        putAll(cacheName, values);

        if (insideMutex) {
            returnValues = getAll(cacheName); // this only works and returns values with V9 !!
        }

        mutexManager.commitTransaction();
        LOGGER.info("Mutex lock released after starting context.");

        if (!insideMutex) {
            returnValues = getAll(cacheName); 
        }

        return returnValues;
    }

这是 mutexManager 的 startTransactionAndAcquireMutex,它开始事务并使用提供的“LOCK_KEY”锁定名为 Mutex 的缓存

@Override
    public boolean startTransactionAndAcquireMutex(String mutexName) {
        final TransactionManager transactionManager = mutexCache.getTransactionManager();
        LOGGER.debug("Mutex cache TransactionManager is " + transactionManager.getClass());

        try {
            transactionManager.begin();
        } catch (NotSupportedException | SystemException ex) {
            throw new CacheException("Unable to start transaction for mutex " + mutexName, ex);
        }
        return acquireMutex(mutexName);
    }

这是获取锁的 mutexManager:

@Override
    public boolean acquireMutex(String mutexName) {
        final TransactionManager transactionManager = mutexCache.getTransactionManager();

        boolean lockResult = false;
        try {
            if (transactionManager.getStatus() == Status.STATUS_ACTIVE) {
                lockResult = mutexCache.lock(mutexName);
            }
        } catch (final SystemException ex) {
            throw new CacheException("Unable to lock mutex " + mutexName, ex);
        }

        return lockResult;
    }

最后是 XML 中的缓存配置

<?xml version="1.0" encoding="UTF-8"?>
<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="urn:infinispan:config:10.1 http://www.infinispan.org/schemas/infinispan-config-10.1.xsd" 
    xmlns="urn:infinispan:config:10.1">

    <jgroups>
        <stack-file name="tcp-cdl" path="cluster-jgroups.xml"/>
    </jgroups>

    <cache-container name="SampleCacheManager" statistics="true">
        <transport stack="tcp-cdl"/>
        <jmx duplicate-domains="true"/>
        
        <replicated-cache-configuration name="replicated-cache-template" statistics="true" mode="SYNC" remote-timeout="120000">
            <locking isolation="READ_COMMITTED" acquire-timeout="120000" write-skew="false" concurrency-level="150" striping="false"/>
            <state-transfer enabled="true" timeout="240000" chunk-size="10000"/>
            <transaction
                transaction-manager-lookup="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
                mode="NON_XA"
                locking="OPTIMISTIC">
            </transaction>   
        </replicated-cache-configuration>
        
        <replicated-cache name="Mutex" configuration="replicated-cache-template">
            <transaction locking="PESSIMISTIC" />
        </replicated-cache>   
        
    </cache-container>
</infinispan>
4

0 回答 0