##### Child pages
• Terracotta Distributed Cache
Go to start of banner

# Cache Evictor

Go to start of metadata

You are viewing an old version of this page. View the current version.

Version 61

This documentation is about Terracotta DSO, an advanced distributed-computing technology aimed at meeting special clustering requirements.

Terracotta products without the overhead and complexity of DSO meet the needs of almost all use cases and clustering requirements. To learn how to migrate from Terracotta DSO to standard Terracotta products, see Migrating From Terracotta DSO. To find documentation on non-DSO (standard) Terracotta products, see Terracotta Documentation. Terracotta release information, such as release notes and platform compatibility, is found in Product Information.

Unknown macro: {div}
Unknown macro: {div9}
 Release: 3.6 Publish Date: November, 2011 Documentation Archive »

# Terracotta Cache Evictor

## Introduction

The Terracotta Cache Evictor is an interface providing a simple distributed eviction solution for map elements. The Cache Evictor, implemented with the Terracotta Integration Module tim-map-evictor, provides a number of advantages over more complex solutions:

• Simple – API is easy to understand and code against.
• Distributed – Eviction is distributed along with data to maintain coherence.
• Standard – Data eviction is based on standard expiration metrics.
• Lightweight – Implementation does not hog resources.
• Efficient – Optimized for a clustered environment to minimize faulting due to low locality of reference.
• Fail-Safe – Data can be evicted even if written by a failed node or after all nodes have been restarted.
• Self-Contained – Implements a Map for optional ready-to-use distributed cache.
• Native – Designed for Terracotta to eliminate integration issues.

## How to Implement and Configure

Under the appropriate conditions, the Terracotta Cache Evictor can be used in any Terracotta cluster. If your application can use the Cache Evictor's built-in Map implementation for a cache, you can avoid having to customize your own data structure. See [#A Simple Distributed Cache] for instructions on using the Cache Evictor with the provided Map implementation.

### Characteristics and Requirements

The Terracotta Cache Evictor has the following eviction characteristics:

• A Time To Live (TTL) value can be set.
The TTL determines the maximum amount of time an object can remain in the cache before becoming eligible for eviction, regardless of other conditions such as use. TTL is global (applies to each element).
• A Time To Idle (TTI) value can be set.
The TTI determines the maximum amount of time an object can remain idle in the cache before becoming eligible for eviction. TTI is reset each time the object is used. TTI is global (applies to each element).
• Each element does receive its own timestamp used against the cache-wide TTL and TTI.
• "Orphaned" values (values no longer local to any node) are evicted in batches.

