redis穿透优化

一般缓存设计,首先从缓存查询数据,如果没有值,再从DB数据库获取数据,获取数据后写入缓存。缓存穿透是指查询一个不存在的数据,在缓存层DB数据库都不能查询到数据,最后返回空数据。如果该类情况的访问并发很高,或者受到恶意的攻击,可能会造成DB数据库宕机。

解决方案如下:

  • 缓存空对象

在DB数据库查询不到数据时,设置一个空对象,下次再次查询该对象时,则直接返回缓存对象。示例代码如下:

public Goods getById(Long id) {

        if (Objects.isNull(id)) {
            return null;
        }
        String key = GOODS + id;
        String goodsJson = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(goodsJson)) {
            return JSON.parseObject(goodsJson, Goods.class);
        }
        Goods goods = goodsMapper.selectByPrimaryKey(id);
        if (Objects.nonNull(goods)) {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(goods), RedisConst.DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
            return goods;
        } else {
            
            // 穿透优化
            redisTemplate.opsForValue().set(key, JSON.toJSONString(new Goods()), RedisConst.DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
            return null;
        }
    }

但是,缓存空对象存在一些问题。存储空对象后,需要更多的存储空间(如果是收到攻击,问题更严重)。可以设置一个失效时间,让其自动删除。缓存了空对象后,与DB数据库的数据会有一段数据不一致。例如,设置缓存的失效时间是2分钟,在这段时间内,数据库又添加了该id的数据,就出现了缓存和数据库数据不一致。此时,可以利用消息系统或者其他方式清理缓存。

  • 使用bloomfilter过滤器

对于数据实时性比较小的数据,可以使用bloomfilter过滤器存储数据库存在的数据,在缓存查询数据前,根据bloomfilter过滤器做一次校验。如果存在,在进行查询操作,反之,则直接返回空值。这在一定程度上减少了DB数据库的负载,起到了保护作用。由于bloomfilter没有删除操作,所以,该解决方案只适用于数据实时性不大,数据量大的情况。

发布了8 篇原创文章 · 获赞 0 · 访问量 3817

猜你喜欢

转载自blog.csdn.net/new_com/article/details/104251140
今日推荐