Skip to main content

Command Palette

Search for a command to run...

Cache 缓存三问

Published
1 min read
Cache 缓存三问

哎,我一个个人项目基本上都没有超过过两位数的QPS的人,面试你天天问我缓存的这些问题,你们礼貌吗?

缓存穿透

是啥

当请求试图访问一个在缓存和数据库都不存在的 key时,因为缓存没有,所以请求会直接转发到数据库上。然而数据库里面也没有这个 key 的记录,所以也就没有办法将这个数据写入缓存。当下一次同样的请求来了的时候,还是会转发到数据库上。

在这种情况下,缓存基本上也就没用了,就像被穿透了一样,请求每次都会走到数据库,流量大时数据库可能会扛不住。

咋整

  1. 对请求进行校验。一些明显不合理的参数直接前端过滤掉就好了,就不要让他进来了。
  2. 将空值缓存起来。查完之后,即使数据库没有这条记录,也把这个 key 和没有记录的情况缓存起来,这样下次就不会再查数据库了。
  3. 布隆过滤器。挺有意思的一个东西,值得单独讲讲。

布隆过滤器

介绍

布隆过滤器是一种概率型的数据结构,它可以告诉你某条记录一定不存在或者有可能存在。

正常我们考虑一个东西是否存在的判断的时候,大家下意识的反应可能会是哈希。但是哈希需要保存所有的对象,以便后续哈希冲突的时候找到特定的值。所以这也导致了哈希对大量数据的时候,内存是非常大的。

所以就有个小天才,尝试我们用多个哈希,来讲存在变成一个概率性的事情:

比如说:

  • 我们初始化一个值为0,容量为10的数组:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 然后设定两个不同的哈希方法:
  • 哈希1 => %5
  • 哈希2 => %7

现在,我们要存放 25 这个值,我们来看一下: 25:哈希1得到0,我们将0这个下标对应的值标记成1;哈希2得到4,我们将4这个下标对应的值修改成1;此时数组为:[1, 0, 0, 0, 1, 0, 0, 0, 0, 0]

当我们尝试获取25的时候,我们还是按照哈希1和哈希2,取得对应的下标,然后获取下标对应的值。如果下标的值一旦有0值,那么我们就认为这条记录是不存在的,但即便是都是1,也不一定百分百存在,为什么呢?

假设说我们现在要存 60 这个值,哈希1返回下标0,哈希2返回下标4,跟25是一样的结果。所以0和4的下标都是1的时候,可能是25带来的,也可以能是60带来的,这并不能确定,只能说,有概率存在。

但这个种并不是很精准筛查,在某些条件下,已经可以帮我们解决很大程度上的问题了。

哈希函数个数和布隆过滤器长度

布隆过滤器长度越长,误报概率越小。 哈希函数越多,一个值写的1也越多。

经典应用

用布隆过滤器减少磁盘 IO 和网络请求。

缓存击穿

是啥

某一热门的 key,在它过期的一瞬间,突然来了对它的好多请求。因为缓存已经过期了,所以这些请求就都转到了数据库,那个可怜的数据库又扛不住了。

咋整

  1. 加互斥锁。比如 Redis 分布式锁。
  2. 设置热点数据不过期。

缓存雪崩

是啥

大量热点 key 设置了相同的过期时间,在他们过期的一瞬间,出现了大量的请求,然后那个数据库应该更扛不住了。可以简单的理解,缓存击穿时一个 key,缓存雪崩是一堆 key。

咋整

基本上跟缓存击穿一样,无法时加了一个打散过期时间来处理一组的问题。

  1. 打散过期时间
  2. 加互斥锁
  3. 热点数据不过期
18 views

More from this blog

你愿意相信机器,还是人

春节回家,跟老爸一起刷了小破球2。 之后忽然想到了这个话题:你愿意相信机器,还是人 (一) 春节的时候,陪老爸去配了一副眼镜。 因为前不久我也正好花重金配了一副,在之前做了很多的功课,诸如眼镜的前倾角、面弯、镜间距、单眼瞳高、单眼瞳距之类的知识,了解了一些配镜过程中应该注意的事项。 老家是一个小县城,虽然眼镜店遍地都是,但专业的还真没几个。在配镜的过程中,能注意到这些细节的眼镜店几乎没有。蔡司专业的三维定位的仪器,更是全县城都没有。 当我提出需要仪器辅助测量这些参数的时候,一个配镜师傅跟我说,...

Jan 30, 20231 min read2
你愿意相信机器,还是人

C# 托管代码和垃圾回收

什么是托管代码 托管代码就是执行过程交由运行时管理的代码。运行时一般是指 CLR,公共语言运行时。 CLR 负责提取托管代码、将其编译成机器代码,然后执行它。除此之外,运行时还负责自动内存管理、安全边界、类型安全等等。 如果在 .Net 里面直接调用 C/C++ 程序,此类代码也称为“非托管代码”。在非托管代码的环境中,操作系统将程序加载进内存,然后调用内部的二进制代码,所以从内存管理到安全等诸多因素都需要程序员自己处理。 正常使用 .Net 编写的代码,会先编译成中间语言 (IL)。执行的...

Jun 14, 20221 min read43
C# 托管代码和垃圾回收

C# 发布-订阅模式

#CSharp #PubSub 发布-订阅模式 有些时候,发布-订阅模式也会被称为观察者模式,但其实,如果细分的话,这两者之间还是有些细微的差别的。 观察者模式是在主题者(Subject)内部,维护一个观察者(Observer)列表。然后当主题者的状态发生变更的时候,主题者可以通知观察者发生了变化。观察者可以主动访问主题者,获得变更。也可以在通知观察者的时候,直接带上变更的消息。 在观察者模式中,主题者和观察者还是存在部分的耦合。因此,我们可以引入一个中介,来接触这种耦合。 类 A(发布者)发生...

Jun 8, 20222 min read80
C# 发布-订阅模式

NightBack

7 posts