Redis缓存穿透问题解决

Redis缓存结构
在这里插入图片描述
什么是缓存穿透?
用户发送请求查询了一条数据,但是数据库并没有这条数据,数据库没有这条数据,缓存中肯定也没有这条数据,所以这个请求就越过了缓存去数据库中查询,数据库查询不到返回空值,而这种场景就称之为缓存穿透
缓存穿透的危害?
试想若是在高并发的情况下,缓存被穿透了导致数据库压力倍增甚至会出现宕机,若是被别人恶意访问缓存穿透又会造成怎样的后果?
解决方案
1.简单粗暴的方式:如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
2.布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
这里只介绍布隆过滤器感觉第一种方式没啥可介绍的

需要依赖

        <!-- guava 引入布隆过滤器 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0.1-jre</version>
        </dependency>

布隆过滤器代码

@Component
public class BloomFilterImpl {

    // 预存的数据个数 100w
    private static int size = 1000000;

    // 创建布隆过滤器的对象   3.容错率容错率越小越费性能越安全
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(),size,0.001);

    @Resource
    private UserDao userDao;

    /**
     * BloomFilterImpl对象被创建后,立即初始化的方法
     */
    @PostConstruct
    public void initData(){
        // 查询数据库中所有的id的值
        List<Integer> ids = userDao.selectAllIds();
        // 初始化到布隆过滤器中
        for (Integer id : ids) {
            bloomFilter.put(id);
        }
    }
    /**
     * 判断布隆过滤器中是否存在该id
     * @param id
     * @return
     */
    public boolean mightContain(Integer id){
        return bloomFilter.mightContain(id);
    }

}

使用方式就不介绍了,只需在访问数据库前判断布隆过滤器中是否存在即可

发布了60 篇原创文章 · 获赞 70 · 访问量 3194

猜你喜欢

转载自blog.csdn.net/qq_44784185/article/details/105217831