Redis缓存三大问题原因分析及解决

515 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

简介

你们项目中使用到Redis了吗?我猜大部分都用了吧,没用到的就快要学一下了,为明年做下准备了。

image.png

缓存穿透

问题描述

缓存穿透是指网站攻击者或者其他一直访问不存在的数据,比如findById?id=-1,redis和数据库都没有,这时就会所有请求都打到数据库上,将数据库打崩,缓存也就失去了意义。

原因分析

  • 代码自身原因等
  • 其他网站恶意攻击等

如何解决

  • 缓存空对象(伪代码如下)
public UserDTO getUserById(Long id) {
    Object object = redisUtil.get(String.valueOf(id));
    if (Optional.ofNullable(object).isPresent()) {
        // 命中缓存
        if (object instanceof NullValueResultDto) {
            return null;
        }
        return (UserDto) object;
    }
    // 缓存没有命中,查询数据库放入缓存
    Optional<User> userOptional = userService.getById(id);
    userOptional.ifPresent(user -> {
        // 存入缓存
        redisUtil.set(String.valueOf(id), user);
    });
    return BeanUtils.copy2Bean(userOptional.orElseGet(() -> getAndSetNull(id)), UserDTO.class);
}

public User getAndSetNull(Long id) {
    // 空对象存入缓存
    redisUtil.set(String.valueOf(id), new NullValueResultDto());
    return null;
}

需要注意的是:会缓存大量的空对象,浪费内存,可以设置有效期

  • 布隆过滤器

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

以上引用自维基百科

这里简单提一嘴,有兴趣的可以了解一下或者后面可以专门出一篇讲一下。

tempImage1632656731471.jpeg

缓存击穿

问题描述

缓存击穿是指高并发情况下,缓存中没有但数据库有的数据(一般缓存时间到了)。这时,缓存中没有,大量用户请求打到了数据库上,把数据库打崩了。

原因分析

使用缓存时,获取不到的话会去数据库获取,可以看上面获取user的伪代码,获取到了后存到缓存。但由于是高并发下,访问量特别大,大量请求都去重建缓存,导致服务过慢。

如何解决

加个分布式锁,可以看下基于redis实现分布式锁的文章。

缓存雪崩

问题描述

大量key在存取时选择了相同的过期时间,导致大量key在某一时刻同时失效,请求全部打到数据库,造成数据库宕机。

原因分析

过多的缓存数据。

解决方案

不同的key设置不同的过期时间,尽量将其过期时间分布均匀。

总结

Redis缓存的三大问题知道了原因,怎么造成这三大问题的就会很老解决了,希望大家可以学到东西,欢迎评论想看什么样的文章。

tempImage1632656934854.gif