300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 缓存击穿 穿透 雪崩_缓存雪崩 缓存穿透 缓存击穿的问题

缓存击穿 穿透 雪崩_缓存雪崩 缓存穿透 缓存击穿的问题

时间:2021-01-19 20:10:00

相关推荐

缓存击穿 穿透 雪崩_缓存雪崩 缓存穿透 缓存击穿的问题

背景

一直都是在有道上用markdown记笔记,前段时间突发奇想为什么不做一个公众号。

一来是记一些随笔,二来也是督促自己学习的一个方式。

本文有关于redis缓存、布隆过滤器和数据库模型方面的知识。

缓存雪崩、缓存穿透、缓存击穿的问题

缓存雪崩

  例:假如某东618做活动,00:00某个商铺有场秒杀活动,用户量大概在6 000左右,缓存每秒可以顶住5 000个请求。但是呢,在零点的时候也,缓存过期了,当时key全部失效,一下子6 000多个请求全部绕开缓存,直接打在数据库上(直接请求数据库了),这样用户体验就很差。原本从缓存中取数据,假设时间复杂度为O(1)。这样一来,用户就口吐芬芳,什么破系统,老娘不买了。

如图

处理缓存雪崩

我们可以在redis上设置key值随机过期,这样保证了同一时间,不会有大量的数据直接绕开缓存,访问数据库。

setRedis(key, value, exprTime + Math.random * num);

当然如果redis部署在集群上(redis cluster),热点数据分布在不同主机,同样可以避免同一时间key值失效。

缓存穿透、缓存击穿

缓存穿透

指的是原本数据库中没有数据,而用户不断访问,而缓存中无法读到对应的数据,直接访问数据库。这点,好比黑客攻击,假设我们Key值设定的是自增类型的int,从0到5 000,但是黑客一直拿着-1或者5 000+去访问,那肯定获取不到数据。不断的攻击导致服务器压力过大。

解决一:

我们在提供接口时,要有种“不信任的新”,要做鉴权校验,不符合的直接return。

还有一个是,当一个黑客每秒访问量超过预设的阈值,比如说某IP我设定它每秒钟访问10次,那么超过这个次数,我们就拉黑。

解决二:

布隆过滤器

简而言之,我们通过这种数据结构,去判断,当不存在的时候我们直接return,存在才去取数据。

在了解布隆过滤器之前,首先要知道HashMap,简单的来说,对于一个key:value,他们是怎样存储的呢?首先要准备一个哈希函数H()和一个散列表ht(数组),值是怎样存储的呢?

ht[H(key)] =value

当然,会出现一些哈希冲突的问题,这里就不深入了。

布隆过滤器的结构

布隆过滤器是一个bit向量或者说是bit数组,长成这样:

对于一个值,比如说0到 5 000要映射到布隆过滤器,我们需要使用多个Hash函数,生成hashCode,然后将值打在布隆过滤器上,存在的话,就将对应的bit设置成1,不存在设置成0。手写一个简单的布隆过滤器:

public class BloomFilter{

private BloomFilter( int initSize)

{

bitSet = new BitSet( initSize);

}

private static BitSet bitSet;

public static void Instance( int initSize = MAX_LEN)

{

if( 0 == bitSet.size() )

{

BloomFilter(initSize);

}

}

public void add( int key)

{

int location1 = Math.abs(hash1(key));

int location2 =Math.abs(hash2(key));

int location3 = Math.abs(hash3(key));

bitSet.set( location1);

bitSet.set( location2);

bitSet.set( location3);

}

public bool contains(int key)

{

int location1 = Math.abs(hash1(key));

int location2 = Math.abs(hash2(key));

int location3 = Math.abs(hash3(key));

return bitSet.get(location1) && bitSet.get(location2) && bitSet.get(location3) ;

}

private:

int hash1(Integer key)

{

return key.hashCode();

}

int hash2(Integer key)

{

return key.hashCode()^(key.hashCode()>>3);

}

int hash3(Integer key)

{

return key.hashCode()^(key.hashCode()>>16);

}

}

缓存击穿

就是对于某个热点数据,它的单个的并发量很大,突然间,他失效了,导致,很多数据一下子全部访问了数据库。

我们可以设置热点数据永不过期或者是加锁。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。