题目
高并发电商系统缓存架构设计
信息
- 类型:问答
- 难度:⭐⭐⭐
考点
缓存穿透防护,缓存一致性策略,热点数据处理,分布式锁应用,失效策略设计
快速回答
核心解决方案要点:
- 使用布隆过滤器+空值缓存解决缓存穿透
- 采用Cache-Aside模式配合双删策略保证一致性
- 热点数据使用本地二级缓存+Redis分布式锁防击穿
- 分层过期时间+随机抖动防止雪崩
- 读写分离+监控自动预热应对突发流量
问题场景
设计一个电商商品详情页缓存系统,要求:
1. QPS峰值10万+
2. 承受恶意请求攻击(如遍历商品ID)
3. 保证数据库与缓存强一致性
4. 处理热点商品(如秒杀商品)的并发访问
5. 防止缓存雪崩
架构设计
// 伪代码示例:缓存读取逻辑
public Product getProduct(String id) {
// 1. 布隆过滤器拦截
if (!bloomFilter.mightContain(id)) return null;
// 2. 查询Redis主缓存
Product product = redis.get(id);
if (product != null) {
if (product.isEmptyObject()) { // 空值标识
throw new ProductNotFoundException();
}
return product;
}
// 3. 获取分布式锁
Lock lock = redisson.getLock("lock:" + id);
if (lock.tryLock()) {
try {
// 4. 双重检查
product = redis.get(id);
if (product == null) {
// 5. 查询数据库
product = db.query("SELECT * FROM products WHERE id = ?", id);
// 6. 空结果处理
if (product == null) {
redis.setex(id, 300, "{empty}"); // 空值缓存
bloomFilter.put(id);
return null;
}
// 7. 写入缓存(设置分层过期时间)
redis.setex(id, baseTTL + random(600), product);
}
return product;
} finally {
lock.unlock();
}
} else {
// 8. 锁竞争时降级查询本地缓存
return localCache.get(id);
}
}关键技术点
1. 缓存穿透防护
- 布隆过滤器:预加载有效ID,拦截非法请求(误判率0.1%)
- 空值缓存:对不存在的键缓存特殊标记(TTL 5分钟)
2. 数据一致性保障
// 更新操作伪代码
public void updateProduct(Product product) {
// 1. 先更新数据库
db.update(product);
// 2. 删除Redis缓存
redis.del(product.id);
// 3. 延迟双删(1秒后二次删除)
delayQueue.add(() -> redis.del(product.id), 1000);
}- 双删策略:解决主从同步延迟导致的脏读
- 监听binlog:通过Canal同步数据库变更
3. 热点数据处理
- 二级本地缓存:Guava Cache存储热点商品(最大1万条)
- Key分片:hot:product_{id}分散到不同Redis节点
- 限流降级:Sentinel对热点ID实施QPS限制
4. 雪崩防护策略
- 分层TTL:基础过期时间+随机抖动(如3600±600秒)
- 永不过期设计:后台任务定期更新热点数据
- 熔断机制:缓存故障时直接访问数据库限流
最佳实践
- 监控体系:实时监控缓存命中率/慢查询/内存碎片率
- 动态预热:基于访问频率自动预热TOP100商品
- 多级缓存:浏览器CDN → Nginx缓存 → Redis → 本地缓存
- 集群部署:Redis Cluster分片部署(至少6节点)
常见错误
- 先删缓存后更新DB:导致读取旧数据回填缓存
- 无超时的分布式锁:引发死锁(必须设置leaseTime)
- 固定TTL集中失效:未添加随机抖动导致雪崩
- 缓存大对象:超过1MB对象需分片存储
扩展知识
- 缓存模式对比:Write-Through vs Write-Behind
- 一致性算法:Redis CRDTs解决多活数据中心同步
- 新型存储:Persistent Memory(PMEM)替代方案
- 热点探测:使用Redis的LFU算法识别热点Key