Near Cache

Overview

A Near Cache provides local cache access to recently- and/or often-used data, backed by a centralized or multi-tiered cache that is used to load-on-demand for local cache misses. Near Caches have configurable levels of cache coherency, from the most basic expiry-based caches and invalidation-based caches, up to advanced data-versioning caches that can provide guaranteed coherency. The result is a tunable balance between the preservation of local memory resources and the performance benefits of truly local caches.

A Near Cache is actually an INamedCache implementation that wraps two caches - a front cache (assumed to be "inexpensive" and probably "incomplete") and a back cache (assumed to be "complete" and "correct", but more "expensive") - using a read-through/write-through approach. If the back cache implements the IObservableCache interface, the Near Cache provides four different strategies of invalidating the front cache entries that have changed by other processes in the back cache:

Configuring and using a Near Cache

The Coherence for .NET Near Cache functionality is implemented by the Tangosol.Net.Cache.NearCache class. As such, it can be programatically instantiated and configured; however, it is recommended that a NearCache be configured via a cache configuration descriptor, just like any other Coherence for .NET cache.

A typical Near Cache is configured to use a Local Cache (thread safe, highly concurrent, size-limited and/or auto-expiring local cache) as the front cache and a remote cache as a back cache. A Near Cache is configured via the near-scheme which has two child elements - a front-scheme for configuring a local (front) cache and a back-scheme for defining a remote (back) cache. For example:

<?xml version="1.0"?>

<cache-config xmlns="http://schemas.tangosol.com/cache">
  <caching-scheme-mapping>
    <cache-mapping>
      <cache-name>example-near-cache</cache-name>
      <scheme-name>example-near</scheme-name>
    </cache-mapping>
  </caching-scheme-mapping>
  <caching-schemes>
    <local-scheme>
      <scheme-name>example-local</scheme-name>
    </local-scheme>

    <near-scheme>
      <scheme-name>example-near</scheme-name>
      <front-scheme>
        <local-scheme>
          <scheme-ref>example-local</scheme-ref>
        </local-scheme>
      </front-scheme>
      <back-scheme>
        <remote-cache-scheme>
          <scheme-ref>example-remote</scheme-ref>
        </remote-cache-scheme>
      </back-scheme>
    </near-scheme>

    <remote-cache-scheme>
      <scheme-name>example-remote</scheme-name>
      <service-name>ExtendTcpCacheService</service-name>
      <initiator-config>
        <tcp-initiator>
          <remote-addresses>
            <socket-address>
              <address>localhost</address>
              <port>9099</port>
            </socket-address>
          </remote-addresses>

          <connect-timeout>5s</connect-timeout>
        </tcp-initiator>

        <outgoing-message-handler>
          <request-timeout>30s</request-timeout>
        </outgoing-message-handler>
      </initiator-config>
    </remote-cache-scheme>
  </caching-schemes>
</cache-config>

A reference to a configured Near Cache can then be obtained by name via the CacheFactory class:

INamedCache cache = CacheFactory.GetCache("example-near-cache");
Cleaning up the resources associated with a NearCache

Instances of all INamedCache implementations, including NearCache, should be explicitly released by calling the INamedCache.Release() method when they are no longer needed, in order to free up any resources they might hold.

If the particular INamedCache is used for the duration of the application, then the resources will be cleaned up when the application is shut down or otherwise stops. However, if it is only used for a period of time, the application should call its Release() method when finished using it.

Alternatively, you can leverage the fact that INamedCache extends IDisposable and that all cache implementations delegate a call to IDisposable.Dispose() to INamedCache.Release(). This means that if you need to obtain and release a cache instance within a single method, you can do so via a using block:

using (INamedCache cache = CacheFactory.GetCache("my-cache"))
{
   // use cache as usual
}

After the using block terminates, IDisposable.Dispose() will be call on the INamedCache instance, and all resources associated with it will be released.