To learn how to configure the eviction parameters, see [#Usage Pattern].

The Terracotta Cache Evictor requires JDK 1.5 or greater.

If you choose not to use the provided Map implementation, you must provide your own data structure and take the following steps:

• Use a partial-loading data structure for the evictor to target (see [Clustered Data Structures Guide]).
• Write start/stop thread-management code to run the evictor.
• Include the code from CHMDistributedMap that performs local eviction (see the tim-map-evictor library).
• Implement the Evictor interface from tim-map-evictor.

See the following sections for an example of how the Terracotta Cache Evictor is intended to function with its built-in Map implementation.

### Installing the TIM

To use the Terracotta Cache Evictor, you must both install tim-map-evictor and include the evictor JAR file in your classpath.

To install the TIM, run the following command from ${TERRACOTTA_HOME}: UNIX/Linux [PROMPT] bin/tim-get.sh install tim-map-evictor  Microsoft Windows [PROMPT] bin\tim-get.bat install tim-map-evictor  You should see output that appears similar to the following: Installing tim-map-evictor 1.3.0-SNAPSHOT and dependencies... INSTALLED: tim-map-evictor 1.3.0-SNAPSHOT - Ok INSTALLED: tim-concurrent-collections 1.3.0-SNAPSHOT - Ok  Run the following command from${TERRACOTTA_HOME} to update the Terracotta configuration file (tc-config.xml by default):

UNIX/Linux
[PROMPT] bin/tim-get.sh upgrade <path/to/Terracotta/configuration/file>

Microsoft Windows
[PROMPT] bin\tim-get.bat upgrade <path\to\Terracotta\configuration\file>


For more information about installing and updating TIMs, see the TIM Update Center.

### Locking Requirements

Terracotta automatically provides locking for read (get) and write (put) operations on the distributed map. These locks last for the duration of the get or put operation.

Mutating an object obtained from the distributed map requires a read/write lock to avoid race conditions and potential corruption to data.

For example, assume a distributed map has an element <k1, v1> in it. The following operation does not require explicit locking:

myObject = getFromMyDistributedMap(k1); // Terracotta provides a lock for the duration of getFromMyDistributedMap().


Adding a new element to the map also does not require explicit locking:

putIntoMyDistributedMap(k2, v2); // Terracotta provides a lock for the duration of putIntoMyDistributedMap().


However, the following operation requires a read/write lock:

myNewObject = myMutator(myObject); // myObject should be locked until it is put back into the map.


Note the following:

• The myObject class (or a class above it in the object graph) must be instrumented.
• and autolocked ???
• Use the Terracotta Developer Console to gain visibility into the cluster to better understand how the map and object graphs is being clustered.
• Use the Terracotta Developer Console's Lock Profiler to see what locks exist and how they are being used.

## A Simple Distributed Cache

Clustered applications with a system of record (SOR) on the backend can benefit from a distributed cache that manages certain data in memory while reducing costly application-SOR interactions. However, using a cache can introduce increased complexity to software development, integration, operation, and maintenance.

The Terracotta Cache Evictor includes a distributed Map that can be used as a simple distributed cache. This cache uses the Terracotta Cache Evictor, incorporating all of its benefits. It also takes both established and innovative approaches to the caching model, solving performance and complexity issues by:

• obviating SOR commits for data with a limited lifetime;
• making cached application data available in-memory across a cluster of application servers;
• offering standard methods for working with cache elements and performing cache-wide operations;
• incorporating concurrency for readers and writers;
• utilizing a flexible map implementation to adapt to more applications;
• minimizing inter-node faulting to speed data operations.

### Structure and Characteristics

The Terracotta distributed cache is an interface incorporating a distributed map with standard map operations:

public interface DistributedMap<K, V> {
// Single item operations
void put(K key, V value);
V get(K key);
V remove(K key);
boolean containsKey(K key);

// Multi item operations.
int size();
void clear();
Set<K> getKeys();

// For managing the background evictor thread.
void start();
void shutdown();
}


getValues() is not provided, but an iterator can be obtained for Set<K> to obtain values.

### Usage Pattern

A typical usage pattern for the Terracotta Cache Evictor is shown in the MyStuff class below. The next section contains a full list of configuration parameters available to DistributedMapBuilder.

import org.terracotta.modules.dmap.DistributedMap;
import org.terracotta.modules.dmap.DistributedMapBuilder;
import static org.terracotta.modules.dmap.DistributedMapBuilder.HOUR;
import static org.terracotta.modules.dmap.DistributedMapBuilder.MINUTE;

public class MyStuff {

// Mark as Terracotta root
private DistributedMap<String, Stuff> sharedMap;

public MyStuff() {
if(sharedMap == null) {
DistributedMap<String, Stuff> newMap = new DistributedMapBuilder()
.setMaxTTLMillis(6*HOUR)       // Regardless of use, remove after 6 hours.
.setMaxTTIMillis(30*MINUTE)      // Remove after 30 minutes of none-use.
.setEvictorSleepMillis(5*MINUTE)  // Perform eviction every 5 minutes.
.newMap();

// Set root - if this doesn't succeed, shutdown the newMap as it has a worthless background evictor thread.
sharedMap = newMap;
if(sharedMap != newMap) {
newMap.shutdown();
}
}

public void putStuff(String key, Stuff stuff) {
sharedMap.put(key, stuff);
}

public Stuff getStuff(String key) {
return sharedMap.get(key);
}
}


#### Evictor Configuration Parameters

The configuration parameters that can be set through DistributedMapBuilder() are summarized in the following table.

Config property

Default value

Description

name

"Distributed Map"

A descriptive string used in log messages and evictor thread names.

concurrency

16

The maximum number of concurrent threads that can access the map.

maxTTIMillis

0

Time To Idle - the maximum amount of time (in milliseconds) an item can be in the map unused before expiration; 0 means never expire due to TTI.

maxTTLMillis

0

Time To Live - the maximum amount of time (in milliseconds) an item may be in the map regardless of use before expiration; 0 means never expire due to TTL.

evictorSleepMillis

30000

Wait time (in milliseconds) between eviction cycles; should be tuned to work well with TTI/TTL values.

orphanEvictionEnabled

true

Determines whether "orphaned" values (values no longer local to any node) are evicted.

orphanEvictionFrequency

4

Number of times to run local eviction between doing orphan eviction.

orphanBatchSize

1000

Size of each set of items evicted during orphan eviction.

orphanBatchPauseMillis

20

Rest time (in milliseconds) between each orphan batch eviction.

loggingEnabled

false

Basic distributed-map logging messages saved to the Terracotta logs.

evictorLoggingEnabled

false

Eviction logging messages saved to the Terracotta logs..

### Usage Example

The following is an example of a cache that implements the Terracotta distributed cache:

import org.terracotta.modules.dmap.*;
import static org.terracotta.modules.dmap.DistributedMapBuilder.*;

DisributedMap<String,String> map = new DistributedMapBuilder()
.setMaxTTLMillis(10 * SECOND)
.setMaxTTIMillis(5 * SECOND)
.setConcurrency(16)
.newMap();
map.start(); // start eviction thread

map.put("Rabbit", "Carrots");
map.put("Dog", "Bone");
map.put("Owl", "Mouse");
// wait 3 seconds
map.get("Rabbit");

// wait 2 seconds - expire Dog and Owl due to TTI
assert ! map.containsKey("Dog");
assert ! map.containsKey("Owl");
assert map.containsKey("Rabbit");

// wait 5 seconds - expire Rabbit due to TTL
assert ! map.containsKey("Rabbit");


## Terracotta Cache Evictor in a Reference Application

The [Examinator reference application] uses the Terracotta Cache Evictor to handle pending user registrations. This type of data has a "medium-term" lifetime which needs to be persisted long enough to give prospective registrants a chance to verify their registrations. If a registration isn't verified by the time TTL is reached, it can be evicted from the cache. Only if the registration is verified is it written to the database.

The combination of Terracotta and the Terracotta Cache Evictor gives Examinator the following advantages:

• The simple Terracotta Cache Evictor's API makes it easy to integrate with Examinator and to maintain and troubleshoot.
• Medium-term data is not written to the database unnecessarily, improving application performance.
• Terracotta persists the pending registrations so they can survive node failure.
• Terracotta clusters (shares) the pending registration data so that any node can handle validation.
• No labels