Redis Lazy‑Loading Cache Combined with Guava Local Cache – Design, Implementation, and Evaluation
This article explains how to reduce Redis read/write pressure by using a lazy‑loading cache pattern together with Guava local cache, provides Java code examples, discusses advantages and disadvantages, and shows practical scenarios such as device ID generation in high‑frequency streaming systems.
In many backend systems Redis is used as a high‑performance cache, but heavy read/write traffic can become a bottleneck; combining Redis with a local Guava cache can alleviate this pressure.
Design Example
The lazy‑loading cache stores data in Redis only when a precise query occurs, avoiding unnecessary caching of cold data. The workflow is illustrated in a diagram, and the approach is suitable when the total data volume is controllable.
Code Example – Lazy Loading Cache
public class XxLazyCache {
@Autowired
private RedisTemplate<String, Xx> redisTemplate;
@Autowired
private XxService xxService;
/**
* Query: if cache exists, return it; otherwise load from DB and cache it.
*/
public Xx getXx(int id) {
Xx xxCache = getXxFromCache(id);
if (xxCache != null) {
return xxCache; // guard clause
}
Xx xx = xxService.getXxById(id); // assume DB always has the record
setXxFromCache(xx);
return xx;
}
/**
* Delete cache after DB delete.
*/
public void deleteXxFromCache(long id) {
String key = "Xx:" + xx.getId();
redisTemplate.delete(key);
}
private void setXxFromCache(Xx xx) {
String key = "Xx:" + xx.getId();
redisTemplate.opsForValue().set(key, xx);
}
private Xx getXxFromCache(int id) {
String key = "Xx:" + id;
return redisTemplate.opsForValue().get(key);
}
}
public class XxServie {
@Autowired
private XxLazyCache xxLazyCache;
public Xx getXxById(long id) {
// DB query omitted
return xx;
}
public void updateXx(Xx xx) {
// update DB omitted
xxLazyCache.deleteXxFromCache(xx.getId());
}
public void deleteXx(long id) {
// delete DB omitted
xxLazyCache.deleteXxFromCache(id);
}
}
@Data
public class Xx {
private Long id;
// other fields omitted
}The above implementation demonstrates a simple lazy‑loading cache where data is cached only after a successful DB read, and cache entries are removed on updates or deletions.
Advantages
Minimizes cache size while satisfying precise‑query workloads.
Low intrusion on CRUD operations; cache is synchronized on delete.
Plug‑in friendly for legacy systems; no need to pre‑populate cache.
Disadvantages
Requires controlled data volume; not suitable for unbounded growth.
Less appropriate for global caching in micro‑service architectures.
Extended Scenario – Redis + Guava for Device Increment IDs
In a streaming data pipeline, each device needs a unique incremental number for partitioning; the solution uses a Redis atomic counter stored in a hash and a Guava cache to avoid frequent Redis hits.
public class DeviceIncCache {
private Cache<String, Integer> localCache = CacheBuilder.newBuilder()
.concurrencyLevel(16)
.initialCapacity(1000)
.maximumSize(10000)
.expireAfterAccess(1, TimeUnit.HOURS)
.build();
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
private static final String DEVICE_INC_COUNT = "device_inc_count";
private static final String DEVICE_INC_VALUE = "device_inc_value";
public int getInc(String deviceCode) {
Integer inc = localCache.getIfPresent(deviceCode);
if (inc != null) return inc;
inc = (Integer) redisTemplate.opsForHash().get(DEVICE_INC_VALUE, deviceCode);
if (inc == null) {
inc = redisTemplate.opsForValue().increment(DEVICE_INC_COUNT).intValue();
redisTemplate.opsForHash().put(DEVICE_INC_VALUE, deviceCode, inc);
}
localCache.put(deviceCode, inc);
return inc;
}
}This approach ensures that Redis handles the authoritative increment while Guava provides ultra‑fast local reads, reducing Redis load and keeping memory usage bounded.
Conclusion
Combining Redis with Guava local cache offers a balanced solution that minimizes memory consumption, provides high read performance, and fits precise‑query scenarios where data volume is manageable; however, it is less suitable for globally shared caches in large‑scale micro‑service environments.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
