Hibernate.orgCommunity Documentation

Chapter 4. Cache Eviction

4.1. Overview
4.1.1. The Eviction Process
4.1.2. Eviction Regions
4.1.3. Eviction Policies
4.2. Organization of Data in the Cache
4.2.1. Region Prefix and Region Name
4.2.2. Entities
4.2.3. Collections
4.2.4. Queries
4.2.5. Timestamps
4.3. Example Configuration
4.4. Best Practices

Eviction refers to the process by which old, relatively unused, or excessively voluminous data can be dropped from the cache, allowing the cache to remain within a memory budget. Generally, applications that use the Second Level Cache should configure eviction, unless only a relatively small amount of reference data is cached. This chapter provides a brief overview of how JBoss Cache eviction works, and then explains how to configure eviction to effectively manage the data stored in a Hibernate Second Level Cache. A basic understanding of JBoss Cache eviction and of concepts like FQNs is assumed; see the JBoss Cache User Guide for more information.

The JBoss Cache eviction process is fairly straightforward. Whenever a node in a cache is read or written to, added or removed, the cache finds the eviction region (see below) that contains the node and passes an eviction event object to the eviction policy (see below) associated with the region. The eviction policy uses the stream of events it receives to track activity in the region. Periodically, a background thread runs and contacts each region's eviction policy. The policy uses its knowledge of the activity in the region, along with any configuration it was provided at startup, to determine which if any cache nodes should be evicted from memory. It then tells the cache to evict those nodes. Evicting a node means dropping it from the cache's in-memory state. The eviction only occurs on that cache instance; there is no cluster-wide eviction.

An important point to understand is that eviction proceeds independently on each peer in the cluster, with what gets evicted depending on the activity on that peer. There is no "global eviction" where JBoss Cache removes a piece of data in every peer in the cluster in order to keep memory usage inside a budget. The Hibernate/JBC integration layer may remove some data globally, but that isn't done for the kind of memory management reasons we're discussing in this chapter.

An effect of this is that even if a cache is configured for replication, if eviction is enabled the contents of a cache will be different between peers in the cluster; some may have evicted some data, while others will have evicted different data. What gets evicted is driven by what data is accessed by users on each peer.

Controlling when data is evicted from the cache is a matter of setting up appropriate eviction regions and configuring appropriate eviction policies for each region.

An Eviction Policy is a class that knows how to handle eviction events to track the activity in its region. It may have a specialized set of configuration properties that give it rules for when a particular node in the region should be evicted. It can then use that configuration and its knowledge of activity in the region to to determine what nodes to evict.

JBoss Cache ships with a number of eviction policies. See the JBoss Cache User Guide for a discussion of all of them. Here we are going to focus on just two.

In order to understand how to configure eviction, you need to understand how Hibernate organizes data in the cache.

So far we've been looking at things in the abstract; let's see an example of how this comes together. In this example, imagine we have a Hibernate application with the following characteristics.

Let's see a possible eviction configuration for this scenario:

<attribute name="EvictionPolicyConfig">
  <config>
         
    <attribute name="wakeUpIntervalSeconds">5</attribute>
    <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
          
    <!--  
      Default region to pick up anything we miss in the more
      specific regions below.
    -->
    <region name="/_default_">
       <attribute name="maxNodes">500</attribute>
       <attribute name="timeToLiveSeconds">300</attribute>
       <attribute name="minTimeToLiveSeconds">120</attribute>
    </region>
            
    <!--  Don't ever evict modification timestamps -->
    <region name="/TS" 
       policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
            
    <!-- Reference data -->
    <region name="/appA/reference">
       <!-- Keep all reference data if it's being used -->
       <attribute name="maxNodes">0</attribute>
       <!-- Keep it around a long time (4 hours) -->
       <attribute name="timeToLiveSeconds">14400</attribute>
       <attribute name="minTimeToLiveSeconds">120</attribute>
    </region>
            
    <!-- Be more aggressive about queries on reference data -->
    <region name="/appA/reference/QUERY">
       <attribute name="maxNodes">200</attribute>
       <attribute name="timeToLiveSeconds">1000</attribute>
       <attribute name="minTimeToLiveSeconds">120</attribute>
    </region>
            
    <!-- 
       Lots of entity instances from this package, but different
       users are unlikely to share them. So, we can cache
       a lot, but evict unused ones pretty quickly.
    -->
    <region name="/appA/org/example/hibernate">
       <attribute name="maxNodes">50000</attribute>
       <attribute name="timeToLiveSeconds">1200</attribute>
       <attribute name="minTimeToLiveSeconds">120</attribute>
    </region>
            
    <!-- Clean up misc queries very promptly -->
    <region name="/appA/org/hibernate/cache/StandardQueryCache">
       <attribute name="maxNodes">200</attribute>
       <attribute name="timeToLiveSeconds">240</attribute>
       <attribute name="minTimeToLiveSeconds">120</attribute>
    </region>
            
  </config>
</attribute>

Notes on the above:

Some best practices to follow: