hibernateinfinispancache-invalidation

Hibernate with infinispan invalidation cache in a cluster


I am using Hibernate 5.4.22 with Infinispan 11.0.4 in a cluster environment. Hibernate second level cache is configured to use the JCache provider:

    hbProps.setProperty("hibernate.cache.use_minimal_puts", "false");
    hbProps.setProperty("hibernate.cache.use_structured_entries", "false");
    hbProps.setProperty("hibernate.cache.use_query_cache", "false");
    hbProps.setProperty("hibernate.cache.use_second_level_cache", "true");
    hbProps.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.jcache.JCacheRegionFactory");
    hbProps.setProperty("hibernate.javax.cache.provider", "org.infinispan.jcache.embedded.JCachingProvider");

Infinispan is configured with the following infinispan.xml:

<infinispan
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="urn:infinispan:config:11.0 http://www.infinispan.org/schemas/infinispan-config-11.0.xsd"
      xmlns="urn:infinispan:config:11.0">
      
      <jgroups>
          <stack name="jgroups-stack">
              <TCP bind_port="7800"
                   recv_buf_size="${tcp.recv_buf_size:130k}"
                   send_buf_size="${tcp.send_buf_size:130k}"
                   max_bundle_size="64K"
                   sock_conn_timeout="300"
          
                   thread_pool.min_threads="0"
                   thread_pool.max_threads="20"
                   thread_pool.keep_alive_time="30000"/>
          
<!--              <TCPPING async_discovery="true"
                       initial_hosts="${jgroups.tcpping.initial_hosts:localhost[7800],localhost[7801]}"
                       port_range="2"/>-->
              <MPING/>
              <MERGE3  min_interval="10000"
                       max_interval="30000"/>
              <FD_SOCK/>
              <FD_ALL timeout="9000" interval="3000" />
              <VERIFY_SUSPECT timeout="1500"  />
              <BARRIER />
              <pbcast.NAKACK2 use_mcast_xmit="false"
                             discard_delivered_msgs="true"/>
              <UNICAST3 />
              <pbcast.STABLE desired_avg_gossip="50000"
                             max_bytes="4M"/>
              <pbcast.GMS print_local_addr="false" join_timeout="2000"/>
              <UFC max_credits="2M"
                   min_threshold="0.4"/>
              <MFC max_credits="2M"
                   min_threshold="0.4"/>
              <FRAG2 frag_size="60K"  />
              <!--RSVP resend_interval="2000" timeout="10000"/-->
              <pbcast.STATE_TRANSFER/>                    
          </stack>
      </jgroups> 
      
      <cache-container>
          <!-- turn off metrics -->
          <metrics gauges="false" histograms="false"/>
          <jmx enabled="true"/>
          <transport stack="jgroups-stack" cluster="infinispan-hibernate-cluster"/>
          
          <serialization marshaller="org.infinispan.commons.marshall.JavaSerializationMarshaller">
            <white-list>
              <regex>.*</regex>
            </white-list>   
          </serialization>
          
<!--          <replicated-cache name="MainCache" mode="SYNC"> 
            <memory max-count="100000"/>
            <expiration max-idle="3600000" lifespan="-1"/>
          </replicated-cache>-->

          <invalidation-cache name="MainCache" mode="SYNC">
            <memory max-count="100000"/>
            <expiration max-idle="3600000" lifespan="-1"/>
          </invalidation-cache>
      </cache-container>
</infinispan>

I have a test entity 'Profile' which is supposed to be cached with read-write strategy:

<hibernate-mapping>

  <class name="hibernatetest.Profile" table="Profiles" lazy="false">
    <cache usage="read-write" region="MainCache"/>
    <id column="id" name="id" unsaved-value="0">
      <generator class="native"/>
    </id>
    <discriminator column="type" type="string"/>
    <version name="version"/>
    <property name="name" type="string" length="100"/>
    <property name="available" type="yes_no"/>
  </class>
  
</hibernate-mapping>

According to Cache concurrency strategy/cache mode compatibility table, the combination of <cache usage="read-write"> and <invalidation-cache> should be a working scenario. In my tests, I have one node that continuously reads an object and one node that updates the same object. I have found that the reading node never gets notified that the object has changed in order to read it again from the database. By looking at the log, it seems as if the invalidation cache on the writing node does not send any message to the reading node.

However, if I change infinispan.xml to use <replicated-cache> or <distributed-cache> instead of <invalidation-cache>, then the reading node is notified of the change that the writing node did. So, I guess this means that the issue is not in jgroups.

Is this a problem in the invalidation-cache, or am I missing something in my configuration?

Here is a log file of the instance that reads from the invalidation cache inv-read.txt and a log file of the instance that updates the cache inv-update.txt.

Thank you!


Solution

  • The problem is using JCache - the table assumes InfinispanRegionFactory instead of JCacheRegionFactory.

    It seems that Infinispan does not have a module to support Hibernate 5.4 explicitly - I would guess that modules to support Hibernate 5.3 should work even with Hibernate 5.4, though, since there hasn't been much changes in the second-level-cache land in Hibernate 5.4.

    I am surprised that 2LC works with JCache at all with replicated/distributed caches - I would be pretty sure that it does not work 'reliably' (transactionally, covering edge cases etc.) anyway.