将Apache Ignite作为Hibernate L2缓存,存储重复实体

3

环境:

  • Vagrant 运行 MySQL 5.6
  • Java SE 1.8
  • Hibernate 4.2.16.Final
  • Apache Ignite 1.6

设置:

  • ToggleSwitch 实体拥有 String 类型的 id 属性和表示开/关状态的枚举类型 State
  • 已实现 equals() 和 hashcode() 方法针对 id 属性
  • @Cache 使用 READ_WRITE 和默认区域
  • Reader 节点每秒执行 EM.find() 并显示当前 State
  • Writer 节点每 3 秒执行 EM.find() 并切换 State
  • 两个节点都配置了 TRANSACTIONAL 原子性、PARTITIONED 缓存模式和 FULL_SYNC 写同步模式
  • 使用 TcpDiscoverySharedFsIpFinder 进行发现

所以我遇到的问题是读取端从写入端那里获取不到更改。我使用 IgniteInternalCache.entrySet() 将缓存的内容(与 state 的频率相同)输出,它显示缓存中有两个具有相同键的 ToggleSwitch 实例。

我尝试将它们添加到一个集合中,看是否会产生相同的结果,但集合按预期工作,只存储了一个实例。

此时我无法确定发生了什么问题,有什么想法吗?是一个 bug 还是配置错误?

1个回答

0

很可能键的equals和/或hashCode实现不正确。我建议将这两个存储在缓存中的键及其内容取出,并尝试调用这些方法以检查它们是否一致。

-- 更新 --

当使用默认二进制编组器时,此问题也可能发生在多应用程序环境中。更多细节请参见:https://issues.apache.org/jira/browse/IGNITE-3429

作为解决方法,您可以从默认的二进制序列化切换到OptimizedMarhsaller(请参见下面的配置示例)。这将强制在服务器端反序列化键对象并正确应用自定义equals逻辑。

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="marshaller">
        <bean class="org.apache.ignite.marshaller.optimized.OptimizedMarshaller"/>
    </property>
</bean>

@Spencer,你能解决EmbeddedId / IdClass的问题吗?我遇到了这个链接中描述的问题:https://issues.apache.org/jira/browse/IGNITE-3429 - Christian Matthew
@ChristianMatthew 我假设你正在作为一个集群运行这个程序?我自己在使用查询缓存时遇到了这个问题,因为我们没有使用嵌入式id。解决方案是为您的SessionFactory设置名称。反序列化使用本地工厂的UUID和远程工厂的名称在SessionFactory注册表中查找。同时将session_factory_name和如果您不使用JNDI session_factory_is_jndi也设置为false。以下是我偶然发现的一些相关链接: https://github.com/hibernate/hibernate-orm/pull/820 https://hibernate.atlassian.net/browse/HB-178 - Spencer
如果您感兴趣,这里还有一些:https://hibernate.atlassian.net/browse/HHH-9424 和 https://hibernate.atlassian.net/browse/HHH-6822。 - Spencer
@Spencer 感谢您的回复,但仍然存在问题。设置 "hibernate.session_factory_name" = hibernate_sf_starguest,"hibernate.ejb.entitymanager_factory_name (just in case)" = hibernate_sf_starguest,"hibernate.session_factory_name_is_jndi":错误是: 原因是:java.io.InvalidObjectException: 无法找到 SessionFactory [uuid=93176b36-136d-4ff1-a70b-a308fbf320f1,name=hibernate_sf_starguest] at org.hibernate.internal.SessionFactoryImpl.locateSessionFactoryOnDeserialization(SessionFactoryImpl.java:1781) at org.hibernate.internal.SessionFactoryImpl.readResolve(SessionFactoryImpl.java:1761) - Christian Matthew
@ChristianMatthew 抱歉,我错过了这个回复...我不确定这是否还有关系,但是您是否正在运行2个或更多节点?对于我来说,我发现堆栈跟踪是由远程节点生成的,然后在调用节点上记录。如果是这样,那么所有节点是否都配置了具有这些设置的SessionFactory?您是否有多个由同一Ignite节点支持的SessionFactory? - Spencer
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接