你不知道的redis二-缓存穿透和缓存雪崩问题及解决方案

缓存穿透是指存在用户不断地访问缓存和数据库中都没有的数据,从而导致数据库压力过大,从而可能引发服务处理缓慢甚至数据库崩溃等问题。如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者。

解决方式


解决方法很多,一般有以下几种方式

1、接口层校验

接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截,实现比较简单,但是只能拦截部分请求;

2、缓存空对象

从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。 这样可以防止攻击用户反复用同一个id暴力攻击,保护了后端数据源;

存在问题

1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;

2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

3、布隆过滤器

布隆过滤器是一个bit向量或者bit,如果我们要映射一个值到布隆过滤器中,我们要使用多个不同的哈希函数生成多个哈希值,并将每个生成的哈希值指向的bit位设置为1。

可以看到,不同的词对应的bit位置可能相同,当词很多的情况时,可能大部分bit位置都是1,这时查询商品1可能对应的位置都为1,只能说明商品1一词可能存在,不是一定存在的。

布隆过滤器的巨大用处就是,能够迅速判断一个元素是否在一个集合中。命中的可能存在,但不命中的话肯定不存在!

如Gava给我们提供的布隆过滤器,以下程序实现了生成1000000数据进行初始化布隆过滤器,过滤器误判率为3%,然后故意取10000个不存在布隆过滤器里的值,输出误判数量为300.

public class BloomFilterTest {

private static int size = 1000000;

private static BloomFilter bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.03);

public static void main(String[] args) {

for (int i = 0; i < size; i++) {

bloomFilter.put(i);

}

List list = new ArrayList(1000);

//故意取10000个不在过滤器里的值,看看有多少个会被认为在过滤器里

for (int i = size + 10000; i < size + 20000; i++) {

if (bloomFilter.mightContain(i)) {

list.add(i);

}

}

System.out.println(“误判的数量:” + list.size());

}

}

使用场景

  1. 网页爬虫对URL的去重,避免爬取相同的URL地址

  2. 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱(同理,垃圾短信)

  3. 缓存穿透,将所有可能存在的数据缓存放到布隆过滤器中,当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉。

优点

  1. 思路简单

  2. 保证一致性

  3. 性能强

缺点

  1. 代码复杂度增大

  2. 需要另外维护一个集合来存放缓存的Key

  3. 布隆过滤器不支持删值操作

  4. 初始化布隆过滤器和更新过滤器比较复杂

以下代码为redis中取不到值使用布隆过滤器方式判断数据是否存在数据库中,从而减少数据库访问IO。可以提供给大家参考。

三、缓存击穿问题

============

缓存击穿各位同学肯定经常和缓存穿透搞混,以为两个是同一个东西。因为我在面试中经常遇到这样的童鞋

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

解决方式


1、设置热点数据永远不过期。

嗯…场景有,但不科学。

2、互斥锁

当从缓存中没有取到数据时,那么为了防止大量数据打到数据库,我们可以通过加互斥锁的方式,进行限流。同一时间同一个数据只有一个请求可以进到数据库中拿到数据,当从数据库中拿到数据之后再将数据写回redis,其他阻塞的请求再从redis中取数据。以减少数据库压力。

互斥锁参考代码如下:

四、缓存雪崩

======

缓存雪崩是指缓存中数据大批量到过期时间,或者缓存层故障不可用,而查询数据量巨大。请求直接绕过缓存而直接请求数据库,引起数据库压力过大甚至down机。

解决方案


1、redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。可以参考redis的高可用部署以及哨兵机制。这个后面我们会讲

2、过期时间分布均匀

将redis过期时间不要设置统一时间点,比如过期时间为1个小时,可以随机上下增加5分钟随机数,保证数据不在同一时间点过期。

五、几种故障对比

故障类型redis是否存在数据数据库中是否存在数据key过期时间
缓存穿透
缓存击穿
缓存雪崩存在大批量key同一时间过期或者缓存层不可用
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

2021年Java中高级面试必备知识点总结

在这个部分总结了2019年到目前为止Java常见面试问题,取其面试核心编写成这份文档笔记,从中分析面试官的心理,摸清面试官的“套路”,可以说搞定90%以上的Java中高级面试没一点难度。

本节总结的内容涵盖了:消息队列、Redis缓存、分库分表、读写分离、设计高并发系统、分布式系统、高可用系统、SpringCloud微服务架构等一系列互联网主流高级技术的知识点。

目录:

(上述只是一个整体目录大纲,每个点里面都有如下所示的详细内容,从面试问题——分析面试官心理——剖析面试题——完美解答的一个过程)

部分内容:

对于每一个做技术的来说,学习是不能停止的,小编把2019年到目前为止Java的核心知识提炼出来了,无论你现在是处于什么阶段,如你所见,这份文档的内容无论是对于你找面试工作还是提升技术广度深度都是完美的。

不想被后浪淘汰的话,赶紧搞起来吧,高清完整版一共是888页,需要的话可以点赞+关注
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
3-1713519414215)]

对于每一个做技术的来说,学习是不能停止的,小编把2019年到目前为止Java的核心知识提炼出来了,无论你现在是处于什么阶段,如你所见,这份文档的内容无论是对于你找面试工作还是提升技术广度深度都是完美的。

不想被后浪淘汰的话,赶紧搞起来吧,高清完整版一共是888页,需要的话可以点赞+关注
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值