Choosing the Right Local Cache in Java: From ConcurrentHashMap to Caffeine

This article examines why and how to use local in‑process caches in Java, compares four implementations—ConcurrentHashMap, Guava Cache, Caffeine, and Ehcache—covers essential cache features, consistency challenges, hit‑rate optimization, and recommends Caffeine as the most performant choice for a two‑level caching architecture.

Architect
Architect
Architect
Choosing the Right Local Cache in Java: From ConcurrentHashMap to Caffeine

Background

In high‑performance service architectures, caching is essential. Hot data is usually stored in remote caches such as Redis or Memcached, and the database is queried only on a cache miss.

When remote caches become a bottleneck, a local (in‑process) cache can be added as a first‑level cache, forming a two‑level cache architecture that further reduces latency.

Two‑level cache flow diagram
Two‑level cache flow diagram

Why Use a Local Cache

Local memory access is extremely fast, suitable for low‑frequency‑change data.

It reduces network I/O by avoiding unnecessary round‑trips to remote caches.

Required Features of a Local Cache

Basic put/get operations.

Thread‑safe atomic operations (e.g., ConcurrentHashMap).

Maximum size limit.

Eviction policies such as LRU or LFU.

Expiration strategies (time‑based, lazy, periodic).

Optional persistence.

Statistics and monitoring.

Local Cache Options

1. ConcurrentHashMap

Implements a simple KV store with thread safety but requires custom code for eviction, size limits and expiration, making it suitable only for very simple scenarios.

2. Guava Cache

Google’s Guava library provides a ready‑made cache with maximum size, time‑based eviction, simple statistics and an LRU implementation.

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>

public class GuavaCacheTest {
    public static void main(String[] args) throws ExecutionException {
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .initialCapacity(5)
                .maximumSize(10)
                .expireAfterWrite(60, TimeUnit.SECONDS)
                .build();

        String orderId = String.valueOf(123456789);
        String orderInfo = cache.get(orderId, () -> getInfo(orderId));
        System.out.println(orderInfo);
    }

    private static String getInfo(String orderId) {
        // query Redis, then DB if necessary
        return String.format("{orderId=%s}", orderId);
    }
}

3. Caffeine

Caffeine is a Java‑8‑based cache that outperforms Guava by using the W‑TinyLFU algorithm, offering similar features with higher throughput.

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.9.3</version>
</dependency>

public class CaffeineTest {
    public static void main(String[] args) {
        Cache<String, String> cache = Caffeine.newBuilder()
                .initialCapacity(5)
                .maximumSize(10)
                .expireAfterWrite(60, TimeUnit.SECONDS)
                .build();

        String orderId = String.valueOf(123456789);
        String orderInfo = cache.get(orderId, key -> getInfo(key));
        System.out.println(orderInfo);
    }
    // getInfo same as above
}

4. Encache (Ehcache)

Ehcache offers multiple storage tiers (heap, off‑heap, disk) and various eviction algorithms, plus clustering support, but its performance is lower than Caffeine.

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.9.7</version>
</dependency>

public class EhcacheTest {
    public static void main(String[] args) {
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("orderCache",
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(
                                String.class, String.class, ResourcePoolsBuilder.heap(20)))
                .build(true);
        Cache<String, String> cache = cacheManager.getCache("orderCache", String.class, String.class);
        // use cache...
    }
}

Cache Consistency and Hit‑Rate Improvements

1. Consistency

Two‑level caches must stay consistent with the database. Typical solutions include broadcasting invalidation messages via MQ or using Canal to capture MySQL binlog changes and propagate them.

MQ based cache invalidation
MQ based cache invalidation
Canal + MQ consistency solution
Canal + MQ consistency solution

2. Improving Hit Rate

Techniques such as proper key design, appropriate expiration settings, and warm‑up loading can increase local cache hit ratios.

Choosing the Best Implementation

Ease of use: Guava, Caffeine, and Ehcache are all easy to integrate.

Feature set: Guava and Caffeine provide similar in‑heap caching; Ehcache adds off‑heap and disk persistence.

Performance: Benchmarks show Caffeine > Guava > Ehcache.

For most scenarios, Caffeine is recommended as the primary local cache, combined with Redis or Memcached as the second‑level distributed cache.

Performance comparison of Caffeine, Guava, and Ehcache
Performance comparison of Caffeine, Guava, and Ehcache
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaperformanceCache ConsistencyCaffeineGuavalocal cacheConcurrentHashMap
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.