亿级流量下的缓存架构设计:Redis+Caffeine多级缓存实战
一、为什么需要多级缓存?
在亿级流量场景下,单纯依赖Redis会遇到三大瓶颈:
-
网络延迟:Redis远程访问通常需要1-5ms,QPS超过10万时成为瓶颈
-
资源成本:高频读取导致Redis CPU飙升至80%+
-
可用性风险:Redis集群故障时数据库直接被击穿
多级缓存架构正是破局关键:
客户端 浏览器本地缓存 CDN缓存 Nginx代理缓存 应用层Caffeine缓存 Redis分布式缓存 MySQL数据库
二、Caffeine+Redis核心架构设计
2.1 组件定位
组件 | 特性 | 适用场景 |
---|---|---|
Caffeine | 进程内缓存,访问速度纳秒级 | 高频热key(如秒杀商品) |
Redis | 分布式缓存,数据一致性高 | 全量数据缓存层 |
2.2 数据流转流程
java
public Product getProduct(Long id) {
// 1. 查询Caffeine
Product product = caffeineCache.getIfPresent(id);
if (product != null) {
return product;
}
// 2. 查询Redis(加分布式锁防击穿)
product = redisUtil.getWithLock("product:" + id,
lockKey -> loadFromDB(id), // 缓存未命中时查DB
3, TimeUnit.SECONDS);
// 3. 回填Caffeine(设置短过期时间)
caffeineCache.put(id, product, 30, TimeUnit.SECONDS);
return product;
}
三、关键技术实现
3.1 Caffeine高效配置
java
Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
.maximumSize(10_000) // 基于容量淘汰
.expireAfterWrite(30, TimeUnit.SECONDS) // 写后过期
.refreshAfterWrite(5, TimeUnit.SECONDS) // 异步刷新
.recordStats(); // 开启监控统计
LoadingCache<Long, Product> cache = caffeine.build(id -> {
// 异步加载函数(避免阻塞请求线程)
return loadFromRedis(id);
});
3.2 Redis热点Key处理
java
// 使用Redis集群分片+本地缓存分摊压力
public Product getProduct(Long id) {
int slot = id % 100; // 分片逻辑
String key = "product:" + slot + ":" + id;
// 先读本地缓存再读Redis...
}
3.3 缓存一致性保障
双删策略+版本号控制:
java
// 更新数据时
public void updateProduct(Product product) {
// 1. 更新数据库
db.update(product);
// 2. 删除Redis(失败重试3次)
redis.deleteWithRetry("product:"+product.getId());
// 3. 延迟500ms二次删除(防旧数据回填)
scheduleTask(() -> {
redis.delete("product:"+product.getId());
caffeine.invalidate(product.getId());
}, 500);
// 4. 设置版本号(解决并发更新)
redis.incr("version:"+product.getId());
}
四、性能压测对比
使用JMeter模拟100万QPS:
方案 | 平均响应时间 | Redis CPU | 数据库QPS |
---|---|---|---|
纯Redis | 12ms | 92% | 1800 |
多级缓存 | 1.8ms | 35% | <10 |
性能提升点:
-
99%的热点请求被Caffeine拦截
-
Redis负载下降60%
五、避坑指南
缓存污染问题
解决方案:Caffeine配置weakKeys+softValues
java
.weakKeys().softValues() // 启用弱引用+软引用
冷启动雪崩
预热方案:使用Guava的CacheLoader预加载热数据
java
CacheLoader.asyncReloading((id) -> loadFromDB(id), executor)
监控告警体系
java
// 通过Micrometer暴露指标
CaffeineMetrics.monitor(monitorRegistry, cache, "productCache");
监控看板需包含:
Caffeine命中率(Hit Ratio)
Redis连接池等待时间
六、扩展优化方向
热点探测:基于Redis的hotkeys命令动态识别热数据
分级存储:
-
L1:Caffeine(最新数据)
-
L2:Redis(全量数据)
-
L3:磁盘缓存(历史数据)
流量调度:根据用户IP路由到就近缓存节点