读缓存:三问题总结

目录

读缓存时可能遇到的问题

一、缓存穿透:

1、问题出现场景

2、解决方案

①、布隆过滤器(Bloom Filter)

②、空值缓存

3、解决方案详细实践

①、BloomFilter

②、空值缓存:

二、缓存雪崩:

1、问题出现场景

2、解决方案

三、缓存击穿:

1、问题出现场景

2、解决方案


读缓存时可能遇到的问题

老生常谈的话题了,我这里写不是为了别的,也没有什么独特的见解(也许以后会有),我只是想总结下,整理下这部分的实践点,知识点,便于以后遇到此类问题,有个方便查看的解决方案。所以该文章会详细,全面的分析三读缓存的问题,并在下篇文章会详细分析写缓存的问题。

一、缓存穿透:

1、问题出现场景

什么情况下会出现缓存穿透呢?其实很多文章都会先说一下,嗯不例外我也会描述。哈哈哈!!!

缓存穿透是指查询一个一定不存在的数据,因为在缓存中也无该数据的信息,则系统会跳过缓存直接访问数据库,而对于高并发,高吞吐量的系统来说,无疑缓存失效了,同时对数据库上了一个高负载的debuff,显而易见的是数据库的读效率是比不过缓存的,那么很有可能造成数据库崩溃从而影响系统发生故障。当然,一般情况下,数据库的架构一般会搭建HA数据库,怕的就是恶意攻击。

2、解决方案

①、布隆过滤器(Bloom Filter)

②、空值缓存

3、解决方案详细实践

①、BloomFilter

  • 实现原理:假设有10条url,我们可以创建一个100bit位的数组,将URL分别用5个hash算法进行hash,将得到的5个hash值存入数组,如果我们需要判断url是否已经存在,则可通过一次判断url这5此hash算法的hash值是否为1,如果都为一,则说明url已存在,反之如果有任何一个不为1,那么说明这个url不存在。但是当数据量大到一定程度,会存在url的5次hash结果都为1,但其实该url不存在的场景。

读缓存:三问题总结_第1张图片

  • 算法核心思想:
    • 使用多个hash算法,从而减少hash的碰撞率,此处可以借鉴HashMap的hash算法;
    • 扩大数组范围,使hash值分布均匀,减少hash碰撞率。

②、空值缓存:

一种比较简单的解决办法,在第一次查询完不存在的数据后,将该key与对应的空值也放入缓存中,只不过设定为较短的失效时间,例如几分钟,这样则可以应对短时间的大量的该key攻击,设置为较短的失效时间是因为该值可能业务无关,存在意义不大,且该次的查询也未必是攻击者发起,无过久存储的必要,故可以早点失效。

二、缓存雪崩:

1、问题出现场景

在普通的缓存系统中一般例如redis、memcache等中,我们会给缓存设置一个失效时间,但是如果所有的缓存的失效时间相同,那么在同一时间失效时,所有系统的请求都会发送到数据库层,数据库可能无法承受如此大的压力导致系统崩溃。

2、解决方案

解决问题的方法,就是针对问题所在给出合理方案,雪崩的问题在于缓存失效的时间段,大量的并发对持久层造成了严重负载,导致系统崩溃,那么针对缓存失效,可以给出以下一些方案:

  • 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
  • 可以通过缓存reload机制,预先去更新缓存,在即将发生大并发访问前手动触发加载缓存。
  • 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
  • 做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。

三、缓存击穿:

1、问题出现场景

缓存击穿实际上是缓存雪崩的一个特例,大家使用过微博的应该都知道,微博有一个热门话题的功能,用户对于热门话题的搜索量往往在一些时刻会大大的高于其他话题,这种我们成为系统的“热点“,由于系统中对这些热点的数据缓存也存在失效时间,在热点的缓存到达失效时间时,此时可能依然会有大量的请求到达系统,没有了缓存层的保护,这些请求同样的会到达数据库从而可能引起故障。击穿与雪崩的区别即在于击穿是对于特定的热点数据来说,而雪崩是全部数据。

2、解决方案

 

你可能感兴趣的:(缓存)