Open-source project
ck-jesse/l2cache avatar
ck-jesse/l2cache

L2Cache composes Caffeine and Redis into a Spring-friendly L1 and L2

L2Cache 是一个基于 Caffeine + Redis 的二级缓存框架。让缓存的使用在业务开发中更加简单、高效。

635 stars104 forksJavaApache-2.0

At a glance

What is it?
L2Cache is a Java two-level cache framework that combines an in-memory Caffeine or Guava L1 with a Redis L2, adds hot key detection and batch operations, and accepts eventual consistency rather than strong consistency.
Who is it for?
Adopt L2Cache when you run Spring services on Redis and want an in-process L1 in front of it, especially if you have hot keys that repeatedly hit the network tier, and you accept eventual consistency. Do not adopt it if your correctness requirements depend on strong consistency across nodes, since the design explicitly trades the C in CAP away and the consistency guarantee is a message notification best effort.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 89 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

L1 in the process, L2 in Redis, and the network hop in between

L2Cache describes itself as a distributed two-level cache built on memory, Redis and Spring Cache, aimed at high concurrency. The structure is defined plainly in the project description. L1 is the in-memory cache and supports Caffeine or Guava Cache. L2 is the centralised cache and supports Redis. A hybrid cache uses both at once. The reason for the split is stated directly: a large volume of cache reads turns the L2 network into the bottleneck of the whole system, so L1 exists to cut the number of L2 reads and avoid the network IO overhead of a standalone cache system. L2 in turn protects against losing all L1 data when the application restarts. The design is therefore not clever, it is an acknowledgement that Redis round trips are expensive and that application memory is cheap enough to spend on a copy.

The cache type is configuration, and it decides the consistency you get

Three combinations are supported according to the configured cache type: Caffeine or Guava alone as a single level cache, Redis alone as a second level cache, or a Composite cache that uses both. This matters more than it sounds, because the project states the CAP trade-off directly. L2Cache satisfies the A and P parts of CAP, availability and partition tolerance, and strong consistency is not achievable because of the nature of caching, so the framework aims for eventual consistency and does as much as it can to get there. The stated mechanism for that is message notification, which keeps the first level caches consistent across a cluster. Anything that needs a read to reflect a write instantly on every node is outside what this design promises.

Hot key detection is the feature the alternatives do not have

The project includes a comparison table with JetCache from Alibaba and J2Cache from OSChina, and marks three capabilities as the ones where the others do not offer support: automatic hot key detection, cache batch operations and a generic cache layer. Automatic hot key detection identifies keys that are being hit repeatedly and caches them into the first level, which is the exact case where a single L2 lookup becomes the bottleneck. Batch operations cover paginated batch fetches and batch deletions, which otherwise means writing one loop per endpoint. The table itself carries a caveat that the comparison data is still being compiled and will be proofread again, so treat the feature checklist as the author's claim rather than a verified benchmark. The real substance is that these three behaviours come from production use in product, coupon, user and marketing services.

The production figures describe one specific system, not a guarantee

The README publishes performance data from a home page rebuild exercise in the product centre, and it is worth reading carefully rather than quoting the headline number. The table lists single pod, cluster single interface, cluster single link and cluster full link rows. A single pod with 8 cores and 16GB shows a peak above 5k QPS with an average response time within 50ms. A 25 pod cluster on the same interface shows a peak above 80k QPS. The full link row with 120 pods reaches 350k QPS with a response time within 55ms. Several caveats follow in the same section: only pod configuration is listed, not mq, redis, db, ingress or SLB, different interfaces give different QPS because business logic differs, and any single link in the chain can dominate the result. The README also lists one billion GMV monthly, five million daily active users and production use through repeated large promotion events.

Getting it into a Spring project means a starter module and external documentation

The project is a multi-module Maven project and the repository layout shows what ships: l2cache-core, l2cache-spring-boot-starter, l2cache-example, l2cache-jd-hotkey and a top level pom.xml. The core artifact is published to Maven Central under the group id io.github.ck-jesse with the artifact name l2cache-core, and the licence is Apache-2.0. Beyond the repository, the project keeps its how-to guide outside the repository. Usage, core principles, hot key detection design, and a series of post-mortem write-ups on production incidents sit in linked blog posts, including a Caffeine OOM analysis in the user centre and a Redis cluster exceeding its maximum memory limit in the product centre. That is a useful resource, and a how-to document also exists in the repository, but the deeper walkthroughs live in these external articles.

Known failure modes cluster around memory limits, not around correctness

The list of practical problems the project documents is specific and worth reading before you deploy. There is a Caffeine OOM analysis, a separate write-up restoring and verifying a scenario where Caffeine triggered frequent GC and OOM, and another on OOM under high concurrency in the product centre. There is a Redis cluster case that exceeded its maximum memory limit. And there is a subtle one: calling caffeine.getIfPresent() is meant only to read the cache, but it triggered a data load and set a NullValue entry, which is the kind of bug that quietly fills the cache with null placeholders. These are the failure modes of a framework whose L1 sits inside the application heap. The cache type is a per-cache configuration, so a hot key promotion that is right for the product catalogue can be wrong for the user profile.

Multi Redis instances and a Spring Cache abstraction are the practical wins

Beyond the hot key work, two features matter for day to day use. Multiple Redis instances are supported, with the instance selected on a cacheName dimension, so different caches can point at different Redis clusters rather than sharing one. And the generic cache layer is described as connecting the pieces and regularising business code, which is the difference between every team writing its own Caffeine wrapper and one shared component. There is also a dedicated module named l2cache-jd-hotkey, and the README notes that only open source users can register in the known users list, which is a small but telling sign of how the project is positioned. The last push was on 2026-07-26 and the most recent release is 2.0.1 from 2025-11-07, after 2.0.0 in November 2024 and 1.0.39 in April 2024.

Editorial conclusion

Adopt L2Cache when you run Spring services on Redis and want an in-process L1 in front of it, especially if you have hot keys that repeatedly hit the network tier, and you accept eventual consistency. Do not adopt it if your correctness requirements depend on strong consistency across nodes, since the design explicitly trades the C in CAP away and the consistency guarantee is a message notification best effort. Verify first which cache type your data should use, because the type is configurable per cache and switching it at runtime changes the consistency story, and confirm your L1 entry limit is set, since the README links to prior incidents of Caffeine OOM under load.

Frequently asked questions

What does L2Cache add on top of Caffeine and Redis?

It combines an in-memory L1 with Caffeine or Guava Cache and a centralised L2 with Redis, and adds automatic hot key detection, batch cache operations, a generic cache layer and dynamic cache type configuration.

Does L2Cache provide strong consistency across nodes?

No. The project states that it satisfies availability and partition tolerance and that consistency can only be eventually consistent, using message notification to keep first level caches in sync in a cluster.

Which cache implementations does L2Cache support?

Caffeine and Guava Cache for the in-memory first level, Redis for the centralised second level, and a Composite mode that uses both, selected through the configured cache type.

How is L2Cache distributed to Java projects?

It is a multi-module Maven project with l2cache-core, l2cache-spring-boot-starter, l2cache-example and l2cache-jd-hotkey modules, and the core artifact is published to Maven Central as io.github.ck-jesse l2cache-core under the Apache-2.0 licence.

Official sources

  1. ck-jesse/l2cache on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ck-jesse-l2cache.svg)](https://hysenlabs.com/projects/ck-jesse-l2cache)

Was this useful?