10 Replies Latest reply on Nov 26, 2008 11:43 AM by dancantong

    Strange invalidation

    dancantong

      Hi!
      I'm working with JBoss TreeCache 1.4.1 with Tomcat 5.5. I have two tomcat instances configured with one cache instance each. I have configured cache for cluster invalidation and I'm experiencing the following behaviour. First I insert a cache node in a Tomcat instance. Then, I insert the same cache node (with same FQN and attribute data) in another Tomcat instance. After that, If I query for the cached node in the first Tomcat instance, it says it cannot find the node.
      Is this a normal behaviour with cluster invalidation? How can I maintain the same node cached at the same time in both caches instances?


      This is the cache configuration file (applied to both cache instances):

      <server>
       <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar" />
      
       <!-- ==================================================================== -->
       <!-- Defines TreeCache configuration -->
       <!-- ==================================================================== -->
       <mbean code="org.jboss.cache.TreeCache" name="OMADL:name=ThemeAndMediaObjectCache">
       <depends>jboss:service=Naming</depends>
       <depends>jboss:service=TransactionManager</depends>
      
      
       <!-- Configure the TransactionManager -->
       <attribute name="TransactionManagerLookupClass">org.jboss.cache.GenericTransactionManagerLookup</attribute>
      
       <!--
       Node locking scheme :
       PESSIMISTIC (default)
       OPTIMISTIC
       -->
       <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
      
       <!--
       Node locking isolation level :
       SERIALIZABLE
       REPEATABLE_READ (default)
       READ_COMMITTED
       READ_UNCOMMITTED
       NONE
      
       (ignored if NodeLockingScheme is OPTIMISTIC)
       -->
       <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
      
       <!-- Lock parent before doing node additions/removes -->
       <attribute name="LockParentForChildInsertRemove">true</attribute>
      
       <!-- Valid modes are LOCAL
       REPL_ASYNC
       REPL_SYNC
       INVALIDATION_ASYNC
       INVALIDATION_SYNC
       -->
       <attribute name="CacheMode">INVALIDATION_ASYNC</attribute>
      
       <!-- Whether each interceptor should have an mbean
       registered to capture and display its statistics. -->
       <attribute name="UseInterceptorMbeans">true</attribute>
      
       <!-- Name of cluster. Needs to be the same for all TreeCache nodes in a
       cluster, in order to find each other -->
       <attribute name="ClusterName">OMADLCacheCluster</attribute>
      
       <!-- Uncomment next three statements to enable JGroups multiplexer.
       This configuration is dependent on the JGroups multiplexer being
       registered in an MBean server such as JBossAS. -->
       <!--
       <depends>jgroups.mux:name=Multiplexer</depends>
       <attribute name="MultiplexerService">jgroups.mux:name=Multiplexer</attribute>
       <attribute name="MultiplexerStack">udp</attribute>
       -->
      
       <!-- JGroups protocol stack properties. ClusterConfig isn't used if the
       multiplexer is enabled and successfully initialized. -->
       <attribute name="ClusterConfig">
       <config>
       <!-- UDP: if you have a multihomed machine,
       set the bind_addr attribute to the appropriate NIC IP address
       -->
       <!-- UDP: On Windows machines, because of the media sense feature
       being broken with multicast (even after disabling media sense)
       set the loopback attribute to true
       -->
       <UDP mcast_addr="228.1.2.3" mcast_port="45566" bind_addr="127.0.0.1" ip_ttl="64" ip_mcast="true"
       mcast_send_buf_size="150000" mcast_recv_buf_size="80000" ucast_send_buf_size="150000"
       ucast_recv_buf_size="80000" loopback="false" />
       <PING timeout="2000" num_initial_members="3" up_thread="false" down_thread="false" />
       <MERGE2 min_interval="10000" max_interval="20000" />
       <FD shun="true" up_thread="true" down_thread="true" />
       <VERIFY_SUSPECT timeout="1500" up_thread="false" down_thread="false" />
       <pbcast.NAKACK gc_lag="50" max_xmit_size="8192" retransmit_timeout="600,1200,2400,4800" up_thread="false"
       down_thread="false" />
       <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10" down_thread="false" />
       <pbcast.STABLE desired_avg_gossip="20000" up_thread="false" down_thread="false" />
       <FRAG frag_size="8192" down_thread="false" up_thread="false" />
       <pbcast.GMS join_timeout="5000" join_retry_timeout="2000" shun="true" print_local_addr="true" />
       <pbcast.STATE_TRANSFER up_thread="false" down_thread="false" />
       </config>
       </attribute>
      
       <!-- The max amount of time (in milliseconds) we wait until the
       initial state (ie. the contents of the cache) are retrieved from
       existing members in a clustered environment
       -->
       <attribute name="InitialStateRetrievalTimeout">5000</attribute>
      
       <!-- Number of milliseconds to wait until all responses for a
       synchronous call have been received.
       -->
       <attribute name="SyncReplTimeout">10000</attribute>
      
       <!-- Max number of milliseconds to wait for a lock acquisition -->
       <attribute name="LockAcquisitionTimeout">15000</attribute>
      
       <!-- Name of the eviction policy class. -->
       <attribute name="EvictionPolicyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
      
       <!-- Specific eviction policy configurations. This is LRU -->
       <attribute name="EvictionPolicyConfig">
       <config>
       <attribute name="wakeUpIntervalSeconds">5</attribute>
       <!-- Cache wide default -->
       <region name="/_default_">
       <attribute name="maxNodes">100</attribute>
       <attribute name="timeToLiveSeconds">3600</attribute>
       </region>
      
       <region name="/ThemeInfo">
       <attribute name="maxNodes">10</attribute>
       <attribute name="timeToLiveSeconds">3600</attribute>
       </region>
      
       <region name="/MediaObjectData">
       <attribute name="maxNodes">10</attribute>
       <attribute name="timeToLiveSeconds">3600</attribute>
       </region>
       </config>
       </attribute>
       </mbean>
      </server>



      Best regards,

      Daniel.

        • 1. Re: Strange invalidation
          manik

          Yes, since you are using invalidation. The purpose of invalidation is to simply flush out stale data. If you expect both instances to actively use the same state, use replication.

          • 2. Re: Strange invalidation
            dancantong

            Ok, thank you very much for hour help.

            • 3. Re: Strange invalidation
              dancantong

              But there's still something that I can't understand.
              You say the purpose of invalidation is to flush out stale data in a clustered cache. That means that if you modify a node that is cached in a cache instance in the cluster, it sends an invalidation message to the rest of nodes with the same FQN in the cluster. But this does not make sense as it is not possible to have two nodes with the same FQN at the same time in a cluster configured with invalidation policy.
              I can't figure out what invalidation is used for, as I think it will make the cache useless as it will invalidate the nodes continoulsy in most scenaries. Think for example in the scenarie I was talking about (a load balancer that redirects requests to different server instances, each one having a cache instance, with the same data being requested repeatedly). In this case the requested data will be put in both cache instances and will be invalidated repeatedly, so the cache will not have any effectiveness.

              • 4. Re: Strange invalidation
                brian.stansberry

                The trick to having the same info stored in multiple nodes while using invalidation is to have logic to differentiate two types of writes to the cache. Here I'll use terminology from Hibernate's Second Level Caching implementation, which faces this exact problem:

                1) A "put". This is a write to JBC of data that's stored elsewhere in a "master" source (e.g. a database) and is unchanged from that master source. Storing this in JBC shouldn't invalidate other nodes, since other nodes will also have the same data from the same "master" source.

                To make this kind of write to JBC, use the JBC putForExternalRead() method.

                2) An "insert/update". Here the application is changing the master data and needs to make the cache aware of the change. Since other nodes in the cluster may also have now out-of-date copies of the data cached, they need to be invalidated.

                To make this kind of write to JBC, use the JBC put() method.

                • 5. Re: Strange invalidation
                  dancantong

                  Thank you very much. I think that is what I need.

                  I'm testing it but after executing:

                  cacheInstance.putForExternalRead(nodeCatchedFqn, "key", data);

                  when I try to retrieve the data with:

                  data = cacheInstance.get(nodeCatchedFqn,"key");

                  I get no data. The node has been created but it has no data associated to. If I replace the putForExternalRead with the put method it works.

                  I'm working with JBossCache 2.1.1.

                  Any idea with this?

                  • 6. Re: Strange invalidation
                    sancheski

                    As I see in your cache descriptor, you dont use any Cache loader. You can use, for example, a JDBCCacheLoader, that will keep all data stored in a DB. Then, if your application required data that has been invalidated from any node, it can be obtain through the cache loader.

                    I hope it may help you!

                    Sancheski

                    • 7. Re: Strange invalidation
                      dancantong

                      Thanks, but I prefer using putForExternalRead method. If anyone could give me any tip about using it...

                      • 8. Re: Strange invalidation
                        nathanmesser

                        Does your node exist before you call putForExternalRead? The putForExternalRead method will do nothing if the node already exists.

                        • 9. Re: Strange invalidation
                          dancantong

                          No, it doesn't exist. The node exists after putForExternalRead invocation but does not have any data mapped.
                          Could it be a problem with the JBossCache version? I'm using 2.1.1.

                          • 10. Re: Strange invalidation
                            dancantong

                            Hi!
                            I've updated to JBossCache 3.0.0GA and now it works.
                            Thank you everybody.