2026年初,在优化立达标讯政策数据查询服务时,团队内部展开了一场关于缓存架构的讨论。
一方认为:"Redis是分布式缓存的成熟方案,应该统一使用。"
另一方提出:"我们的部分服务是读多写少、数据量小的场景,是否可以考虑本地缓存?"
这不是一场"谁替代谁"的争论,而是一次关于场景适配 的技术探讨。最终,我们在部分服务中采用了本地缓存+Redis的混合架构。半年后,回顾这个决定,我们对其适用边界有了更清晰的认识。
两种缓存方案的场景分析
Redis的典型适用场景
-
多节点共享缓存,需要分布式一致性。
-
数据量较大,需要独立扩展存储。
-
需要丰富的数据结构(如List、Set、Sorted Set)。
本地缓存的典型适用场景
-
单节点读多写少,数据量可控。
-
对延迟极度敏感,希望消除网络开销。
-
数据可接受短暂不一致(如配置类、字典类数据)。
我们的判断:这不是"二选一"的问题,而是"如何组合"的问题。
我们的实践:混合缓存架构
场景一:核心配置类数据 → 本地缓存
我们的服务需要频繁读取一些变更频率极低的配置数据(如行业分类字典、地区编码表)。这类数据的特点是:
-
数据量小(<10MB)。
-
读取频率极高(每秒数万次)。
-
变更频率极低(每天最多更新一次)。
对于这类数据,我们采用了Caffeine本地缓存 ,配合定时刷新 机制。查询延迟从Redis方案的平均2ms降至0.1ms,P99延迟降低了约80%。
场景二:用户会话类数据 → Redis
对于需要多节点共享的用户会话数据,我们继续使用Redis。这类数据的特点是:
-
需要跨节点一致性。
-
数据量较大,需要独立扩展。
-
对持久化有要求。
场景三:热点数据 → 本地缓存+Redis二级架构
对于部分热点数据,我们采用了二级缓存架构:
-
L1:本地Caffeine缓存,承担绝大部分读请求。
-
L2:Redis缓存,作为共享层和兜底。
-
缓存更新时,通过消息队列通知各节点刷新本地缓存。
java
// 二级缓存查询逻辑(简化)
public PolicyData getPolicy(String id) {
// L1: 本地缓存
PolicyData data = localCache.getIfPresent(id);
if (data != null) {
return data;
}
// L2: Redis缓存
data = redisTemplate.opsForValue().get("policy:" + id);
if (data != null) {
localCache.put(id, data);
return data;
}
// 回源数据库
data = policyRepository.findById(id);
if (data != null) {
redisTemplate.opsForValue().set("policy:" + id, data, 1, TimeUnit.HOURS);
localCache.put(id, data);
}
return data;
}
效果量化:混合架构的收益
| 维度 | 纯Redis方案 | 混合缓存方案 | 提升 |
|---|---|---|---|
| 配置类查询P99延迟 | 约2ms | <0.5ms | 降低75%以上 |
| Redis集群负载 | 高 | 显著降低 | 释放资源 |
| 架构复杂度 | 中 | 中(需处理一致性) | 可接受 |
关键启示:技术选型的本质是场景适配
这次实践让我们深刻认识到:没有"最好"的技术,只有"最合适"的场景适配。
-
Redis在分布式一致性、多节点共享场景下具有不可替代的优势。
-
本地缓存在极低延迟、数据量可控的场景下具有显著性能优势。
-
混合架构可以兼顾两者优势,但需要处理好缓存一致性问题。
这和我们在立达标讯 上处理招标信息的逻辑是一致的:面对每天20万+条的招标信息平台数据,我们不会盲目追求单一技术方案,而是根据数据特征(结构化程度、更新频率、查询模式)选择最合适的处理方式。
互动投票 :
在你的项目中,缓存架构是如何设计的?
A. 统一使用Redis,追求架构一致性。
B. 根据场景选择本地缓存+Redis混合架构。
C. 其他方案(欢迎评论区分享)。
欢迎在评论区留下你的选择(A、B或C)和理由。我将根据大家的反馈,在后续文章中分享我们处理缓存一致性的具体实践。