org.apache.geode.cache.UnsupportedOperationInTransactionException

huangapple go评论96阅读模式
英文:

org.apache.geode.cache.UnsupportedOperationInTransactionException

问题

在建立多对多关系时,在更新缓存条目时遇到以下异常。

org.apache.geode.cache.UnsupportedOperationInTransactionException: 在分布式事务期间,预期目标=192.168.1.2(cacheServer2:7756)<v1>:41001的大小为1 {[/__PR/_B__User_101]},但实际得到了2 {[[], [DistTxThinEntryState: ,regionVersion=2 ,tailKey=440 ,memberID=null]]}
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.populateEntryEventMap(DistTXStateProxyImplOnCoordinator.java:576)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.doPrecommit(DistTXStateProxyImplOnCoordinator.java:484)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.commit(DistTXStateProxyImplOnCoordinator.java:88)
at org.apache.geode.internal.cache.TXManagerImpl.commit(TXManagerImpl.java:426)
at com.trendcore.cache.peertopeer.service.UserServiceImpl.attachRoleToUser(UserServiceImpl.java:108)
at com.trendcore.cache.peertopeer.CacheApplication.attachRoleToUser(CacheApplication.java:121)

缓存配置 -> 这是具有2个区域的点对点配置。

Properties properties = new Properties();
properties.setProperty("locators", "localhost[13489]");
properties.setProperty("mcast-address", "224.0.0.0");
properties.setProperty("mcast-port", "0");
properties.setProperty(NAME, "cacheServer1");

CacheFactory cacheFactory = new CacheFactory(this.cacheConfiguration);
cache = cacheFactory.create();

用户区域

RegionFactory<Long, User> regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
userRegion = regionFactory.create(USER_REGION);

角色区域

RegionFactory<Long, Role> regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
roleRegion = regionFactory.create(ROLE_REGION);

用户模型位于用户区域

public class User implements  Serializable{
    private Long id;
    private String username;
    private Map<Long,Object> roles;

    //Getters , Setters

    public void addRole(Long roleId) {
        roles.put(roleId,null);
    }
}

角色模型位于角色区域

public class Role implements Serializable {

    private Long id;
    private String roleName;

    //getters , setters
}

用户和角色通过以下代码插入到各自的区域中。

插入用户:

public void insertUser(User user) {
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
        cacheTransactionManager.begin();
        userRegion.put(user.getId(), user);
        cacheTransactionManager.commit();
    } catch (Exception e) {
        cacheTransactionManager.rollback();
    }
}

插入角色:

public void insertRole(Role role) {
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
        cacheTransactionManager.begin();
        roleRegion.put(role.getId(), role);
        cacheTransactionManager.commit();
    } catch (Exception e) {
        cacheTransactionManager.rollback();
    }
}

当将任何角色ID放入现有缓存用户对象时,将抛出上述异常。

将角色附加到用户:

public void attachRoleToUser(Long userId, Long roleId) {
    Region<Long, User> userRegion = cache.getRegion(USER_REGION);
    Region<Long, Role> roleRegion = cache.getRegion("Role");
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
        cacheTransactionManager.setDistributed(true);
        cacheTransactionManager.begin();

        Role role = roleRegion.get(roleId);

        if (role != null) {
            User user = userRegion.get(userId);
            user.addRole(role.getId());
            userRegion.put(userId,user);
        }
        cacheTransactionManager.commit();
    } catch (Exception e) {
        try {
            cacheTransactionManager.rollback();
        }catch (Exception rbe){

        }
        throw new RuntimeException(e);
    }
}

在这种情况下,任何指导将不胜感激。

英文:

Getting below exception while updating entry in the cache while establishing Many to Many relation.

org.apache.geode.cache.UnsupportedOperationInTransactionException: Expected size of 1 {[/__PR/_B__User_101]} for target=192.168.1.2(cacheServer2:7756)&lt;v1&gt;:41001 during a distributed transaction but got 2 {[[], [DistTxThinEntryState:  ,regionVersion=2 ,tailKey=440 ,memberID=null]]}
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.populateEntryEventMap(DistTXStateProxyImplOnCoordinator.java:576)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.doPrecommit(DistTXStateProxyImplOnCoordinator.java:484)
at org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.commit(DistTXStateProxyImplOnCoordinator.java:88)
at org.apache.geode.internal.cache.TXManagerImpl.commit(TXManagerImpl.java:426)
at com.trendcore.cache.peertopeer.service.UserServiceImpl.attachRoleToUser(UserServiceImpl.java:108)
at com.trendcore.cache.peertopeer.CacheApplication.attachRoleToUser(CacheApplication.java:121)

Cache Configuration -> It's Peer to Peer configration with 2 regions.

Properties properties = new Properties();
properties.setProperty(&quot;locators&quot;, &quot;localhost[13489]&quot;);
properties.setProperty(&quot;mcast-address&quot;, &quot;224.0.0.0&quot;);
properties.setProperty(&quot;mcast-port&quot;, &quot;0&quot;);
properties.setProperty(NAME, &quot;cacheServer1&quot;);

CacheFactory cacheFactory = new CacheFactory(this.cacheConfiguration);
cache = cacheFactory.create();

User Region

RegionFactory&lt;Long, User&gt; regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
    userRegion = regionFactory.create(USER_REGION);

Role Region

RegionFactory&lt;Long, Role&gt; regionFactory = this.cache.createRegionFactory(RegionShortcut.PARTITION);
    roleRegion = regionFactory.create(ROLE_REGION);

