Skip to content
Ben Manes edited this page Jul 14, 2015 · 35 revisions
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
  .writer(new CacheWriter<Key, Graph>() {
    @Override public void write(Key key, Graph graph) {
      // write to storage or secondary cache
    }
    @Override public void delete(Key key, Graph graph, RemovalCause cause) {
      // delete from storage or secondary cache
    })
  .build(key -> createExpensiveGraph(key));

CacheWriter allows the cache to act as a facade to the underlying resource and, when combined with a CacheLoader, all reads and writes can propagate through the cache. Writers expand the atomic operation on the cache to include synchronizing with an external resource. This means that the cache will block subsequent mutative operations for the entry and reads will return the previous value until the write completes. If the writer fails then the mapping is left unchanged and the exception propagates to the caller.

The CacheWriter is notified when an entry is created or mutated (Cache.put), or removed for any reason. A mapping that is loaded (e.g. LoadingCache.get) or computed (e.g. Map.computeIfAbsent) due to a cache miss is not communicated.

Note that the CacheWriter may not be used in conjunction with weak keys or AsyncLoadingCache.

Write Modes

A CacheWriter may be used to implement a write-through or write-back cache.

In a write-through cache the operations are performed synchronously and the cache will only be updated if the writer completes successfully. This avoids race conditions where the resource and cache are updated as independent atomic operations.

In a write-back cache the operation to the external resource is performed asynchronously after the cache has been updated. This improves write throughput at the risk of data inconsistency, such as leaving invalid state in the cache if the write fails. This approach may be useful to delay writes until a specific time, limit the write rate, or batch write operations.

Layering

A CacheWriter may be used to integrate multiple caching layers.

A layered cache loads from and writes to an external cache that is backed by the system of record. This allows having a small fast cache that falls back to slow large cache. Typical tiers are off-heap, file-based, and remote caches.

A victim cache is a layering variant where the evicted entries are written to the secondary cache. The delete(K, V, RemovalCause) allows for inspecting why the entry was removed and reacting accordingly.

Synchronous Listeners

A CacheWriter may be used to publish to synchronous listeners.

A synchronous listener receives event notifications in order that operations occur on the cache for a given key. The listener may either block the cache operation or be performed asynchronously. This type of listener is most often useful for replication or constructing a distributed cache.

Clone this wiki locally