结论:使用布隆过滤器(Bloom Filter)结合Redis缓存是高效防穿透的核心策略。首先在Redis中预热布隆过滤器存储所有存在的博客ID,当请求不存在的ID时,布隆过滤器直接拦截返回空,避免查询数据库。代码实现:
// 初始化布隆过滤器
import redis.clients.jedis.Jedis;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
BloomFilter<Long> bloomFilter = BloomFilter.create(Funnels.longFunnel(), 10000000, 0.01);
Jedis jedis = new Jedis("localhost", 6379);
// 预热数据
bloomFilter.put(blogId);
jedis.setbit("bf:key", bloomFilter.mightContain(blogId) ? 1 : 0);
// 查询时检查
if (!bloomFilter.mightContain(blogId)) {
return null; // 直接返回,避免穿透
}
String cacheValue = jedis.get("blog:" + blogId);
if (cacheValue == null) {
// 双重检查,再查DB并回写
}此策略可将穿透率降至近零,适用于博客园高并发场景。布隆过滤器防穿透
缓存穿透是指查询一个根本不存在的数据,缓存没有命中,请求直接穿透到数据库造成压力。解决方案是使用布隆过滤器,布隆过滤器是一个高效的概率数据结构,可以判断一个元素是否可能存在于集合中。对于博客园这种海量博客ID的场景,预先将所有存在的博客ID插入布隆过滤器中,当查询时先查布隆过滤器,如果过滤器说不存在,就直接返回,不查询数据库和缓存。
SEO缓存+布隆
在博客园架构中,缓存穿透常见于恶意请求热门不存在的ID。高效策略是布隆过滤器+空值缓存。布隆过滤器判断存在性,命中则查Redis,未命中不查DB。同时,对于确实不存在的热点key,设置短时空值缓存(如5分钟)。实现代码:if (!bloom.mightContain(key)) return null; String val = redis.get(key); if(val==null){ synchronized(key){ val=redis.get(key); if(val==null){ val=db.get(key); if(val==null){ redis.setex(key+"_none",300,""); }else redis.setex(key,3600,val); } } } return val;
多层防护
Redis解决缓存穿透的最佳实践是布隆过滤器预过滤+缓存空值+热点key限流。博客园博客ID范围大,使用Guava的BloomFilter在Redis bitmap中存储。先初始化所有博客ID到bloom,然后请求流程:布隆不存在->返回空;布隆可能存在->查Redis,miss则查DB并set空值NX。同时用Lua脚本原子化操作避免并发穿透。性能提升90%以上。
实际案例
博客园曾遭遇缓存穿透攻击,大量不存在的blog/post/id请求打穿Redis直达SQL Server。引入Redis布隆过滤器后,效果立竿见影。部署步骤:1.用go-redis集成bloom模块;2.离线任务每天全量同步10万+博客ID到bloom;3.api层加判断:bloom.Test(key) false则http 404。穿透QPS从5000降到10,数据库CPU从90%降到20%。
代码实现详解
public String getBlog(Long id) { if (!bloomFilter.mightContain(id)) { return null; } String key = "blog:" + id; String value = redisTemplate.opsForValue().get(key); if (value == null) { value = blogDao.selectById(id); if (value != null) { redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS); } else { redisTemplate.opsForValue().set(key, "", 5, TimeUnit.MINUTES); // 空值缓存 } } return value; } 这个实现简单高效,完美解决穿透问题。
高级优化
除了布隆,对于博客园的分布式架构,还可结合一致性哈希+本地缓存双重防线。但核心仍是布隆+空值。注意布隆误判率控制在0.01%,容量预估1.5倍数据量,避免false positive导致无效DB查询。
FAQ
Q: 布隆过滤器会有误判吗?
A: 是的,有小概率false positive(说存在但实际不存在),但不会false negative,确保安全。
Q: 空值缓存时间怎么设?
A: 短时间如5-10分钟,避免缓存污染,同时防重复穿透。
Q: 博客园ID是连续的吗?
A: 否,使用Long类型布隆,预热全量数据。
Q: 如何更新布隆数据?
A: 新博客发布时实时put到布隆,定时全量重建。