User model resides in User region

public class User implements  Serializable{
    private Long id;
    private String username;
    private Map&lt;Long,Object&gt; roles;

    //Getters , Setters

    public void addRole(Long roleId) {
            roles.put(roleId,null);
    }
}

Role model resides in Role region

public class Role implements Serializable {

    private Long id;
    private String roleName;
    
    //getters , setters
}

Users and roles are inserted in the respective regions using below code.

public void insertUser(User user) {
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
        cacheTransactionManager.begin();
        userRegion.put(user.getId(), user);
        cacheTransactionManager.commit();
    } catch (Exception e) {
        cacheTransactionManager.rollback();
    }
}



public void insertRole(Role role) {
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
        cacheTransactionManager.begin();
        roleRegion.put(role.getId(), role);
        cacheTransactionManager.commit();
    } catch (Exception e) {
        cacheTransactionManager.rollback();
    }
}

When any roleIds are put in existing cache user object then above exception is thrown.

public void attachRoleToUser(Long userId, Long roleId) {
    Region&lt;Long, User&gt; userRegion = cache.getRegion(USER_REGION);
    Region&lt;Long, Role&gt; roleRegion = cache.getRegion(&quot;Role&quot;);
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
        cacheTransactionManager.setDistributed(true);
        cacheTransactionManager.begin();

        Role role = roleRegion.get(roleId);

        if (role != null) {
            User user = userRegion.get(userId);
            user.addRole(role.getId());
            userRegion.put(userId,user);
        }
        cacheTransactionManager.commit();
    } catch (Exception e) {
        try {
            cacheTransactionManager.rollback();
        }catch (Exception rbe){

        }
        throw new RuntimeException(e);
    }
}

Any guidance in this case will be appreciated.

答案1

得分: 1

1.) 分布式事务目前仅适用于已复制的区域。

2.) 在第二种情况下,现在事务边界只包含一个区域,因此不需要协同定位。

3.) 我认为在您的第一种情况中,您将两个分区区域作为事务的一部分,这需要这些区域进行协同定位(相关数据必须存在于节点上,因此也有可能其中一个是复制区域,另一个是分区区域)。

英文:

1.) Distributed transactions only work for Replicated Regions at this point.

2.) In the second case, only one region is now in the transaction boundary, so co-location is not needed.

3.) I think in your first case, you had two partitioned regions as part of a transaction, this requires the regions to be co-located ( the relevant data has to exist on the node, so it's also possible that one is a replicated region and the other is a partitioned)

答案2

得分: 0

已更改,将用户附加到角色的方法如下,没有异常。

Region<Long, User> userRegion = cache.getRegion(USER_REGION);
Region<Long, Role> roleRegion = cache.getRegion("Role");
CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
try {
    // 这是在事务边界之外获取角色信息的变化。
    Role role = roleRegion.get(roleId);

    cacheTransactionManager.setDistributed(true);
    cacheTransactionManager.begin();

    // 这一行导致下面的异常
    // org.apache.geode.cache.UnsupportedOperationInTransactionException: 期望大小为 1 {[/__PR/_B__User_101]}
    // Role role = roleRegion.get(roleId);

    if (role != null) {
        User user = userRegion.get(userId);
        user.addRole(role.getId());
        userRegion.put(userId, user);
    }
    cacheTransactionManager.commit();
} catch (Exception e) {
    try {
        if (cacheTransactionManager != null && cacheTransactionManager.exists())
            cacheTransactionManager.rollback();
    } catch (Exception rbe) {

    }
    throw new RuntimeException(e);
}

并且没有异常。

然而,需要更多关于以下几点的信息。

  1. 事务已设置为分布式。
  2. 在此情况下,用户和角色两个区域都参与了事务,导致事务失败,出现 UnsupportedOperationInTransactionException 异常。
  3. 分布式事务在多个区域上不起作用。
英文:

Changed, attach user to role method to below and there is no exception.

Region&lt;Long, User&gt; userRegion = cache.getRegion(USER_REGION);
    Region&lt;Long, Role&gt; roleRegion = cache.getRegion(&quot;Role&quot;);
    CacheTransactionManager cacheTransactionManager = cache.getCacheTransactionManager();
    try {
       //This is change fetching role information outside transaction boundry.
        Role role = roleRegion.get(roleId);

        cacheTransactionManager.setDistributed(true);
        cacheTransactionManager.begin();

        //This line is causing below exception
        //org.apache.geode.cache.UnsupportedOperationInTransactionException: Expected size of 1 {[/__PR/_B__User_101]}
        //Role role = roleRegion.get(roleId);

        if (role != null) {
            User user = userRegion.get(userId);
            user.addRole(role.getId());
            userRegion.put(userId,user);
        }
        cacheTransactionManager.commit();
    } catch (Exception e) {
        try {
            if(cacheTransactionManager != null &amp;&amp; cacheTransactionManager.exists())
                cacheTransactionManager.rollback();
        }catch (Exception rbe){

        }
        throw new RuntimeException(e);
    }

And there is no exception.

However need more information on below points.

  1. Transaction was set to distributed.
  2. User and Role both regions were involved in this case transaction failed, with exception UnsupportedOperationInTransactionException
  3. Distributed transactions are not working on multiple regions.

huangapple
  • 本文由 发表于 2020年1月3日 23:15:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581006.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定